From ddfbe0b58d856ae4a62683943cb35c2ae8f13b95 Mon Sep 17 00:00:00 2001 From: FernandoS27 Date: Fri, 16 Nov 2018 13:01:54 -0400 Subject: [PATCH] Implemented Tile Width Spacing --- src/video_core/engines/fermi_2d.cpp | 4 +-- src/video_core/morton.cpp | 25 ++++++++++--------- src/video_core/morton.h | 6 ++--- .../renderer_opengl/gl_rasterizer_cache.cpp | 12 ++++++--- .../renderer_opengl/gl_rasterizer_cache.h | 13 +++++++--- src/video_core/textures/decoders.cpp | 22 +++++++++------- src/video_core/textures/decoders.h | 7 +++--- src/video_core/textures/texture.h | 2 ++ 8 files changed, 55 insertions(+), 36 deletions(-) diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp index 74e44c7fe5..ee8ebf678d 100644 --- a/src/video_core/engines/fermi_2d.cpp +++ b/src/video_core/engines/fermi_2d.cpp @@ -68,13 +68,13 @@ void Fermi2D::HandleSurfaceCopy() { Texture::CopySwizzledData(regs.src.width, regs.src.height, regs.src.depth, src_bytes_per_pixel, dst_bytes_per_pixel, src_buffer, dst_buffer, true, regs.src.BlockHeight(), - regs.src.BlockDepth()); + regs.src.BlockDepth(), 0); } else { // If the input is linear and the output is tiled, swizzle the input and copy it over. Texture::CopySwizzledData(regs.src.width, regs.src.height, regs.src.depth, src_bytes_per_pixel, dst_bytes_per_pixel, dst_buffer, src_buffer, false, regs.dst.BlockHeight(), - regs.dst.BlockDepth()); + regs.dst.BlockDepth(), 0); } } } diff --git a/src/video_core/morton.cpp b/src/video_core/morton.cpp index f14abba7df..1cf27ee258 100644 --- a/src/video_core/morton.cpp +++ b/src/video_core/morton.cpp @@ -16,12 +16,12 @@ namespace VideoCore { using Surface::GetBytesPerPixel; using Surface::PixelFormat; -using MortonCopyFn = void (*)(u32, u32, u32, u32, u32, u8*, std::size_t, VAddr); +using MortonCopyFn = void (*)(u32, u32, u32, u32, u32, u32, u8*, std::size_t, VAddr); using ConversionArray = std::array; template static void MortonCopy(u32 stride, u32 block_height, u32 height, u32 block_depth, u32 depth, - u8* buffer, std::size_t buffer_size, VAddr addr) { + u32 tile_width_spacing, u8* buffer, std::size_t buffer_size, VAddr addr) { constexpr u32 bytes_per_pixel = GetBytesPerPixel(format); // With the BCn formats (DXT and DXN), each 4x4 tile is swizzled instead of just individual @@ -31,12 +31,13 @@ static void MortonCopy(u32 stride, u32 block_height, u32 height, u32 block_depth if constexpr (morton_to_linear) { Tegra::Texture::UnswizzleTexture(buffer, addr, tile_size_x, tile_size_y, bytes_per_pixel, - stride, height, depth, block_height, block_depth); + stride, height, depth, block_height, block_depth, + tile_width_spacing); } else { - Tegra::Texture::CopySwizzledData((stride + tile_size_x - 1) / tile_size_x, - (height + tile_size_y - 1) / tile_size_y, depth, - bytes_per_pixel, bytes_per_pixel, Memory::GetPointer(addr), - buffer, false, block_height, block_depth); + Tegra::Texture::CopySwizzledData( + (stride + tile_size_x - 1) / tile_size_x, (height + tile_size_y - 1) / tile_size_y, + depth, bytes_per_pixel, bytes_per_pixel, Memory::GetPointer(addr), buffer, false, + block_height, block_depth, tile_width_spacing); } } @@ -325,11 +326,11 @@ static u32 GetMortonOffset128(u32 x, u32 y, u32 bytes_per_pixel) { } void MortonSwizzle(MortonSwizzleMode mode, Surface::PixelFormat format, u32 stride, - u32 block_height, u32 height, u32 block_depth, u32 depth, u8* buffer, - std::size_t buffer_size, VAddr addr) { + u32 block_height, u32 height, u32 block_depth, u32 depth, u32 tile_width_spacing, + u8* buffer, std::size_t buffer_size, VAddr addr) { - GetSwizzleFunction(mode, format)(stride, block_height, height, block_depth, depth, buffer, - buffer_size, addr); + GetSwizzleFunction(mode, format)(stride, block_height, height, block_depth, depth, + tile_width_spacing, buffer, buffer_size, addr); } void MortonCopyPixels128(u32 width, u32 height, u32 bytes_per_pixel, u32 linear_bytes_per_pixel, @@ -350,4 +351,4 @@ void MortonCopyPixels128(u32 width, u32 height, u32 bytes_per_pixel, u32 linear_ } } -} // namespace VideoCore \ No newline at end of file +} // namespace VideoCore diff --git a/src/video_core/morton.h b/src/video_core/morton.h index b9b9eca86d..065f59ce32 100644 --- a/src/video_core/morton.h +++ b/src/video_core/morton.h @@ -12,10 +12,10 @@ namespace VideoCore { enum class MortonSwizzleMode { MortonToLinear, LinearToMorton }; void MortonSwizzle(MortonSwizzleMode mode, VideoCore::Surface::PixelFormat format, u32 stride, - u32 block_height, u32 height, u32 block_depth, u32 depth, u8* buffer, - std::size_t buffer_size, VAddr addr); + u32 block_height, u32 height, u32 block_depth, u32 depth, u32 tile_width_spacing, + u8* buffer, std::size_t buffer_size, VAddr addr); void MortonCopyPixels128(u32 width, u32 height, u32 bytes_per_pixel, u32 linear_bytes_per_pixel, u8* morton_data, u8* linear_data, bool morton_to_linear); -} // namespace VideoCore \ No newline at end of file +} // namespace VideoCore diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index d458f77e46..dde2f468d4 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -97,6 +97,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only, params.block_width = params.is_tiled ? config.tic.BlockWidth() : 0, params.block_height = params.is_tiled ? config.tic.BlockHeight() : 0, params.block_depth = params.is_tiled ? config.tic.BlockDepth() : 0, + params.tile_width_spacing = params.is_tiled ? (1 << config.tic.tile_width_spacing.Value()) : 1; params.srgb_conversion = config.tic.IsSrgbConversionEnabled(); params.pixel_format = PixelFormatFromTextureFormat(config.tic.format, config.tic.r_type.Value(), params.srgb_conversion); @@ -162,6 +163,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only, params.block_width = 1 << config.memory_layout.block_width; params.block_height = 1 << config.memory_layout.block_height; params.block_depth = 1 << config.memory_layout.block_depth; + params.tile_width_spacing = 1; params.pixel_format = PixelFormatFromRenderTargetFormat(config.format); params.srgb_conversion = config.format == Tegra::RenderTargetFormat::BGRA8_SRGB || config.format == Tegra::RenderTargetFormat::RGBA8_SRGB; @@ -197,6 +199,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only, params.block_width = 1 << std::min(block_width, 5U); params.block_height = 1 << std::min(block_height, 5U); params.block_depth = 1 << std::min(block_depth, 5U); + params.tile_width_spacing = 1; params.pixel_format = PixelFormatFromDepthFormat(format); params.component_type = ComponentTypeFromDepthFormat(format); params.type = GetFormatType(params.pixel_format); @@ -223,6 +226,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only, params.block_width = params.is_tiled ? std::min(config.BlockWidth(), 32U) : 0, params.block_height = params.is_tiled ? std::min(config.BlockHeight(), 32U) : 0, params.block_depth = params.is_tiled ? std::min(config.BlockDepth(), 32U) : 0, + params.tile_width_spacing = 1; params.pixel_format = PixelFormatFromRenderTargetFormat(config.format); params.srgb_conversion = config.format == Tegra::RenderTargetFormat::BGRA8_SRGB || config.format == Tegra::RenderTargetFormat::RGBA8_SRGB; @@ -387,8 +391,8 @@ void SwizzleFunc(const MortonSwizzleMode& mode, const SurfaceParams& params, for (u32 i = 0; i < params.depth; i++) { MortonSwizzle(mode, params.pixel_format, params.MipWidth(mip_level), params.MipBlockHeight(mip_level), params.MipHeight(mip_level), - params.MipBlockDepth(mip_level), 1, gl_buffer.data() + offset_gl, gl_size, - params.addr + offset); + params.MipBlockDepth(mip_level), params.tile_width_spacing, 1, + gl_buffer.data() + offset_gl, gl_size, params.addr + offset); offset += layer_size; offset_gl += gl_size; } @@ -396,8 +400,8 @@ void SwizzleFunc(const MortonSwizzleMode& mode, const SurfaceParams& params, const u64 offset = params.GetMipmapLevelOffset(mip_level); MortonSwizzle(mode, params.pixel_format, params.MipWidth(mip_level), params.MipBlockHeight(mip_level), params.MipHeight(mip_level), - params.MipBlockDepth(mip_level), depth, gl_buffer.data(), gl_buffer.size(), - params.addr + offset); + params.MipBlockDepth(mip_level), depth, params.tile_width_spacing, + gl_buffer.data(), gl_buffer.size(), params.addr + offset); } } diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 9ac79c5a4f..c710aa245a 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -196,9 +196,15 @@ struct SurfaceParams { /// Checks if surfaces are compatible for caching bool IsCompatibleSurface(const SurfaceParams& other) const { - return std::tie(pixel_format, type, width, height, target, depth) == - std::tie(other.pixel_format, other.type, other.width, other.height, other.target, - other.depth); + if (std::tie(pixel_format, type, width, height, target, depth, is_tiled) == + std::tie(other.pixel_format, other.type, other.width, other.height, other.target, + other.depth, other.is_tiled)) { + if (!is_tiled) + return true; + return std::tie(block_height, block_depth, tile_width_spacing) == + std::tie(other.block_height, other.block_depth, other.tile_width_spacing); + } + return false; } /// Initializes parameters for caching, should be called after everything has been initialized @@ -208,6 +214,7 @@ struct SurfaceParams { u32 block_width; u32 block_height; u32 block_depth; + u32 tile_width_spacing; PixelFormat pixel_format; ComponentType component_type; SurfaceType type; diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index 7eabd34f17..bbae9285f4 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp @@ -127,7 +127,8 @@ void FastProcessBlock(u8* const swizzled_data, u8* const unswizzled_data, const template void SwizzledData(u8* const swizzled_data, u8* const unswizzled_data, const bool unswizzle, const u32 width, const u32 height, const u32 depth, const u32 bytes_per_pixel, - const u32 out_bytes_per_pixel, const u32 block_height, const u32 block_depth) { + const u32 out_bytes_per_pixel, const u32 block_height, const u32 block_depth, + const u32 width_spacing) { auto div_ceil = [](const u32 x, const u32 y) { return ((x + y - 1) / y); }; const u32 stride_x = width * out_bytes_per_pixel; const u32 layer_z = height * stride_x; @@ -137,7 +138,8 @@ void SwizzledData(u8* const swizzled_data, u8* const unswizzled_data, const bool const u32 block_x_elements = gob_elements_x; const u32 block_y_elements = gob_elements_y * block_height; const u32 block_z_elements = gob_elements_z * block_depth; - const u32 blocks_on_x = div_ceil(width, block_x_elements); + const u32 aligned_width = Common::AlignUp(width, gob_elements_x * width_spacing); + const u32 blocks_on_x = div_ceil(aligned_width, block_x_elements); const u32 blocks_on_y = div_ceil(height, block_y_elements); const u32 blocks_on_z = div_ceil(depth, block_z_elements); const u32 xy_block_size = gob_size * block_height; @@ -169,13 +171,15 @@ void SwizzledData(u8* const swizzled_data, u8* const unswizzled_data, const bool void CopySwizzledData(u32 width, u32 height, u32 depth, u32 bytes_per_pixel, u32 out_bytes_per_pixel, u8* const swizzled_data, u8* const unswizzled_data, - bool unswizzle, u32 block_height, u32 block_depth) { + bool unswizzle, u32 block_height, u32 block_depth, u32 width_spacing) { if (bytes_per_pixel % 3 != 0 && (width * bytes_per_pixel) % fast_swizzle_align == 0) { SwizzledData(swizzled_data, unswizzled_data, unswizzle, width, height, depth, - bytes_per_pixel, out_bytes_per_pixel, block_height, block_depth); + bytes_per_pixel, out_bytes_per_pixel, block_height, block_depth, + width_spacing); } else { SwizzledData(swizzled_data, unswizzled_data, unswizzle, width, height, depth, - bytes_per_pixel, out_bytes_per_pixel, block_height, block_depth); + bytes_per_pixel, out_bytes_per_pixel, block_height, block_depth, + width_spacing); } } @@ -228,19 +232,19 @@ u32 BytesPerPixel(TextureFormat format) { void UnswizzleTexture(u8* const unswizzled_data, VAddr address, u32 tile_size_x, u32 tile_size_y, u32 bytes_per_pixel, u32 width, u32 height, u32 depth, u32 block_height, - u32 block_depth) { + u32 block_depth, u32 width_spacing) { CopySwizzledData((width + tile_size_x - 1) / tile_size_x, (height + tile_size_y - 1) / tile_size_y, depth, bytes_per_pixel, bytes_per_pixel, Memory::GetPointer(address), unswizzled_data, true, - block_height, block_depth); + block_height, block_depth, width_spacing); } std::vector UnswizzleTexture(VAddr address, u32 tile_size_x, u32 tile_size_y, u32 bytes_per_pixel, u32 width, u32 height, u32 depth, - u32 block_height, u32 block_depth) { + u32 block_height, u32 block_depth, u32 width_spacing) { std::vector unswizzled_data(width * height * depth * bytes_per_pixel); UnswizzleTexture(unswizzled_data.data(), address, tile_size_x, tile_size_y, bytes_per_pixel, - width, height, depth, block_height, block_depth); + width, height, depth, block_height, block_depth, width_spacing); return unswizzled_data; } diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h index f4ef7c73eb..85b7e9f7bb 100644 --- a/src/video_core/textures/decoders.h +++ b/src/video_core/textures/decoders.h @@ -22,19 +22,20 @@ inline std::size_t GetGOBSize() { void UnswizzleTexture(u8* unswizzled_data, VAddr address, u32 tile_size_x, u32 tile_size_y, u32 bytes_per_pixel, u32 width, u32 height, u32 depth, u32 block_height = TICEntry::DefaultBlockHeight, - u32 block_depth = TICEntry::DefaultBlockHeight); + u32 block_depth = TICEntry::DefaultBlockHeight, u32 width_spacing = 0); /** * Unswizzles a swizzled texture without changing its format. */ std::vector UnswizzleTexture(VAddr address, u32 tile_size_x, u32 tile_size_y, u32 bytes_per_pixel, u32 width, u32 height, u32 depth, u32 block_height = TICEntry::DefaultBlockHeight, - u32 block_depth = TICEntry::DefaultBlockHeight); + u32 block_depth = TICEntry::DefaultBlockHeight, + u32 width_spacing = 0); /// Copies texture data from a buffer and performs swizzling/unswizzling as necessary. void CopySwizzledData(u32 width, u32 height, u32 depth, u32 bytes_per_pixel, u32 out_bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data, - bool unswizzle, u32 block_height, u32 block_depth); + bool unswizzle, u32 block_height, u32 block_depth, u32 width_spacing); /** * Decodes an unswizzled texture into a A8R8G8B8 texture. diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h index ffa08f5c13..e7c78bee28 100644 --- a/src/video_core/textures/texture.h +++ b/src/video_core/textures/texture.h @@ -166,6 +166,8 @@ struct TICEntry { BitField<3, 3, u32> block_height; BitField<6, 3, u32> block_depth; + BitField<10, 3, u32> tile_width_spacing; + // High 16 bits of the pitch value BitField<0, 16, u32> pitch_high; BitField<26, 1, u32> use_header_opt_control;