From 8af1ae46aa5a9303b21839b446d2ebf17ee12802 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 26 Jun 2018 15:05:13 -0400 Subject: [PATCH] gl_rasterizer_cache: Various fixes for ASTC handling. --- .../renderer_opengl/gl_rasterizer_cache.cpp | 63 ++++++++++--------- .../renderer_opengl/gl_rasterizer_cache.h | 11 ++-- 2 files changed, 39 insertions(+), 35 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 59f1a89c9e..bd35bdb02c 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -41,6 +41,7 @@ struct FormatTuple { params.type = GetFormatType(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.unaligned_height = config.tic.Height(); params.size_in_bytes = params.SizeInBytes(); return params; } @@ -57,6 +58,7 @@ struct FormatTuple { params.type = GetFormatType(params.pixel_format); params.width = config.width; params.height = config.height; + params.unaligned_height = config.height; params.size_in_bytes = params.SizeInBytes(); return params; } @@ -108,20 +110,29 @@ static bool IsPixelFormatASTC(PixelFormat format) { } } -static void ConvertASTCToRGBA8(std::vector& data, PixelFormat format, u32 width, u32 height) { - u32 block_width{}; - u32 block_height{}; - +static std::pair GetASTCBlockSize(PixelFormat format) { switch (format) { case PixelFormat::ASTC_2D_4X4: - block_width = 4; - block_height = 4; - break; + return {4, 4}; default: NGLOG_CRITICAL(HW_GPU, "Unhandled format: {}", static_cast(format)); UNREACHABLE(); } +} +MathUtil::Rectangle 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& 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); } @@ -136,12 +147,6 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, Tegra:: *gpu.memory_manager->GpuToCpuAddress(addr), 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()); } else { // 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) { texture.Create(); + const auto& rect{params.GetRect()}; 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)); @@ -225,21 +231,23 @@ void CachedSurface::LoadGLBuffer() { 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); if (!params.is_tiled) { 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); } else { morton_to_gl_fns[static_cast(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()); ASSERT(dst_buffer); - ASSERT(gl_buffer_size == + ASSERT(gl_buffer.size() == params.width * params.height * GetGLBytesPerPixel(params.pixel_format)); MICROPROFILE_SCOPE(OpenGL_SurfaceFlush); 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 { gl_to_morton_fns[static_cast(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); - ASSERT(gl_buffer_size == + ASSERT(gl_buffer.size() == params.width * params.height * GetGLBytesPerPixel(params.pixel_format)); const auto& rect{params.GetRect()}; @@ -315,10 +323,7 @@ void CachedSurface::DownloadGLTexture(GLuint read_fb_handle, GLuint draw_fb_hand 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 prev_state = state; diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index bf36f6c249..84bdec652a 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "common/common_types.h" #include "common/hash.h" @@ -79,7 +80,7 @@ struct SurfaceParams { 4, // DXT23 4, // DXT45 4, // DXN1 - 1, // ASTC_2D_4X4 + 4, // ASTC_2D_4X4 }}; ASSERT(static_cast(format) < compression_factor_table.size()); @@ -242,9 +243,7 @@ struct SurfaceParams { return SurfaceType::Invalid; } - MathUtil::Rectangle GetRect() const { - return {0, height, width, 0}; - } + MathUtil::Rectangle GetRect() const; size_t SizeInBytes() const { const u32 compression_factor{GetCompressionFactor(pixel_format)}; @@ -269,6 +268,7 @@ struct SurfaceParams { SurfaceType type; u32 width; u32 height; + u32 unaligned_height; size_t size_in_bytes; }; @@ -318,8 +318,7 @@ public: private: OGLTexture texture; - std::unique_ptr gl_buffer; - size_t gl_buffer_size; + std::vector gl_buffer; SurfaceParams params; };