Przeglądaj źródła

GPU: Implemented the Z24S8 depth format and load the depth framebuffer.

Subv 8 lat temu
rodzic
commit
0f929762b3

+ 1 - 1
src/video_core/engines/maxwell_3d.h

@@ -413,7 +413,7 @@ public:
                 struct {
                     u32 address_high;
                     u32 address_low;
-                    u32 format;
+                    Tegra::DepthFormat format;
                     u32 block_dimensions;
                     u32 layer_stride;
 

+ 9 - 0
src/video_core/gpu.h

@@ -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);
 

+ 3 - 1
src/video_core/renderer_opengl/gl_rasterizer.cpp

@@ -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 =

+ 29 - 20
src/video_core/renderer_opengl/gl_rasterizer_cache.cpp

@@ -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;

+ 45 - 2
src/video_core/renderer_opengl/gl_rasterizer_cache.h

@@ -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);
 

+ 31 - 0
src/video_core/textures/decoders.cpp

@@ -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;

+ 6 - 0
src/video_core/textures/decoders.h

@@ -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);