mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-27 01:02:48 +01:00
texture_cache: General Fixes
Fixed ASTC mipmaps loading Fixed alignment on openGL upload/download Fixed Block Height Calculation Removed unalign_height
This commit is contained in:
parent
c2ed348bdd
commit
7731a0e2d1
8 changed files with 170 additions and 47 deletions
|
@ -23,6 +23,7 @@ using VideoCore::MortonSwizzleMode;
|
||||||
|
|
||||||
using VideoCore::Surface::ComponentType;
|
using VideoCore::Surface::ComponentType;
|
||||||
using VideoCore::Surface::PixelFormat;
|
using VideoCore::Surface::PixelFormat;
|
||||||
|
using VideoCore::Surface::SurfaceCompression;
|
||||||
using VideoCore::Surface::SurfaceTarget;
|
using VideoCore::Surface::SurfaceTarget;
|
||||||
using VideoCore::Surface::SurfaceType;
|
using VideoCore::Surface::SurfaceType;
|
||||||
|
|
||||||
|
@ -242,10 +243,10 @@ void CachedSurface::DownloadTexture(std::vector<u8>& staging_buffer) {
|
||||||
MICROPROFILE_SCOPE(OpenGL_Texture_Download);
|
MICROPROFILE_SCOPE(OpenGL_Texture_Download);
|
||||||
|
|
||||||
// TODO(Rodrigo): Optimize alignment
|
// TODO(Rodrigo): Optimize alignment
|
||||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
|
||||||
SCOPE_EXIT({ glPixelStorei(GL_PACK_ROW_LENGTH, 0); });
|
SCOPE_EXIT({ glPixelStorei(GL_PACK_ROW_LENGTH, 0); });
|
||||||
|
|
||||||
for (u32 level = 0; level < params.num_levels; ++level) {
|
for (u32 level = 0; level < params.num_levels; ++level) {
|
||||||
|
glPixelStorei(GL_PACK_ALIGNMENT, std::min(8U, params.GetRowAlignment(level)));
|
||||||
glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(params.GetMipWidth(level)));
|
glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(params.GetMipWidth(level)));
|
||||||
const std::size_t mip_offset = params.GetHostMipmapLevelOffset(level);
|
const std::size_t mip_offset = params.GetHostMipmapLevelOffset(level);
|
||||||
if (is_compressed) {
|
if (is_compressed) {
|
||||||
|
@ -270,10 +271,14 @@ void CachedSurface::UploadTexture(std::vector<u8>& staging_buffer) {
|
||||||
|
|
||||||
void CachedSurface::UploadTextureMipmap(u32 level, std::vector<u8>& staging_buffer) {
|
void CachedSurface::UploadTextureMipmap(u32 level, std::vector<u8>& staging_buffer) {
|
||||||
// TODO(Rodrigo): Optimize alignment
|
// TODO(Rodrigo): Optimize alignment
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, std::min(8U, params.GetRowAlignment(level)));
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.GetMipWidth(level)));
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.GetMipWidth(level)));
|
||||||
|
|
||||||
const std::size_t mip_offset = params.GetHostMipmapLevelOffset(level);
|
auto compression_type = params.GetCompressionType();
|
||||||
|
|
||||||
|
const std::size_t mip_offset = compression_type == SurfaceCompression::Converted
|
||||||
|
? params.GetConvertedMipmapOffset(level)
|
||||||
|
: params.GetHostMipmapLevelOffset(level);
|
||||||
u8* buffer{staging_buffer.data() + mip_offset};
|
u8* buffer{staging_buffer.data() + mip_offset};
|
||||||
if (is_compressed) {
|
if (is_compressed) {
|
||||||
const auto image_size{static_cast<GLsizei>(params.GetHostMipmapSize(level))};
|
const auto image_size{static_cast<GLsizei>(params.GetHostMipmapSize(level))};
|
||||||
|
|
|
@ -197,7 +197,7 @@ inline constexpr std::array<u32, MaxPixelFormat> compression_factor_shift_table
|
||||||
*/
|
*/
|
||||||
inline constexpr u32 GetCompressionFactorShift(PixelFormat format) {
|
inline constexpr u32 GetCompressionFactorShift(PixelFormat format) {
|
||||||
DEBUG_ASSERT(format != PixelFormat::Invalid);
|
DEBUG_ASSERT(format != PixelFormat::Invalid);
|
||||||
DEBUG_ASSERT(static_cast<std::size_t>(format) < compression_factor_table.size());
|
DEBUG_ASSERT(static_cast<std::size_t>(format) < compression_factor_shift_table.size());
|
||||||
return compression_factor_shift_table[static_cast<std::size_t>(format)];
|
return compression_factor_shift_table[static_cast<std::size_t>(format)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,6 +438,88 @@ static constexpr u32 GetBytesPerPixel(PixelFormat pixel_format) {
|
||||||
return GetFormatBpp(pixel_format) / CHAR_BIT;
|
return GetFormatBpp(pixel_format) / CHAR_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class SurfaceCompression : u8 {
|
||||||
|
None = 0,
|
||||||
|
Compressed = 1,
|
||||||
|
Converted = 2,
|
||||||
|
Rearranged = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr std::array<SurfaceCompression, MaxPixelFormat> compression_type_table = {{
|
||||||
|
SurfaceCompression::None, // ABGR8U
|
||||||
|
SurfaceCompression::None, // ABGR8S
|
||||||
|
SurfaceCompression::None, // ABGR8UI
|
||||||
|
SurfaceCompression::None, // B5G6R5U
|
||||||
|
SurfaceCompression::None, // A2B10G10R10U
|
||||||
|
SurfaceCompression::None, // A1B5G5R5U
|
||||||
|
SurfaceCompression::None, // R8U
|
||||||
|
SurfaceCompression::None, // R8UI
|
||||||
|
SurfaceCompression::None, // RGBA16F
|
||||||
|
SurfaceCompression::None, // RGBA16U
|
||||||
|
SurfaceCompression::None, // RGBA16UI
|
||||||
|
SurfaceCompression::None, // R11FG11FB10F
|
||||||
|
SurfaceCompression::None, // RGBA32UI
|
||||||
|
SurfaceCompression::Compressed, // DXT1
|
||||||
|
SurfaceCompression::Compressed, // DXT23
|
||||||
|
SurfaceCompression::Compressed, // DXT45
|
||||||
|
SurfaceCompression::Compressed, // DXN1
|
||||||
|
SurfaceCompression::Compressed, // DXN2UNORM
|
||||||
|
SurfaceCompression::Compressed, // DXN2SNORM
|
||||||
|
SurfaceCompression::Compressed, // BC7U
|
||||||
|
SurfaceCompression::Compressed, // BC6H_UF16
|
||||||
|
SurfaceCompression::Compressed, // BC6H_SF16
|
||||||
|
SurfaceCompression::Converted, // ASTC_2D_4X4
|
||||||
|
SurfaceCompression::None, // BGRA8
|
||||||
|
SurfaceCompression::None, // RGBA32F
|
||||||
|
SurfaceCompression::None, // RG32F
|
||||||
|
SurfaceCompression::None, // R32F
|
||||||
|
SurfaceCompression::None, // R16F
|
||||||
|
SurfaceCompression::None, // R16U
|
||||||
|
SurfaceCompression::None, // R16S
|
||||||
|
SurfaceCompression::None, // R16UI
|
||||||
|
SurfaceCompression::None, // R16I
|
||||||
|
SurfaceCompression::None, // RG16
|
||||||
|
SurfaceCompression::None, // RG16F
|
||||||
|
SurfaceCompression::None, // RG16UI
|
||||||
|
SurfaceCompression::None, // RG16I
|
||||||
|
SurfaceCompression::None, // RG16S
|
||||||
|
SurfaceCompression::None, // RGB32F
|
||||||
|
SurfaceCompression::None, // RGBA8_SRGB
|
||||||
|
SurfaceCompression::None, // RG8U
|
||||||
|
SurfaceCompression::None, // RG8S
|
||||||
|
SurfaceCompression::None, // RG32UI
|
||||||
|
SurfaceCompression::None, // R32UI
|
||||||
|
SurfaceCompression::Converted, // ASTC_2D_8X8
|
||||||
|
SurfaceCompression::Converted, // ASTC_2D_8X5
|
||||||
|
SurfaceCompression::Converted, // ASTC_2D_5X4
|
||||||
|
SurfaceCompression::None, // BGRA8_SRGB
|
||||||
|
SurfaceCompression::Compressed, // DXT1_SRGB
|
||||||
|
SurfaceCompression::Compressed, // DXT23_SRGB
|
||||||
|
SurfaceCompression::Compressed, // DXT45_SRGB
|
||||||
|
SurfaceCompression::Compressed, // BC7U_SRGB
|
||||||
|
SurfaceCompression::Converted, // ASTC_2D_4X4_SRGB
|
||||||
|
SurfaceCompression::Converted, // ASTC_2D_8X8_SRGB
|
||||||
|
SurfaceCompression::Converted, // ASTC_2D_8X5_SRGB
|
||||||
|
SurfaceCompression::Converted, // ASTC_2D_5X4_SRGB
|
||||||
|
SurfaceCompression::Converted, // ASTC_2D_5X5
|
||||||
|
SurfaceCompression::Converted, // ASTC_2D_5X5_SRGB
|
||||||
|
SurfaceCompression::Converted, // ASTC_2D_10X8
|
||||||
|
SurfaceCompression::Converted, // ASTC_2D_10X8_SRGB
|
||||||
|
SurfaceCompression::None, // Z32F
|
||||||
|
SurfaceCompression::None, // Z16
|
||||||
|
SurfaceCompression::None, // Z24S8
|
||||||
|
SurfaceCompression::Rearranged, // S8Z24
|
||||||
|
SurfaceCompression::None, // Z32FS8
|
||||||
|
}};
|
||||||
|
|
||||||
|
static constexpr SurfaceCompression GetFormatCompressionType(PixelFormat format) {
|
||||||
|
if (format == PixelFormat::Invalid)
|
||||||
|
return SurfaceCompression::None;
|
||||||
|
|
||||||
|
ASSERT(static_cast<std::size_t>(format) < compression_type_table.size());
|
||||||
|
return compression_type_table[static_cast<std::size_t>(format)];
|
||||||
|
}
|
||||||
|
|
||||||
SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_type);
|
SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_type);
|
||||||
|
|
||||||
bool SurfaceTargetIsLayered(SurfaceTarget target);
|
bool SurfaceTargetIsLayered(SurfaceTarget target);
|
||||||
|
|
|
@ -17,6 +17,7 @@ MICROPROFILE_DEFINE(GPU_Flush_Texture, "GPU", "Texture Flush", MP_RGB(128, 192,
|
||||||
|
|
||||||
using Tegra::Texture::ConvertFromGuestToHost;
|
using Tegra::Texture::ConvertFromGuestToHost;
|
||||||
using VideoCore::MortonSwizzleMode;
|
using VideoCore::MortonSwizzleMode;
|
||||||
|
using VideoCore::Surface::SurfaceCompression;
|
||||||
|
|
||||||
SurfaceBaseImpl::SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params)
|
SurfaceBaseImpl::SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params)
|
||||||
: params{params}, mipmap_sizes(params.num_levels),
|
: params{params}, mipmap_sizes(params.num_levels),
|
||||||
|
@ -102,9 +103,20 @@ void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 level = 0; level < params.num_levels; ++level) {
|
auto compression_type = params.GetCompressionType();
|
||||||
const std::size_t host_offset{params.GetHostMipmapLevelOffset(level)};
|
if (compression_type == SurfaceCompression::None ||
|
||||||
ConvertFromGuestToHost(staging_buffer.data() + host_offset, params.pixel_format,
|
compression_type == SurfaceCompression::Compressed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (u32 level_up = params.num_levels; level_up > 0; --level_up) {
|
||||||
|
const u32 level = level_up - 1;
|
||||||
|
const std::size_t in_host_offset{params.GetHostMipmapLevelOffset(level)};
|
||||||
|
const std::size_t out_host_offset = compression_type == SurfaceCompression::Rearranged
|
||||||
|
? in_host_offset
|
||||||
|
: params.GetConvertedMipmapOffset(level);
|
||||||
|
u8* in_buffer = staging_buffer.data() + in_host_offset;
|
||||||
|
u8* out_buffer = staging_buffer.data() + out_host_offset;
|
||||||
|
ConvertFromGuestToHost(in_buffer, out_buffer, params.pixel_format,
|
||||||
params.GetMipWidth(level), params.GetMipHeight(level),
|
params.GetMipWidth(level), params.GetMipHeight(level),
|
||||||
params.GetMipDepth(level), true, true);
|
params.GetMipDepth(level), true, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,6 +93,10 @@ public:
|
||||||
return mipmap_sizes[level];
|
return mipmap_sizes[level];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsLinear() const {
|
||||||
|
return !params.is_tiled;
|
||||||
|
}
|
||||||
|
|
||||||
bool MatchFormat(VideoCore::Surface::PixelFormat pixel_format) const {
|
bool MatchFormat(VideoCore::Surface::PixelFormat pixel_format) const {
|
||||||
return params.pixel_format == pixel_format;
|
return params.pixel_format == pixel_format;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,17 +76,14 @@ SurfaceParams SurfaceParams::CreateForTexture(Core::System& system,
|
||||||
params.type = GetFormatType(params.pixel_format);
|
params.type = GetFormatType(params.pixel_format);
|
||||||
// TODO: on 1DBuffer we should use the tic info.
|
// TODO: on 1DBuffer we should use the tic info.
|
||||||
params.target = TextureType2SurfaceTarget(entry.GetType(), entry.IsArray());
|
params.target = TextureType2SurfaceTarget(entry.GetType(), entry.IsArray());
|
||||||
params.width =
|
params.width = config.tic.Width();
|
||||||
Common::AlignBits(config.tic.Width(), GetCompressionFactorShift(params.pixel_format));
|
params.height = config.tic.Height();
|
||||||
params.height =
|
|
||||||
Common::AlignBits(config.tic.Height(), GetCompressionFactorShift(params.pixel_format));
|
|
||||||
params.depth = config.tic.Depth();
|
params.depth = config.tic.Depth();
|
||||||
if (params.target == SurfaceTarget::TextureCubemap ||
|
if (params.target == SurfaceTarget::TextureCubemap ||
|
||||||
params.target == SurfaceTarget::TextureCubeArray) {
|
params.target == SurfaceTarget::TextureCubeArray) {
|
||||||
params.depth *= 6;
|
params.depth *= 6;
|
||||||
}
|
}
|
||||||
params.pitch = params.is_tiled ? 0 : config.tic.Pitch();
|
params.pitch = params.is_tiled ? 0 : config.tic.Pitch();
|
||||||
params.unaligned_height = config.tic.Height();
|
|
||||||
params.num_levels = config.tic.max_mip_level + 1;
|
params.num_levels = config.tic.max_mip_level + 1;
|
||||||
params.is_layered = params.IsLayered();
|
params.is_layered = params.IsLayered();
|
||||||
return params;
|
return params;
|
||||||
|
@ -108,7 +105,6 @@ SurfaceParams SurfaceParams::CreateForDepthBuffer(
|
||||||
params.type = GetFormatType(params.pixel_format);
|
params.type = GetFormatType(params.pixel_format);
|
||||||
params.width = zeta_width;
|
params.width = zeta_width;
|
||||||
params.height = zeta_height;
|
params.height = zeta_height;
|
||||||
params.unaligned_height = zeta_height;
|
|
||||||
params.target = SurfaceTarget::Texture2D;
|
params.target = SurfaceTarget::Texture2D;
|
||||||
params.depth = 1;
|
params.depth = 1;
|
||||||
params.pitch = 0;
|
params.pitch = 0;
|
||||||
|
@ -141,7 +137,6 @@ SurfaceParams SurfaceParams::CreateForFramebuffer(Core::System& system, std::siz
|
||||||
}
|
}
|
||||||
params.height = config.height;
|
params.height = config.height;
|
||||||
params.depth = 1;
|
params.depth = 1;
|
||||||
params.unaligned_height = config.height;
|
|
||||||
params.target = SurfaceTarget::Texture2D;
|
params.target = SurfaceTarget::Texture2D;
|
||||||
params.num_levels = 1;
|
params.num_levels = 1;
|
||||||
params.is_layered = false;
|
params.is_layered = false;
|
||||||
|
@ -164,7 +159,6 @@ SurfaceParams SurfaceParams::CreateForFermiCopySurface(
|
||||||
params.width = config.width;
|
params.width = config.width;
|
||||||
params.height = config.height;
|
params.height = config.height;
|
||||||
params.pitch = config.pitch;
|
params.pitch = config.pitch;
|
||||||
params.unaligned_height = config.height;
|
|
||||||
// TODO(Rodrigo): Try to guess the surface target from depth and layer parameters
|
// TODO(Rodrigo): Try to guess the surface target from depth and layer parameters
|
||||||
params.target = SurfaceTarget::Texture2D;
|
params.target = SurfaceTarget::Texture2D;
|
||||||
params.depth = 1;
|
params.depth = 1;
|
||||||
|
@ -185,18 +179,18 @@ bool SurfaceParams::IsLayered() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Auto block resizing algorithm from:
|
||||||
|
// https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nv50/nv50_miptree.c
|
||||||
u32 SurfaceParams::GetMipBlockHeight(u32 level) const {
|
u32 SurfaceParams::GetMipBlockHeight(u32 level) const {
|
||||||
// Auto block resizing algorithm from:
|
|
||||||
// https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nv50/nv50_miptree.c
|
|
||||||
if (level == 0) {
|
if (level == 0) {
|
||||||
return this->block_height;
|
return this->block_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 height{GetMipHeight(level)};
|
const u32 height_new{GetMipHeight(level)};
|
||||||
const u32 default_block_height{GetDefaultBlockHeight()};
|
const u32 default_block_height{GetDefaultBlockHeight()};
|
||||||
const u32 blocks_in_y{(height + default_block_height - 1) / default_block_height};
|
const u32 blocks_in_y{(height_new + default_block_height - 1) / default_block_height};
|
||||||
const u32 block_height = Common::Log2Ceil32(blocks_in_y);
|
const u32 block_height_new = Common::Log2Ceil32(blocks_in_y);
|
||||||
return std::clamp(block_height, 3U, 8U) - 3U;
|
return std::clamp(block_height_new, 3U, 7U) - 3U;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 SurfaceParams::GetMipBlockDepth(u32 level) const {
|
u32 SurfaceParams::GetMipBlockDepth(u32 level) const {
|
||||||
|
@ -207,12 +201,12 @@ u32 SurfaceParams::GetMipBlockDepth(u32 level) const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 depth{GetMipDepth(level)};
|
const u32 depth_new{GetMipDepth(level)};
|
||||||
const u32 block_depth = Common::Log2Ceil32(depth);
|
const u32 block_depth_new = Common::Log2Ceil32(depth_new);
|
||||||
if (block_depth > 4) {
|
if (block_depth_new > 4) {
|
||||||
return 5 - (GetMipBlockHeight(level) >= 2);
|
return 5 - (GetMipBlockHeight(level) >= 2);
|
||||||
}
|
}
|
||||||
return block_depth;
|
return block_depth_new;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t SurfaceParams::GetGuestMipmapLevelOffset(u32 level) const {
|
std::size_t SurfaceParams::GetGuestMipmapLevelOffset(u32 level) const {
|
||||||
|
@ -231,6 +225,14 @@ std::size_t SurfaceParams::GetHostMipmapLevelOffset(u32 level) const {
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t SurfaceParams::GetConvertedMipmapOffset(u32 level) const {
|
||||||
|
std::size_t offset = 0;
|
||||||
|
for (u32 i = 0; i < level; i++) {
|
||||||
|
offset += GetConvertedMipmapSize(i);
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t SurfaceParams::GetGuestMipmapSize(u32 level) const {
|
std::size_t SurfaceParams::GetGuestMipmapSize(u32 level) const {
|
||||||
return GetInnerMipmapMemorySize(level, false, false);
|
return GetInnerMipmapMemorySize(level, false, false);
|
||||||
}
|
}
|
||||||
|
@ -239,6 +241,14 @@ std::size_t SurfaceParams::GetHostMipmapSize(u32 level) const {
|
||||||
return GetInnerMipmapMemorySize(level, true, false) * GetNumLayers();
|
return GetInnerMipmapMemorySize(level, true, false) * GetNumLayers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t SurfaceParams::GetConvertedMipmapSize(u32 level) const {
|
||||||
|
constexpr std::size_t rgb8_bpp = 4ULL;
|
||||||
|
const std::size_t width_t = GetMipWidth(level);
|
||||||
|
const std::size_t height_t = GetMipHeight(level);
|
||||||
|
const std::size_t depth_t = is_layered ? depth : GetMipDepth(level);
|
||||||
|
return width_t * height_t * depth_t * rgb8_bpp;
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t SurfaceParams::GetGuestLayerSize() const {
|
std::size_t SurfaceParams::GetGuestLayerSize() const {
|
||||||
return GetLayerSize(false, false);
|
return GetLayerSize(false, false);
|
||||||
}
|
}
|
||||||
|
@ -287,12 +297,10 @@ std::size_t SurfaceParams::Hash() const {
|
||||||
|
|
||||||
bool SurfaceParams::operator==(const SurfaceParams& rhs) const {
|
bool SurfaceParams::operator==(const SurfaceParams& rhs) const {
|
||||||
return std::tie(is_tiled, block_width, block_height, block_depth, tile_width_spacing, width,
|
return std::tie(is_tiled, block_width, block_height, block_depth, tile_width_spacing, width,
|
||||||
height, depth, pitch, unaligned_height, num_levels, pixel_format,
|
height, depth, pitch, num_levels, pixel_format, component_type, type, target) ==
|
||||||
component_type, type, target) ==
|
|
||||||
std::tie(rhs.is_tiled, rhs.block_width, rhs.block_height, rhs.block_depth,
|
std::tie(rhs.is_tiled, rhs.block_width, rhs.block_height, rhs.block_depth,
|
||||||
rhs.tile_width_spacing, rhs.width, rhs.height, rhs.depth, rhs.pitch,
|
rhs.tile_width_spacing, rhs.width, rhs.height, rhs.depth, rhs.pitch,
|
||||||
rhs.unaligned_height, rhs.num_levels, rhs.pixel_format, rhs.component_type,
|
rhs.num_levels, rhs.pixel_format, rhs.component_type, rhs.type, rhs.target);
|
||||||
rhs.type, rhs.target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SurfaceParams::TargetName() const {
|
std::string SurfaceParams::TargetName() const {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
|
#include "common/bit_util.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/engines/fermi_2d.h"
|
#include "video_core/engines/fermi_2d.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
|
@ -16,6 +17,8 @@
|
||||||
|
|
||||||
namespace VideoCommon {
|
namespace VideoCommon {
|
||||||
|
|
||||||
|
using VideoCore::Surface::SurfaceCompression;
|
||||||
|
|
||||||
class SurfaceParams {
|
class SurfaceParams {
|
||||||
public:
|
public:
|
||||||
/// Creates SurfaceCachedParams from a texture configuration.
|
/// Creates SurfaceCachedParams from a texture configuration.
|
||||||
|
@ -50,17 +53,12 @@ public:
|
||||||
|
|
||||||
std::size_t GetHostSizeInBytes() const {
|
std::size_t GetHostSizeInBytes() const {
|
||||||
std::size_t host_size_in_bytes;
|
std::size_t host_size_in_bytes;
|
||||||
if (IsPixelFormatASTC(pixel_format)) {
|
if (GetCompressionType() == SurfaceCompression::Converted) {
|
||||||
constexpr std::size_t rgb8_bpp = 4ULL;
|
constexpr std::size_t rgb8_bpp = 4ULL;
|
||||||
// ASTC is uncompressed in software, in emulated as RGBA8
|
// ASTC is uncompressed in software, in emulated as RGBA8
|
||||||
host_size_in_bytes = 0;
|
host_size_in_bytes = 0;
|
||||||
for (u32 level = 0; level < num_levels; ++level) {
|
for (u32 level = 0; level < num_levels; ++level) {
|
||||||
const std::size_t width =
|
host_size_in_bytes += GetConvertedMipmapSize(level);
|
||||||
Common::AlignUp(GetMipWidth(level), GetDefaultBlockWidth());
|
|
||||||
const std::size_t height =
|
|
||||||
Common::AlignUp(GetMipHeight(level), GetDefaultBlockHeight());
|
|
||||||
const std::size_t depth = is_layered ? this->depth : GetMipDepth(level);
|
|
||||||
host_size_in_bytes += width * height * depth * rgb8_bpp;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
host_size_in_bytes = GetInnerMemorySize(true, false, false);
|
host_size_in_bytes = GetInnerMemorySize(true, false, false);
|
||||||
|
@ -93,6 +91,12 @@ public:
|
||||||
/// Returns the block depth of a given mipmap level.
|
/// Returns the block depth of a given mipmap level.
|
||||||
u32 GetMipBlockDepth(u32 level) const;
|
u32 GetMipBlockDepth(u32 level) const;
|
||||||
|
|
||||||
|
u32 GetRowAlignment(u32 level) const {
|
||||||
|
const u32 bpp =
|
||||||
|
GetCompressionType() == SurfaceCompression::Converted ? 4 : GetBytesPerPixel();
|
||||||
|
return 1U << Common::CountTrailingZeroes32(GetMipWidth(level) * bpp);
|
||||||
|
}
|
||||||
|
|
||||||
// Helper used for out of class size calculations
|
// Helper used for out of class size calculations
|
||||||
static std::size_t AlignLayered(const std::size_t out_size, const u32 block_height,
|
static std::size_t AlignLayered(const std::size_t out_size, const u32 block_height,
|
||||||
const u32 block_depth) {
|
const u32 block_depth) {
|
||||||
|
@ -106,12 +110,16 @@ public:
|
||||||
/// Returns the offset in bytes in host memory (linear) of a given mipmap level.
|
/// Returns the offset in bytes in host memory (linear) of a given mipmap level.
|
||||||
std::size_t GetHostMipmapLevelOffset(u32 level) const;
|
std::size_t GetHostMipmapLevelOffset(u32 level) const;
|
||||||
|
|
||||||
|
std::size_t GetConvertedMipmapOffset(u32 level) const;
|
||||||
|
|
||||||
/// Returns the size in bytes in guest memory of a given mipmap level.
|
/// Returns the size in bytes in guest memory of a given mipmap level.
|
||||||
std::size_t GetGuestMipmapSize(u32 level) const;
|
std::size_t GetGuestMipmapSize(u32 level) const;
|
||||||
|
|
||||||
/// Returns the size in bytes in host memory (linear) of a given mipmap level.
|
/// Returns the size in bytes in host memory (linear) of a given mipmap level.
|
||||||
std::size_t GetHostMipmapSize(u32 level) const;
|
std::size_t GetHostMipmapSize(u32 level) const;
|
||||||
|
|
||||||
|
std::size_t GetConvertedMipmapSize(u32 level) const;
|
||||||
|
|
||||||
/// Returns the size of a layer in bytes in guest memory.
|
/// Returns the size of a layer in bytes in guest memory.
|
||||||
std::size_t GetGuestLayerSize() const;
|
std::size_t GetGuestLayerSize() const;
|
||||||
|
|
||||||
|
@ -141,6 +149,10 @@ public:
|
||||||
/// Returns true if the pixel format is a depth and/or stencil format.
|
/// Returns true if the pixel format is a depth and/or stencil format.
|
||||||
bool IsPixelFormatZeta() const;
|
bool IsPixelFormatZeta() const;
|
||||||
|
|
||||||
|
SurfaceCompression GetCompressionType() const {
|
||||||
|
return VideoCore::Surface::GetFormatCompressionType(pixel_format);
|
||||||
|
}
|
||||||
|
|
||||||
std::string TargetName() const;
|
std::string TargetName() const;
|
||||||
|
|
||||||
bool is_tiled;
|
bool is_tiled;
|
||||||
|
@ -154,7 +166,6 @@ public:
|
||||||
u32 height;
|
u32 height;
|
||||||
u32 depth;
|
u32 depth;
|
||||||
u32 pitch;
|
u32 pitch;
|
||||||
u32 unaligned_height;
|
|
||||||
u32 num_levels;
|
u32 num_levels;
|
||||||
VideoCore::Surface::PixelFormat pixel_format;
|
VideoCore::Surface::PixelFormat pixel_format;
|
||||||
VideoCore::Surface::ComponentType component_type;
|
VideoCore::Surface::ComponentType component_type;
|
||||||
|
|
|
@ -62,19 +62,19 @@ static void ConvertZ24S8ToS8Z24(u8* data, u32 width, u32 height) {
|
||||||
SwapS8Z24ToZ24S8<true>(data, width, height);
|
SwapS8Z24ToZ24S8<true>(data, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConvertFromGuestToHost(u8* data, PixelFormat pixel_format, u32 width, u32 height, u32 depth,
|
void ConvertFromGuestToHost(u8* in_data, u8* out_data, PixelFormat pixel_format, u32 width,
|
||||||
bool convert_astc, bool convert_s8z24) {
|
u32 height, u32 depth, bool convert_astc, bool convert_s8z24) {
|
||||||
if (convert_astc && IsPixelFormatASTC(pixel_format)) {
|
if (convert_astc && IsPixelFormatASTC(pixel_format)) {
|
||||||
// Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC.
|
// Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC.
|
||||||
u32 block_width{};
|
u32 block_width{};
|
||||||
u32 block_height{};
|
u32 block_height{};
|
||||||
std::tie(block_width, block_height) = GetASTCBlockSize(pixel_format);
|
std::tie(block_width, block_height) = GetASTCBlockSize(pixel_format);
|
||||||
const std::vector<u8> rgba8_data =
|
const std::vector<u8> rgba8_data = Tegra::Texture::ASTC::Decompress(
|
||||||
Tegra::Texture::ASTC::Decompress(data, width, height, depth, block_width, block_height);
|
in_data, width, height, depth, block_width, block_height);
|
||||||
std::copy(rgba8_data.begin(), rgba8_data.end(), data);
|
std::copy(rgba8_data.begin(), rgba8_data.end(), out_data);
|
||||||
|
|
||||||
} else if (convert_s8z24 && pixel_format == PixelFormat::S8Z24) {
|
} else if (convert_s8z24 && pixel_format == PixelFormat::S8Z24) {
|
||||||
Tegra::Texture::ConvertS8Z24ToZ24S8(data, width, height);
|
Tegra::Texture::ConvertS8Z24ToZ24S8(in_data, width, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,4 +90,4 @@ void ConvertFromHostToGuest(u8* data, PixelFormat pixel_format, u32 width, u32 h
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Tegra::Texture
|
} // namespace Tegra::Texture
|
||||||
|
|
|
@ -12,10 +12,11 @@ enum class PixelFormat;
|
||||||
|
|
||||||
namespace Tegra::Texture {
|
namespace Tegra::Texture {
|
||||||
|
|
||||||
void ConvertFromGuestToHost(u8* data, VideoCore::Surface::PixelFormat pixel_format, u32 width,
|
void ConvertFromGuestToHost(u8* in_data, u8* out_data, VideoCore::Surface::PixelFormat pixel_format,
|
||||||
u32 height, u32 depth, bool convert_astc, bool convert_s8z24);
|
u32 width, u32 height, u32 depth, bool convert_astc,
|
||||||
|
bool convert_s8z24);
|
||||||
|
|
||||||
void ConvertFromHostToGuest(u8* data, VideoCore::Surface::PixelFormat pixel_format, u32 width,
|
void ConvertFromHostToGuest(u8* data, VideoCore::Surface::PixelFormat pixel_format, u32 width,
|
||||||
u32 height, u32 depth, bool convert_astc, bool convert_s8z24);
|
u32 height, u32 depth, bool convert_astc, bool convert_s8z24);
|
||||||
|
|
||||||
} // namespace Tegra::Texture
|
} // namespace Tegra::Texture
|
||||||
|
|
Loading…
Reference in a new issue