diff options
| author | 2018-04-18 14:46:10 -0400 | |
|---|---|---|
| committer | 2018-04-18 14:46:10 -0400 | |
| commit | d3f9ea90e78dce585f23c71c969990439937b427 (patch) | |
| tree | 618163c00bf621be9b7a44535493ceeaabd6257f /src | |
| parent | Merge pull request #346 from bunnei/misc-gpu-improvements (diff) | |
| parent | GPU: Pitch textures are now supported, don't assert when encountering them. (diff) | |
| download | yuzu-d3f9ea90e78dce585f23c71c969990439937b427.tar.gz yuzu-d3f9ea90e78dce585f23c71c969990439937b427.tar.xz yuzu-d3f9ea90e78dce585f23c71c969990439937b427.zip | |
Merge pull request #349 from Subv/texturing
GPU: Support non-tiled textures and configurable block height.
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 5 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 93 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 13 | ||||
| -rw-r--r-- | src/video_core/textures/decoders.cpp | 9 | ||||
| -rw-r--r-- | src/video_core/textures/decoders.h | 3 | ||||
| -rw-r--r-- | src/video_core/textures/texture.h | 24 |
7 files changed, 97 insertions, 53 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index a2f162602..2a3ff234a 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -218,8 +218,9 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const { | |||
| 218 | Texture::TICEntry tic_entry; | 218 | Texture::TICEntry tic_entry; |
| 219 | Memory::ReadBlock(tic_address_cpu, &tic_entry, sizeof(Texture::TICEntry)); | 219 | Memory::ReadBlock(tic_address_cpu, &tic_entry, sizeof(Texture::TICEntry)); |
| 220 | 220 | ||
| 221 | ASSERT_MSG(tic_entry.header_version == Texture::TICHeaderVersion::BlockLinear, | 221 | ASSERT_MSG(tic_entry.header_version == Texture::TICHeaderVersion::BlockLinear || |
| 222 | "TIC versions other than BlockLinear are unimplemented"); | 222 | tic_entry.header_version == Texture::TICHeaderVersion::Pitch, |
| 223 | "TIC versions other than BlockLinear or Pitch are unimplemented"); | ||
| 223 | 224 | ||
| 224 | ASSERT_MSG((tic_entry.texture_type == Texture::TextureType::Texture2D) || | 225 | ASSERT_MSG((tic_entry.texture_type == Texture::TextureType::Texture2D) || |
| 225 | (tic_entry.texture_type == Texture::TextureType::Texture2DNoMipmap), | 226 | (tic_entry.texture_type == Texture::TextureType::Texture2DNoMipmap), |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 7b6240e65..9522a35ea 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -523,7 +523,8 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& framebu | |||
| 523 | src_params.width = std::min(framebuffer.width, pixel_stride); | 523 | src_params.width = std::min(framebuffer.width, pixel_stride); |
| 524 | src_params.height = framebuffer.height; | 524 | src_params.height = framebuffer.height; |
| 525 | src_params.stride = pixel_stride; | 525 | src_params.stride = pixel_stride; |
| 526 | src_params.is_tiled = false; | 526 | src_params.is_tiled = true; |
| 527 | src_params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight; | ||
| 527 | src_params.pixel_format = | 528 | src_params.pixel_format = |
| 528 | SurfaceParams::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format); | 529 | SurfaceParams::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format); |
| 529 | src_params.UpdateParams(); | 530 | src_params.UpdateParams(); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 213b20a21..a92773f11 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -102,39 +102,36 @@ static void MortonCopyTile(u32 stride, u8* tile_buffer, u8* gl_buffer) { | |||
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | template <bool morton_to_gl, PixelFormat format> | 104 | template <bool morton_to_gl, PixelFormat format> |
| 105 | void MortonCopy(u32 stride, u32 height, u8* gl_buffer, VAddr base, VAddr start, VAddr end) { | 105 | void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, VAddr base, VAddr start, |
| 106 | VAddr end) { | ||
| 106 | constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8; | 107 | constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8; |
| 107 | constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format); | 108 | constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format); |
| 108 | 109 | ||
| 109 | // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check the | 110 | if (morton_to_gl) { |
| 110 | // configuration for this and perform more generic un/swizzle | 111 | auto data = Tegra::Texture::UnswizzleTexture( |
| 111 | LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); | 112 | base, SurfaceParams::TextureFormatFromPixelFormat(format), stride, height, |
| 112 | VideoCore::MortonCopyPixels128(stride, height, bytes_per_pixel, gl_bytes_per_pixel, | 113 | block_height); |
| 113 | Memory::GetPointer(base), gl_buffer, morton_to_gl); | 114 | std::memcpy(gl_buffer, data.data(), data.size()); |
| 114 | } | 115 | } else { |
| 115 | 116 | // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check | |
| 116 | template <> | 117 | // the configuration for this and perform more generic un/swizzle |
| 117 | void MortonCopy<true, PixelFormat::DXT1>(u32 stride, u32 height, u8* gl_buffer, VAddr base, | 118 | LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); |
| 118 | VAddr start, VAddr end) { | 119 | VideoCore::MortonCopyPixels128(stride, height, bytes_per_pixel, gl_bytes_per_pixel, |
| 119 | constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(PixelFormat::DXT1) / 8; | 120 | Memory::GetPointer(base), gl_buffer, morton_to_gl); |
| 120 | constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(PixelFormat::DXT1); | 121 | } |
| 121 | |||
| 122 | // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check the | ||
| 123 | // configuration for this and perform more generic un/swizzle | ||
| 124 | LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); | ||
| 125 | auto data = | ||
| 126 | Tegra::Texture::UnswizzleTexture(base, Tegra::Texture::TextureFormat::DXT1, stride, height); | ||
| 127 | std::memcpy(gl_buffer, data.data(), data.size()); | ||
| 128 | } | 122 | } |
| 129 | 123 | ||
| 130 | static constexpr std::array<void (*)(u32, u32, u8*, VAddr, VAddr, VAddr), 2> morton_to_gl_fns = { | 124 | static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr), 2> morton_to_gl_fns = |
| 131 | MortonCopy<true, PixelFormat::RGBA8>, | 125 | { |
| 132 | MortonCopy<true, PixelFormat::DXT1>, | 126 | MortonCopy<true, PixelFormat::RGBA8>, |
| 127 | MortonCopy<true, PixelFormat::DXT1>, | ||
| 133 | }; | 128 | }; |
| 134 | 129 | ||
| 135 | static constexpr std::array<void (*)(u32, u32, u8*, VAddr, VAddr, VAddr), 2> gl_to_morton_fns = { | 130 | static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr), 2> gl_to_morton_fns = |
| 136 | MortonCopy<false, PixelFormat::RGBA8>, | 131 | { |
| 137 | MortonCopy<false, PixelFormat::DXT1>, | 132 | MortonCopy<false, PixelFormat::RGBA8>, |
| 133 | // TODO(Subv): Swizzling the DXT1 format is not yet supported | ||
| 134 | nullptr, | ||
| 138 | }; | 135 | }; |
| 139 | 136 | ||
| 140 | // Allocate an uninitialized texture of appropriate size and format for the surface | 137 | // Allocate an uninitialized texture of appropriate size and format for the surface |
| @@ -311,15 +308,16 @@ MathUtil::Rectangle<u32> SurfaceParams::GetScaledSubRect(const SurfaceParams& su | |||
| 311 | 308 | ||
| 312 | bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const { | 309 | bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const { |
| 313 | return std::tie(other_surface.addr, other_surface.width, other_surface.height, | 310 | return std::tie(other_surface.addr, other_surface.width, other_surface.height, |
| 314 | other_surface.stride, other_surface.pixel_format, other_surface.is_tiled) == | 311 | other_surface.stride, other_surface.block_height, other_surface.pixel_format, |
| 315 | std::tie(addr, width, height, stride, pixel_format, is_tiled) && | 312 | other_surface.is_tiled) == |
| 313 | std::tie(addr, width, height, stride, block_height, pixel_format, is_tiled) && | ||
| 316 | pixel_format != PixelFormat::Invalid; | 314 | pixel_format != PixelFormat::Invalid; |
| 317 | } | 315 | } |
| 318 | 316 | ||
| 319 | bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const { | 317 | bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const { |
| 320 | return sub_surface.addr >= addr && sub_surface.end <= end && | 318 | return sub_surface.addr >= addr && sub_surface.end <= end && |
| 321 | sub_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid && | 319 | sub_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid && |
| 322 | sub_surface.is_tiled == is_tiled && | 320 | sub_surface.is_tiled == is_tiled && sub_surface.block_height == block_height && |
| 323 | (sub_surface.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 && | 321 | (sub_surface.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 && |
| 324 | (sub_surface.stride == stride || sub_surface.height <= (is_tiled ? 8u : 1u)) && | 322 | (sub_surface.stride == stride || sub_surface.height <= (is_tiled ? 8u : 1u)) && |
| 325 | GetSubRect(sub_surface).left + sub_surface.width <= stride; | 323 | GetSubRect(sub_surface).left + sub_surface.width <= stride; |
| @@ -328,7 +326,8 @@ bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const { | |||
| 328 | bool SurfaceParams::CanExpand(const SurfaceParams& expanded_surface) const { | 326 | bool SurfaceParams::CanExpand(const SurfaceParams& expanded_surface) const { |
| 329 | return pixel_format != PixelFormat::Invalid && pixel_format == expanded_surface.pixel_format && | 327 | return pixel_format != PixelFormat::Invalid && pixel_format == expanded_surface.pixel_format && |
| 330 | addr <= expanded_surface.end && expanded_surface.addr <= end && | 328 | addr <= expanded_surface.end && expanded_surface.addr <= end && |
| 331 | is_tiled == expanded_surface.is_tiled && stride == expanded_surface.stride && | 329 | is_tiled == expanded_surface.is_tiled && block_height == expanded_surface.block_height && |
| 330 | stride == expanded_surface.stride && | ||
| 332 | (std::max(expanded_surface.addr, addr) - std::min(expanded_surface.addr, addr)) % | 331 | (std::max(expanded_surface.addr, addr) - std::min(expanded_surface.addr, addr)) % |
| 333 | BytesInPixels(stride * (is_tiled ? 8 : 1)) == | 332 | BytesInPixels(stride * (is_tiled ? 8 : 1)) == |
| 334 | 0; | 333 | 0; |
| @@ -339,6 +338,9 @@ bool SurfaceParams::CanTexCopy(const SurfaceParams& texcopy_params) const { | |||
| 339 | end < texcopy_params.end) { | 338 | end < texcopy_params.end) { |
| 340 | return false; | 339 | return false; |
| 341 | } | 340 | } |
| 341 | if (texcopy_params.block_height != block_height) | ||
| 342 | return false; | ||
| 343 | |||
| 342 | if (texcopy_params.width != texcopy_params.stride) { | 344 | if (texcopy_params.width != texcopy_params.stride) { |
| 343 | const u32 tile_stride = static_cast<u32>(BytesInPixels(stride * (is_tiled ? 8 : 1))); | 345 | const u32 tile_stride = static_cast<u32>(BytesInPixels(stride * (is_tiled ? 8 : 1))); |
| 344 | return (texcopy_params.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 && | 346 | return (texcopy_params.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 && |
| @@ -481,18 +483,13 @@ void CachedSurface::LoadGLBuffer(VAddr load_start, VAddr load_end) { | |||
| 481 | const u64 start_offset = load_start - addr; | 483 | const u64 start_offset = load_start - addr; |
| 482 | 484 | ||
| 483 | if (!is_tiled) { | 485 | if (!is_tiled) { |
| 484 | ASSERT(type == SurfaceType::Color); | ||
| 485 | const u32 bytes_per_pixel{GetFormatBpp() >> 3}; | 486 | const u32 bytes_per_pixel{GetFormatBpp() >> 3}; |
| 486 | 487 | ||
| 487 | // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check | 488 | std::memcpy(&gl_buffer[start_offset], texture_src_data + start_offset, |
| 488 | // the configuration for this and perform more generic un/swizzle | 489 | bytes_per_pixel * width * height); |
| 489 | LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); | ||
| 490 | VideoCore::MortonCopyPixels128(width, height, bytes_per_pixel, 4, | ||
| 491 | texture_src_data + start_offset, &gl_buffer[start_offset], | ||
| 492 | true); | ||
| 493 | } else { | 490 | } else { |
| 494 | morton_to_gl_fns[static_cast<size_t>(pixel_format)](stride, height, &gl_buffer[0], addr, | 491 | morton_to_gl_fns[static_cast<size_t>(pixel_format)]( |
| 495 | load_start, load_end); | 492 | stride, block_height, height, &gl_buffer[0], addr, load_start, load_end); |
| 496 | } | 493 | } |
| 497 | } | 494 | } |
| 498 | 495 | ||
| @@ -533,11 +530,10 @@ void CachedSurface::FlushGLBuffer(VAddr flush_start, VAddr flush_end) { | |||
| 533 | if (backup_bytes) | 530 | if (backup_bytes) |
| 534 | std::memcpy(&dst_buffer[coarse_start_offset], &backup_data[0], backup_bytes); | 531 | std::memcpy(&dst_buffer[coarse_start_offset], &backup_data[0], backup_bytes); |
| 535 | } else if (!is_tiled) { | 532 | } else if (!is_tiled) { |
| 536 | ASSERT(type == SurfaceType::Color); | ||
| 537 | std::memcpy(dst_buffer + start_offset, &gl_buffer[start_offset], flush_end - flush_start); | 533 | std::memcpy(dst_buffer + start_offset, &gl_buffer[start_offset], flush_end - flush_start); |
| 538 | } else { | 534 | } else { |
| 539 | gl_to_morton_fns[static_cast<size_t>(pixel_format)](stride, height, &gl_buffer[0], addr, | 535 | gl_to_morton_fns[static_cast<size_t>(pixel_format)]( |
| 540 | flush_start, flush_end); | 536 | stride, block_height, height, &gl_buffer[0], addr, flush_start, flush_end); |
| 541 | } | 537 | } |
| 542 | } | 538 | } |
| 543 | 539 | ||
| @@ -1041,9 +1037,18 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu | |||
| 1041 | params.height = config.tic.Height(); | 1037 | params.height = config.tic.Height(); |
| 1042 | params.is_tiled = config.tic.IsTiled(); | 1038 | params.is_tiled = config.tic.IsTiled(); |
| 1043 | params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format); | 1039 | params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format); |
| 1040 | |||
| 1041 | if (config.tic.IsTiled()) { | ||
| 1042 | params.block_height = config.tic.BlockHeight(); | ||
| 1043 | } else { | ||
| 1044 | // Use the texture-provided stride value if the texture isn't tiled. | ||
| 1045 | params.stride = params.PixelsInBytes(config.tic.Pitch()); | ||
| 1046 | } | ||
| 1047 | |||
| 1044 | params.UpdateParams(); | 1048 | params.UpdateParams(); |
| 1045 | 1049 | ||
| 1046 | if (config.tic.Width() % 8 != 0 || config.tic.Height() % 8 != 0) { | 1050 | if (config.tic.Width() % 8 != 0 || config.tic.Height() % 8 != 0 || |
| 1051 | params.stride != params.width) { | ||
| 1047 | Surface src_surface; | 1052 | Surface src_surface; |
| 1048 | MathUtil::Rectangle<u32> rect; | 1053 | MathUtil::Rectangle<u32> rect; |
| 1049 | std::tie(src_surface, rect) = GetSurfaceSubRect(params, ScaleMatch::Ignore, true); | 1054 | std::tie(src_surface, rect) = GetSurfaceSubRect(params, ScaleMatch::Ignore, true); |
| @@ -1094,6 +1099,8 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( | |||
| 1094 | color_params.res_scale = resolution_scale_factor; | 1099 | color_params.res_scale = resolution_scale_factor; |
| 1095 | color_params.width = config.width; | 1100 | color_params.width = config.width; |
| 1096 | color_params.height = config.height; | 1101 | color_params.height = config.height; |
| 1102 | // TODO(Subv): Can framebuffers use a different block height? | ||
| 1103 | color_params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight; | ||
| 1097 | SurfaceParams depth_params = color_params; | 1104 | SurfaceParams depth_params = color_params; |
| 1098 | 1105 | ||
| 1099 | color_params.addr = memory_manager->PhysicalToVirtualAddress(config.Address()); | 1106 | color_params.addr = memory_manager->PhysicalToVirtualAddress(config.Address()); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 3293905d6..26d6c3061 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h | |||
| @@ -115,6 +115,18 @@ struct SurfaceParams { | |||
| 115 | } | 115 | } |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | static Tegra::Texture::TextureFormat TextureFormatFromPixelFormat(PixelFormat format) { | ||
| 119 | // TODO(Subv): Properly implement this | ||
| 120 | switch (format) { | ||
| 121 | case PixelFormat::RGBA8: | ||
| 122 | return Tegra::Texture::TextureFormat::A8R8G8B8; | ||
| 123 | case PixelFormat::DXT1: | ||
| 124 | return Tegra::Texture::TextureFormat::DXT1; | ||
| 125 | default: | ||
| 126 | UNREACHABLE(); | ||
| 127 | } | ||
| 128 | } | ||
| 129 | |||
| 118 | static bool CheckFormatsBlittable(PixelFormat pixel_format_a, PixelFormat pixel_format_b) { | 130 | static bool CheckFormatsBlittable(PixelFormat pixel_format_a, PixelFormat pixel_format_b) { |
| 119 | SurfaceType a_type = GetFormatType(pixel_format_a); | 131 | SurfaceType a_type = GetFormatType(pixel_format_a); |
| 120 | SurfaceType b_type = GetFormatType(pixel_format_b); | 132 | SurfaceType b_type = GetFormatType(pixel_format_b); |
| @@ -213,6 +225,7 @@ struct SurfaceParams { | |||
| 213 | u32 width = 0; | 225 | u32 width = 0; |
| 214 | u32 height = 0; | 226 | u32 height = 0; |
| 215 | u32 stride = 0; | 227 | u32 stride = 0; |
| 228 | u32 block_height = 0; | ||
| 216 | u16 res_scale = 1; | 229 | u16 res_scale = 1; |
| 217 | 230 | ||
| 218 | bool is_tiled = false; | 231 | bool is_tiled = false; |
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index 2e87281eb..9c2a10d2e 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp | |||
| @@ -56,23 +56,22 @@ u32 BytesPerPixel(TextureFormat format) { | |||
| 56 | } | 56 | } |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height) { | 59 | std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height, |
| 60 | u32 block_height) { | ||
| 60 | u8* data = Memory::GetPointer(address); | 61 | u8* data = Memory::GetPointer(address); |
| 61 | u32 bytes_per_pixel = BytesPerPixel(format); | 62 | u32 bytes_per_pixel = BytesPerPixel(format); |
| 62 | 63 | ||
| 63 | static constexpr u32 DefaultBlockHeight = 16; | ||
| 64 | |||
| 65 | std::vector<u8> unswizzled_data(width * height * bytes_per_pixel); | 64 | std::vector<u8> unswizzled_data(width * height * bytes_per_pixel); |
| 66 | 65 | ||
| 67 | switch (format) { | 66 | switch (format) { |
| 68 | case TextureFormat::DXT1: | 67 | case TextureFormat::DXT1: |
| 69 | // In the DXT1 format, each 4x4 tile is swizzled instead of just individual pixel values. | 68 | // In the DXT1 format, each 4x4 tile is swizzled instead of just individual pixel values. |
| 70 | CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data, | 69 | CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data, |
| 71 | unswizzled_data.data(), true, DefaultBlockHeight); | 70 | unswizzled_data.data(), true, block_height); |
| 72 | break; | 71 | break; |
| 73 | case TextureFormat::A8R8G8B8: | 72 | case TextureFormat::A8R8G8B8: |
| 74 | CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data, | 73 | CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data, |
| 75 | unswizzled_data.data(), true, DefaultBlockHeight); | 74 | unswizzled_data.data(), true, block_height); |
| 76 | break; | 75 | break; |
| 77 | default: | 76 | default: |
| 78 | UNIMPLEMENTED_MSG("Format not implemented"); | 77 | UNIMPLEMENTED_MSG("Format not implemented"); |
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h index 0c21694ff..a700911cf 100644 --- a/src/video_core/textures/decoders.h +++ b/src/video_core/textures/decoders.h | |||
| @@ -14,7 +14,8 @@ namespace Texture { | |||
| 14 | /** | 14 | /** |
| 15 | * Unswizzles a swizzled texture without changing its format. | 15 | * Unswizzles a swizzled texture without changing its format. |
| 16 | */ | 16 | */ |
| 17 | std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height); | 17 | std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height, |
| 18 | u32 block_height = TICEntry::DefaultBlockHeight); | ||
| 18 | 19 | ||
| 19 | /** | 20 | /** |
| 20 | * Decodes an unswizzled texture into a A8R8G8B8 texture. | 21 | * 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 9d443ea90..09d2317e0 100644 --- a/src/video_core/textures/texture.h +++ b/src/video_core/textures/texture.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/assert.h" | ||
| 7 | #include "common/bit_field.h" | 8 | #include "common/bit_field.h" |
| 8 | #include "common/common_funcs.h" | 9 | #include "common/common_funcs.h" |
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| @@ -57,6 +58,8 @@ union TextureHandle { | |||
| 57 | static_assert(sizeof(TextureHandle) == 4, "TextureHandle has wrong size"); | 58 | static_assert(sizeof(TextureHandle) == 4, "TextureHandle has wrong size"); |
| 58 | 59 | ||
| 59 | struct TICEntry { | 60 | struct TICEntry { |
| 61 | static constexpr u32 DefaultBlockHeight = 16; | ||
| 62 | |||
| 60 | union { | 63 | union { |
| 61 | u32 raw; | 64 | u32 raw; |
| 62 | BitField<0, 7, TextureFormat> format; | 65 | BitField<0, 7, TextureFormat> format; |
| @@ -70,7 +73,12 @@ struct TICEntry { | |||
| 70 | BitField<0, 16, u32> address_high; | 73 | BitField<0, 16, u32> address_high; |
| 71 | BitField<21, 3, TICHeaderVersion> header_version; | 74 | BitField<21, 3, TICHeaderVersion> header_version; |
| 72 | }; | 75 | }; |
| 73 | INSERT_PADDING_BYTES(4); | 76 | union { |
| 77 | BitField<3, 3, u32> block_height; | ||
| 78 | |||
| 79 | // High 16 bits of the pitch value | ||
| 80 | BitField<0, 16, u32> pitch_high; | ||
| 81 | }; | ||
| 74 | union { | 82 | union { |
| 75 | BitField<0, 16, u32> width_minus_1; | 83 | BitField<0, 16, u32> width_minus_1; |
| 76 | BitField<23, 4, TextureType> texture_type; | 84 | BitField<23, 4, TextureType> texture_type; |
| @@ -82,6 +90,13 @@ struct TICEntry { | |||
| 82 | return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low); | 90 | return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low); |
| 83 | } | 91 | } |
| 84 | 92 | ||
| 93 | u32 Pitch() const { | ||
| 94 | ASSERT(header_version == TICHeaderVersion::Pitch || | ||
| 95 | header_version == TICHeaderVersion::PitchColorKey); | ||
| 96 | // The pitch value is 21 bits, and is 32B aligned. | ||
| 97 | return pitch_high << 5; | ||
| 98 | } | ||
| 99 | |||
| 85 | u32 Width() const { | 100 | u32 Width() const { |
| 86 | return width_minus_1 + 1; | 101 | return width_minus_1 + 1; |
| 87 | } | 102 | } |
| @@ -90,6 +105,13 @@ struct TICEntry { | |||
| 90 | return height_minus_1 + 1; | 105 | return height_minus_1 + 1; |
| 91 | } | 106 | } |
| 92 | 107 | ||
| 108 | u32 BlockHeight() const { | ||
| 109 | ASSERT(header_version == TICHeaderVersion::BlockLinear || | ||
| 110 | header_version == TICHeaderVersion::BlockLinearColorKey); | ||
| 111 | // The block height is stored in log2 format. | ||
| 112 | return 1 << block_height; | ||
| 113 | } | ||
| 114 | |||
| 93 | bool IsTiled() const { | 115 | bool IsTiled() const { |
| 94 | return header_version == TICHeaderVersion::BlockLinear || | 116 | return header_version == TICHeaderVersion::BlockLinear || |
| 95 | header_version == TICHeaderVersion::BlockLinearColorKey; | 117 | header_version == TICHeaderVersion::BlockLinearColorKey; |