Просмотр исходного кода

gl_rasterizer_cache: Various fixes for ASTC handling.

bunnei 8 лет назад
Родитель
Сommit
8af1ae46aa

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

@@ -41,6 +41,7 @@ struct FormatTuple {
     params.type = GetFormatType(params.pixel_format);
     params.type = GetFormatType(params.pixel_format);
     params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format));
     params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format));
     params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format));
     params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format));
+    params.unaligned_height = config.tic.Height();
     params.size_in_bytes = params.SizeInBytes();
     params.size_in_bytes = params.SizeInBytes();
     return params;
     return params;
 }
 }
@@ -57,6 +58,7 @@ struct FormatTuple {
     params.type = GetFormatType(params.pixel_format);
     params.type = GetFormatType(params.pixel_format);
     params.width = config.width;
     params.width = config.width;
     params.height = config.height;
     params.height = config.height;
+    params.unaligned_height = config.height;
     params.size_in_bytes = params.SizeInBytes();
     params.size_in_bytes = params.SizeInBytes();
     return params;
     return params;
 }
 }
@@ -108,20 +110,29 @@ static bool IsPixelFormatASTC(PixelFormat format) {
     }
     }
 }
 }
 
 
-static void ConvertASTCToRGBA8(std::vector<u8>& data, PixelFormat format, u32 width, u32 height) {
-    u32 block_width{};
-    u32 block_height{};
-
+static std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) {
     switch (format) {
     switch (format) {
     case PixelFormat::ASTC_2D_4X4:
     case PixelFormat::ASTC_2D_4X4:
-        block_width = 4;
-        block_height = 4;
-        break;
+        return {4, 4};
     default:
     default:
         NGLOG_CRITICAL(HW_GPU, "Unhandled format: {}", static_cast<u32>(format));
         NGLOG_CRITICAL(HW_GPU, "Unhandled format: {}", static_cast<u32>(format));
         UNREACHABLE();
         UNREACHABLE();
     }
     }
+}
 
 
+MathUtil::Rectangle<u32> SurfaceParams::GetRect() const {
+    u32 actual_height{unaligned_height};
+    if (IsPixelFormatASTC(pixel_format)) {
+        // ASTC formats must stop at the ATSC block size boundary
+        actual_height = Common::AlignDown(actual_height, GetASTCBlockSize(pixel_format).second);
+    }
+    return {0, actual_height, width, 0};
+}
+
+static void ConvertASTCToRGBA8(std::vector<u8>& data, PixelFormat format, u32 width, u32 height) {
+    u32 block_width{};
+    u32 block_height{};
+    std::tie(block_width, block_height) = GetASTCBlockSize(format);
     data = Tegra::Texture::ASTC::Decompress(data, width, height, block_width, block_height);
     data = Tegra::Texture::ASTC::Decompress(data, width, height, block_width, block_height);
 }
 }
 
 
@@ -136,12 +147,6 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, Tegra::
             *gpu.memory_manager->GpuToCpuAddress(addr),
             *gpu.memory_manager->GpuToCpuAddress(addr),
             SurfaceParams::TextureFormatFromPixelFormat(format), stride, height, block_height);
             SurfaceParams::TextureFormatFromPixelFormat(format), stride, height, block_height);
 
 
-        if (IsPixelFormatASTC(format)) {
-            // ASTC formats are converted to RGBA8 in software, as most PC GPUs do not support
-            // this
-            ConvertASTCToRGBA8(data, format, stride, height);
-        }
-
         std::memcpy(gl_buffer, data.data(), data.size());
         std::memcpy(gl_buffer, data.data(), data.size());
     } else {
     } else {
         // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should
         // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should
@@ -212,9 +217,10 @@ static void AllocateSurfaceTexture(GLuint texture, const FormatTuple& format_tup
 
 
 CachedSurface::CachedSurface(const SurfaceParams& params) : params(params), gl_buffer_size(0) {
 CachedSurface::CachedSurface(const SurfaceParams& params) : params(params), gl_buffer_size(0) {
     texture.Create();
     texture.Create();
+    const auto& rect{params.GetRect()};
     AllocateSurfaceTexture(texture.handle,
     AllocateSurfaceTexture(texture.handle,
-                           GetFormatTuple(params.pixel_format, params.component_type), params.width,
-                           params.height);
+                           GetFormatTuple(params.pixel_format, params.component_type),
+                           rect.GetWidth(), rect.GetHeight());
 }
 }
 
 
 MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 64, 192));
 MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 64, 192));
@@ -225,21 +231,23 @@ void CachedSurface::LoadGLBuffer() {
 
 
     ASSERT(texture_src_data);
     ASSERT(texture_src_data);
 
 
-    if (!gl_buffer) {
-        gl_buffer_size = params.width * params.height * GetGLBytesPerPixel(params.pixel_format);
-        gl_buffer.reset(new u8[gl_buffer_size]);
-    }
+    gl_buffer.resize(params.width * params.height * GetGLBytesPerPixel(params.pixel_format));
 
 
     MICROPROFILE_SCOPE(OpenGL_SurfaceLoad);
     MICROPROFILE_SCOPE(OpenGL_SurfaceLoad);
 
 
     if (!params.is_tiled) {
     if (!params.is_tiled) {
         const u32 bytes_per_pixel{params.GetFormatBpp() >> 3};
         const u32 bytes_per_pixel{params.GetFormatBpp() >> 3};
 
 
-        std::memcpy(&gl_buffer[0], texture_src_data,
+        std::memcpy(gl_buffer.data(), texture_src_data,
                     bytes_per_pixel * params.width * params.height);
                     bytes_per_pixel * params.width * params.height);
     } else {
     } else {
         morton_to_gl_fns[static_cast<size_t>(params.pixel_format)](
         morton_to_gl_fns[static_cast<size_t>(params.pixel_format)](
-            params.width, params.block_height, params.height, &gl_buffer[0], params.addr);
+            params.width, params.block_height, params.height, gl_buffer.data(), params.addr);
+    }
+
+    if (IsPixelFormatASTC(params.pixel_format)) {
+        // ASTC formats are converted to RGBA8 in software, as most PC GPUs do not support this
+        ConvertASTCToRGBA8(gl_buffer, params.pixel_format, params.width, params.height);
     }
     }
 }
 }
 
 
@@ -248,16 +256,16 @@ void CachedSurface::FlushGLBuffer() {
     u8* const dst_buffer = Memory::GetPointer(params.GetCpuAddr());
     u8* const dst_buffer = Memory::GetPointer(params.GetCpuAddr());
 
 
     ASSERT(dst_buffer);
     ASSERT(dst_buffer);
-    ASSERT(gl_buffer_size ==
+    ASSERT(gl_buffer.size() ==
            params.width * params.height * GetGLBytesPerPixel(params.pixel_format));
            params.width * params.height * GetGLBytesPerPixel(params.pixel_format));
 
 
     MICROPROFILE_SCOPE(OpenGL_SurfaceFlush);
     MICROPROFILE_SCOPE(OpenGL_SurfaceFlush);
 
 
     if (!params.is_tiled) {
     if (!params.is_tiled) {
-        std::memcpy(dst_buffer, &gl_buffer[0], params.size_in_bytes);
+        std::memcpy(dst_buffer, gl_buffer.data(), params.size_in_bytes);
     } else {
     } else {
         gl_to_morton_fns[static_cast<size_t>(params.pixel_format)](
         gl_to_morton_fns[static_cast<size_t>(params.pixel_format)](
-            params.width, params.block_height, params.height, &gl_buffer[0], params.addr);
+            params.width, params.block_height, params.height, gl_buffer.data(), params.addr);
     }
     }
 }
 }
 
 
@@ -268,7 +276,7 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle
 
 
     MICROPROFILE_SCOPE(OpenGL_TextureUL);
     MICROPROFILE_SCOPE(OpenGL_TextureUL);
 
 
-    ASSERT(gl_buffer_size ==
+    ASSERT(gl_buffer.size() ==
            params.width * params.height * GetGLBytesPerPixel(params.pixel_format));
            params.width * params.height * GetGLBytesPerPixel(params.pixel_format));
 
 
     const auto& rect{params.GetRect()};
     const auto& rect{params.GetRect()};
@@ -315,10 +323,7 @@ void CachedSurface::DownloadGLTexture(GLuint read_fb_handle, GLuint draw_fb_hand
 
 
     MICROPROFILE_SCOPE(OpenGL_TextureDL);
     MICROPROFILE_SCOPE(OpenGL_TextureDL);
 
 
-    if (!gl_buffer) {
-        gl_buffer_size = params.width * params.height * GetGLBytesPerPixel(params.pixel_format);
-        gl_buffer.reset(new u8[gl_buffer_size]);
-    }
+    gl_buffer.resize(params.width * params.height * GetGLBytesPerPixel(params.pixel_format));
 
 
     OpenGLState state = OpenGLState::GetCurState();
     OpenGLState state = OpenGLState::GetCurState();
     OpenGLState prev_state = state;
     OpenGLState prev_state = state;

+ 5 - 6
src/video_core/renderer_opengl/gl_rasterizer_cache.h

@@ -7,6 +7,7 @@
 #include <array>
 #include <array>
 #include <map>
 #include <map>
 #include <memory>
 #include <memory>
+#include <vector>
 
 
 #include "common/common_types.h"
 #include "common/common_types.h"
 #include "common/hash.h"
 #include "common/hash.h"
@@ -79,7 +80,7 @@ struct SurfaceParams {
             4, // DXT23
             4, // DXT23
             4, // DXT45
             4, // DXT45
             4, // DXN1
             4, // DXN1
-            1, // ASTC_2D_4X4
+            4, // ASTC_2D_4X4
         }};
         }};
 
 
         ASSERT(static_cast<size_t>(format) < compression_factor_table.size());
         ASSERT(static_cast<size_t>(format) < compression_factor_table.size());
@@ -242,9 +243,7 @@ struct SurfaceParams {
         return SurfaceType::Invalid;
         return SurfaceType::Invalid;
     }
     }
 
 
-    MathUtil::Rectangle<u32> GetRect() const {
-        return {0, height, width, 0};
-    }
+    MathUtil::Rectangle<u32> GetRect() const;
 
 
     size_t SizeInBytes() const {
     size_t SizeInBytes() const {
         const u32 compression_factor{GetCompressionFactor(pixel_format)};
         const u32 compression_factor{GetCompressionFactor(pixel_format)};
@@ -269,6 +268,7 @@ struct SurfaceParams {
     SurfaceType type;
     SurfaceType type;
     u32 width;
     u32 width;
     u32 height;
     u32 height;
+    u32 unaligned_height;
     size_t size_in_bytes;
     size_t size_in_bytes;
 };
 };
 
 
@@ -318,8 +318,7 @@ public:
 
 
 private:
 private:
     OGLTexture texture;
     OGLTexture texture;
-    std::unique_ptr<u8[]> gl_buffer;
-    size_t gl_buffer_size;
+    std::vector<u8> gl_buffer;
     SurfaceParams params;
     SurfaceParams params;
 };
 };