GPU: Implemented the Z24S8 depth format and load the depth framebuffer.
This commit is contained in:
		| @@ -413,7 +413,7 @@ public: | ||||
|                 struct { | ||||
|                     u32 address_high; | ||||
|                     u32 address_low; | ||||
|                     u32 format; | ||||
|                     Tegra::DepthFormat format; | ||||
|                     u32 block_dimensions; | ||||
|                     u32 layer_stride; | ||||
|  | ||||
|   | ||||
| @@ -24,6 +24,15 @@ enum class RenderTargetFormat : u32 { | ||||
|     R11G11B10_FLOAT = 0xE0, | ||||
| }; | ||||
|  | ||||
| enum class DepthFormat : u32 { | ||||
|     Z32_FLOAT = 0xA, | ||||
|     Z16_UNORM = 0x13, | ||||
|     S8_Z24_UNORM = 0x14, | ||||
|     Z24_X8_UNORM = 0x15, | ||||
|     Z24_S8_UNORM = 0x16, | ||||
|     Z24_C8_UNORM = 0x18, | ||||
| }; | ||||
|  | ||||
| /// Returns the number of bytes per pixel of each rendertarget format. | ||||
| u32 RenderTargetBytesPerPixel(RenderTargetFormat format); | ||||
|  | ||||
|   | ||||
| @@ -307,7 +307,9 @@ void RasterizerOpenGL::DrawArrays() { | ||||
|     // TODO(bunnei): Implement these | ||||
|     const bool has_stencil = false; | ||||
|     const bool using_color_fb = true; | ||||
|     const bool using_depth_fb = false; | ||||
|  | ||||
|     const bool using_depth_fb = regs.zeta.Address() != 0; | ||||
|  | ||||
|     const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()}; | ||||
|  | ||||
|     const bool write_color_fb = | ||||
|   | ||||
| @@ -84,22 +84,18 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form | ||||
|      true},                                                                                 // DXT45 | ||||
|     {GL_COMPRESSED_RED_RGTC1, GL_RED, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, true}, // DXN1 | ||||
|     {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4 | ||||
|  | ||||
|     // DepthStencil formats | ||||
|     {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, ComponentType::UNorm, | ||||
|      false}, // Z24S8 | ||||
| }}; | ||||
|  | ||||
| static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) { | ||||
|     const SurfaceType type = SurfaceParams::GetFormatType(pixel_format); | ||||
|     if (type == SurfaceType::ColorTexture) { | ||||
|         ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size()); | ||||
|         auto& format = tex_format_tuples[static_cast<unsigned int>(pixel_format)]; | ||||
|         ASSERT(component_type == format.component_type); | ||||
|         return format; | ||||
|     } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) { | ||||
|         // TODO(Subv): Implement depth formats | ||||
|         ASSERT_MSG(false, "Unimplemented"); | ||||
|     } | ||||
|     ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size()); | ||||
|     auto& format = tex_format_tuples[static_cast<unsigned int>(pixel_format)]; | ||||
|     ASSERT(component_type == format.component_type); | ||||
|  | ||||
|     UNREACHABLE(); | ||||
|     return {}; | ||||
|     return format; | ||||
| } | ||||
|  | ||||
| VAddr SurfaceParams::GetCpuAddr() const { | ||||
| @@ -149,11 +145,17 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, Tegra:: | ||||
|     const auto& gpu = Core::System::GetInstance().GPU(); | ||||
|  | ||||
|     if (morton_to_gl) { | ||||
|         auto data = Tegra::Texture::UnswizzleTexture( | ||||
|             *gpu.memory_manager->GpuToCpuAddress(addr), | ||||
|             SurfaceParams::TextureFormatFromPixelFormat(format), stride, height, block_height); | ||||
|  | ||||
|         std::memcpy(gl_buffer, data.data(), data.size()); | ||||
|         if (SurfaceParams::GetFormatType(format) == SurfaceType::ColorTexture) { | ||||
|             auto data = Tegra::Texture::UnswizzleTexture( | ||||
|                 *gpu.memory_manager->GpuToCpuAddress(addr), | ||||
|                 SurfaceParams::TextureFormatFromPixelFormat(format), stride, height, block_height); | ||||
|             std::memcpy(gl_buffer, data.data(), data.size()); | ||||
|         } else { | ||||
|             auto data = Tegra::Texture::UnswizzleDepthTexture( | ||||
|                 *gpu.memory_manager->GpuToCpuAddress(addr), | ||||
|                 SurfaceParams::DepthFormatFromPixelFormat(format), stride, height, block_height); | ||||
|             std::memcpy(gl_buffer, data.data(), data.size()); | ||||
|         } | ||||
|     } else { | ||||
|         // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should | ||||
|         // check the configuration for this and perform more generic un/swizzle | ||||
| @@ -174,7 +176,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr), | ||||
|         MortonCopy<true, PixelFormat::R11FG11FB10F>, MortonCopy<true, PixelFormat::RGBA32UI>, | ||||
|         MortonCopy<true, PixelFormat::DXT1>,         MortonCopy<true, PixelFormat::DXT23>, | ||||
|         MortonCopy<true, PixelFormat::DXT45>,        MortonCopy<true, PixelFormat::DXN1>, | ||||
|         MortonCopy<true, PixelFormat::ASTC_2D_4X4>, | ||||
|         MortonCopy<true, PixelFormat::ASTC_2D_4X4>,  MortonCopy<true, PixelFormat::Z24S8>, | ||||
| }; | ||||
|  | ||||
| static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr), | ||||
| @@ -194,6 +196,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr), | ||||
|         nullptr, | ||||
|         nullptr, | ||||
|         MortonCopy<false, PixelFormat::ABGR8>, | ||||
|         MortonCopy<false, PixelFormat::Z24S8>, | ||||
| }; | ||||
|  | ||||
| // Allocate an uninitialized texture of appropriate size and format for the surface | ||||
| @@ -397,9 +400,15 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( | ||||
|  | ||||
|     // get color and depth surfaces | ||||
|     const SurfaceParams color_params{SurfaceParams::CreateForFramebuffer(regs.rt[0])}; | ||||
|     const SurfaceParams depth_params{color_params}; | ||||
|     SurfaceParams depth_params{color_params}; | ||||
|  | ||||
|     ASSERT_MSG(!using_depth_fb, "depth buffer is unimplemented"); | ||||
|     if (using_depth_fb) { | ||||
|         depth_params.addr = regs.zeta.Address(); | ||||
|         depth_params.pixel_format = SurfaceParams::PixelFormatFromDepthFormat(regs.zeta.format); | ||||
|         depth_params.component_type = SurfaceParams::ComponentTypeFromDepthFormat(regs.zeta.format); | ||||
|         depth_params.type = SurfaceParams::GetFormatType(depth_params.pixel_format); | ||||
|         depth_params.size_in_bytes = depth_params.SizeInBytes(); | ||||
|     } | ||||
|  | ||||
|     MathUtil::Rectangle<u32> color_rect{}; | ||||
|     Surface color_surface; | ||||
|   | ||||
| @@ -37,7 +37,14 @@ struct SurfaceParams { | ||||
|         DXN1 = 11, // This is also known as BC4 | ||||
|         ASTC_2D_4X4 = 12, | ||||
|  | ||||
|         Max, | ||||
|         MaxColorFormat, | ||||
|  | ||||
|         // DepthStencil formats | ||||
|         Z24S8 = 13, | ||||
|  | ||||
|         MaxDepthStencilFormat, | ||||
|  | ||||
|         Max = MaxDepthStencilFormat, | ||||
|         Invalid = 255, | ||||
|     }; | ||||
|  | ||||
| @@ -84,6 +91,7 @@ struct SurfaceParams { | ||||
|             4, // DXT45 | ||||
|             4, // DXN1 | ||||
|             4, // ASTC_2D_4X4 | ||||
|             1, // Z24S8 | ||||
|         }}; | ||||
|  | ||||
|         ASSERT(static_cast<size_t>(format) < compression_factor_table.size()); | ||||
| @@ -108,6 +116,7 @@ struct SurfaceParams { | ||||
|             128, // DXT45 | ||||
|             64,  // DXN1 | ||||
|             32,  // ASTC_2D_4X4 | ||||
|             32,  // Z24S8 | ||||
|         }}; | ||||
|  | ||||
|         ASSERT(static_cast<size_t>(format) < bpp_table.size()); | ||||
| @@ -117,6 +126,16 @@ struct SurfaceParams { | ||||
|         return GetFormatBpp(pixel_format); | ||||
|     } | ||||
|  | ||||
|     static PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) { | ||||
|         switch (format) { | ||||
|         case Tegra::DepthFormat::Z24_S8_UNORM: | ||||
|             return PixelFormat::Z24S8; | ||||
|         default: | ||||
|             NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); | ||||
|             UNREACHABLE(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) { | ||||
|         switch (format) { | ||||
|         case Tegra::RenderTargetFormat::RGBA8_UNORM: | ||||
| @@ -205,6 +224,15 @@ struct SurfaceParams { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Tegra::DepthFormat DepthFormatFromPixelFormat(PixelFormat format) { | ||||
|         switch (format) { | ||||
|         case PixelFormat::Z24S8: | ||||
|             return Tegra::DepthFormat::Z24_S8_UNORM; | ||||
|         default: | ||||
|             UNREACHABLE(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static ComponentType ComponentTypeFromTexture(Tegra::Texture::ComponentType type) { | ||||
|         // TODO(Subv): Implement more component types | ||||
|         switch (type) { | ||||
| @@ -244,11 +272,26 @@ struct SurfaceParams { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static ComponentType ComponentTypeFromDepthFormat(Tegra::DepthFormat format) { | ||||
|         switch (format) { | ||||
|         case Tegra::DepthFormat::Z24_S8_UNORM: | ||||
|             return ComponentType::UNorm; | ||||
|         default: | ||||
|             NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); | ||||
|             UNREACHABLE(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static SurfaceType GetFormatType(PixelFormat pixel_format) { | ||||
|         if (static_cast<size_t>(pixel_format) < MaxPixelFormat) { | ||||
|         if (static_cast<size_t>(pixel_format) < static_cast<size_t>(PixelFormat::MaxColorFormat)) { | ||||
|             return SurfaceType::ColorTexture; | ||||
|         } | ||||
|  | ||||
|         if (static_cast<size_t>(pixel_format) < | ||||
|             static_cast<size_t>(PixelFormat::MaxDepthStencilFormat)) { | ||||
|             return SurfaceType::DepthStencil; | ||||
|         } | ||||
|  | ||||
|         // TODO(Subv): Implement the other formats | ||||
|         ASSERT(false); | ||||
|  | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| #include <cstring> | ||||
| #include "common/assert.h" | ||||
| #include "core/memory.h" | ||||
| #include "video_core/gpu.h" | ||||
| #include "video_core/textures/decoders.h" | ||||
| #include "video_core/textures/texture.h" | ||||
|  | ||||
| @@ -73,6 +74,16 @@ u32 BytesPerPixel(TextureFormat format) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| static u32 DepthBytesPerPixel(DepthFormat format) { | ||||
|     switch (format) { | ||||
|     case DepthFormat::Z24_S8_UNORM: | ||||
|         return 4; | ||||
|     default: | ||||
|         UNIMPLEMENTED_MSG("Format not implemented"); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height, | ||||
|                                  u32 block_height) { | ||||
|     u8* data = Memory::GetPointer(address); | ||||
| @@ -110,6 +121,26 @@ std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, | ||||
|     return unswizzled_data; | ||||
| } | ||||
|  | ||||
| std::vector<u8> UnswizzleDepthTexture(VAddr address, DepthFormat format, u32 width, u32 height, | ||||
|                                       u32 block_height) { | ||||
|     u8* data = Memory::GetPointer(address); | ||||
|     u32 bytes_per_pixel = DepthBytesPerPixel(format); | ||||
|  | ||||
|     std::vector<u8> unswizzled_data(width * height * bytes_per_pixel); | ||||
|  | ||||
|     switch (format) { | ||||
|     case DepthFormat::Z24_S8_UNORM: | ||||
|         CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data, | ||||
|                          unswizzled_data.data(), true, block_height); | ||||
|         break; | ||||
|     default: | ||||
|         UNIMPLEMENTED_MSG("Format not implemented"); | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     return unswizzled_data; | ||||
| } | ||||
|  | ||||
| std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width, | ||||
|                               u32 height) { | ||||
|     std::vector<u8> rgba_data; | ||||
|   | ||||
| @@ -17,6 +17,12 @@ namespace Texture { | ||||
| std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height, | ||||
|                                  u32 block_height = TICEntry::DefaultBlockHeight); | ||||
|  | ||||
| /** | ||||
|  * Unswizzles a swizzled depth texture without changing its format. | ||||
|  */ | ||||
| std::vector<u8> UnswizzleDepthTexture(VAddr address, DepthFormat format, u32 width, u32 height, | ||||
|                                       u32 block_height = TICEntry::DefaultBlockHeight); | ||||
|  | ||||
| /// Copies texture data from a buffer and performs swizzling/unswizzling as necessary. | ||||
| void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel, | ||||
|                       u8* swizzled_data, u8* unswizzled_data, bool unswizzle, u32 block_height); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user