From 35ca6274f4bee69dd76ff2aa165186b01594eaba Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Tue, 16 Nov 2021 18:19:47 -0500 Subject: [PATCH 1/4] gl_texture_cache: Rename BGRCopyPass to FormatConversionPass --- .../renderer_opengl/gl_texture_cache.cpp | 23 ++++++++----------- .../renderer_opengl/gl_texture_cache.h | 16 ++++++------- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 2f7d98d8bf..85a02d8594 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -538,7 +538,7 @@ void TextureCacheRuntime::EmulateCopyImage(Image& dst, Image& src, ASSERT(src.info.type == ImageType::e3D); util_shaders.CopyBC4(dst, src, copies); } else if (IsPixelFormatBGR(dst.info.format) || IsPixelFormatBGR(src.info.format)) { - bgr_copy_pass.CopyBGR(dst, src, copies); + format_conversion_pass.ConvertImage(dst, src, copies); } else { UNREACHABLE(); } @@ -1286,32 +1286,29 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span copies) { - static constexpr VideoCommon::Offset3D zero_offset{0, 0, 0}; +void FormatConversionPass::ConvertImage(Image& dst_image, Image& src_image, + std::span copies) { const u32 img_bpp = BytesPerBlock(src_image.info.format); for (const ImageCopy& copy : copies) { - ASSERT(copy.src_offset == zero_offset); - ASSERT(copy.dst_offset == zero_offset); const u32 num_src_layers = static_cast(copy.src_subresource.num_layers); const u32 copy_size = copy.extent.width * copy.extent.height * num_src_layers * img_bpp; - if (bgr_pbo_size < copy_size) { - bgr_pbo.Create(); - bgr_pbo_size = copy_size; - glNamedBufferData(bgr_pbo.handle, bgr_pbo_size, nullptr, GL_STREAM_COPY); + if (pbo_size < copy_size) { + intermediate_pbo.Create(); + pbo_size = copy_size; + glNamedBufferData(intermediate_pbo.handle, pbo_size, nullptr, GL_STREAM_COPY); } // Copy from source to PBO glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ROW_LENGTH, copy.extent.width); - glBindBuffer(GL_PIXEL_PACK_BUFFER, bgr_pbo.handle); + glBindBuffer(GL_PIXEL_PACK_BUFFER, intermediate_pbo.handle); glGetTextureSubImage(src_image.Handle(), 0, 0, 0, 0, copy.extent.width, copy.extent.height, num_src_layers, src_image.GlFormat(), src_image.GlType(), - static_cast(bgr_pbo_size), nullptr); + static_cast(pbo_size), nullptr); // Copy from PBO to destination in desired GL format glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, copy.extent.width); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bgr_pbo.handle); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, intermediate_pbo.handle); glTextureSubImage3D(dst_image.Handle(), 0, 0, 0, 0, copy.extent.width, copy.extent.height, copy.dst_subresource.num_layers, dst_image.GlFormat(), dst_image.GlType(), nullptr); diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 1bb7625685..b89c183a91 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h @@ -52,17 +52,17 @@ struct FormatProperties { bool is_compressed; }; -class BGRCopyPass { +class FormatConversionPass { public: - BGRCopyPass() = default; - ~BGRCopyPass() = default; + FormatConversionPass() = default; + ~FormatConversionPass() = default; - void CopyBGR(Image& dst_image, Image& src_image, - std::span copies); + void ConvertImage(Image& dst_image, Image& src_image, + std::span copies); private: - OGLBuffer bgr_pbo; - size_t bgr_pbo_size{}; + OGLBuffer intermediate_pbo; + size_t pbo_size{}; }; class TextureCacheRuntime { @@ -144,7 +144,7 @@ private: const Device& device; StateTracker& state_tracker; UtilShaders util_shaders; - BGRCopyPass bgr_copy_pass; + FormatConversionPass format_conversion_pass; std::array, 3> format_properties; bool has_broken_texture_view_formats = false; From 50c3d530761a8477a1300e69158ce28595530fbf Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Tue, 16 Nov 2021 18:32:36 -0500 Subject: [PATCH 2/4] gl_texture_cache: Make FormatConversionPass more generic This allows the usage of the FormatConversionPass to be applied to more than the previously used BGR conversion scenarios. --- .../renderer_opengl/gl_texture_cache.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 85a02d8594..3bfd82cf04 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -1288,10 +1288,14 @@ Framebuffer::~Framebuffer() = default; void FormatConversionPass::ConvertImage(Image& dst_image, Image& src_image, std::span copies) { + const GLenum dst_target = ImageTarget(dst_image.info); + const GLenum src_target = ImageTarget(src_image.info); const u32 img_bpp = BytesPerBlock(src_image.info.format); for (const ImageCopy& copy : copies) { - const u32 num_src_layers = static_cast(copy.src_subresource.num_layers); - const u32 copy_size = copy.extent.width * copy.extent.height * num_src_layers * img_bpp; + const auto src_origin = MakeCopyOrigin(copy.src_offset, copy.src_subresource, src_target); + const auto dst_origin = MakeCopyOrigin(copy.dst_offset, copy.dst_subresource, dst_target); + const auto region = MakeCopyRegion(copy.extent, copy.dst_subresource, dst_target); + const u32 copy_size = region.width * region.height * region.depth * img_bpp; if (pbo_size < copy_size) { intermediate_pbo.Create(); pbo_size = copy_size; @@ -1301,17 +1305,18 @@ void FormatConversionPass::ConvertImage(Image& dst_image, Image& src_image, glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ROW_LENGTH, copy.extent.width); glBindBuffer(GL_PIXEL_PACK_BUFFER, intermediate_pbo.handle); - glGetTextureSubImage(src_image.Handle(), 0, 0, 0, 0, copy.extent.width, copy.extent.height, - num_src_layers, src_image.GlFormat(), src_image.GlType(), + glGetTextureSubImage(src_image.Handle(), src_origin.level, src_origin.x, src_origin.y, + src_origin.z, region.width, region.height, region.depth, + src_image.GlFormat(), src_image.GlType(), static_cast(pbo_size), nullptr); // Copy from PBO to destination in desired GL format glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, copy.extent.width); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, intermediate_pbo.handle); - glTextureSubImage3D(dst_image.Handle(), 0, 0, 0, 0, copy.extent.width, copy.extent.height, - copy.dst_subresource.num_layers, dst_image.GlFormat(), - dst_image.GlType(), nullptr); + glTextureSubImage3D(dst_image.Handle(), dst_origin.level, dst_origin.x, dst_origin.y, + dst_origin.z, region.width, region.height, region.depth, + dst_image.GlFormat(), dst_image.GlType(), nullptr); } } From 20ed7ba4417a165f3af41d93a0e838c057c81c84 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Tue, 16 Nov 2021 18:56:40 -0500 Subject: [PATCH 3/4] texture_cache: Use pixel format conversion when supported by the runtime --- src/video_core/renderer_opengl/gl_texture_cache.cpp | 6 ++++++ src/video_core/renderer_opengl/gl_texture_cache.h | 3 +++ src/video_core/renderer_vulkan/vk_texture_cache.h | 1 + src/video_core/texture_cache/texture_cache.h | 3 +++ src/video_core/texture_cache/texture_cache_base.h | 2 ++ 5 files changed, 15 insertions(+) diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 3bfd82cf04..e560111c38 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -522,6 +522,12 @@ void TextureCacheRuntime::CopyImage(Image& dst_image, Image& src_image, } } +void TextureCacheRuntime::ConvertImage(Image& dst, Image& src, + std::span copies) { + LOG_DEBUG(Render_OpenGL, "Converting {} to {}", src.info.format, dst.info.format); + format_conversion_pass.ConvertImage(dst, src, copies); +} + bool TextureCacheRuntime::CanImageBeCopied(const Image& dst, const Image& src) { if (dst.info.type == ImageType::e3D && dst.info.format == PixelFormat::BC4_UNORM) { return false; diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index b89c183a91..578f8d5231 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h @@ -86,6 +86,8 @@ public: void CopyImage(Image& dst, Image& src, std::span copies); + void ConvertImage(Image& dst, Image& src, std::span copies); + void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled) { UNIMPLEMENTED(); } @@ -336,6 +338,7 @@ struct TextureCacheParams { static constexpr bool FRAMEBUFFER_BLITS = true; static constexpr bool HAS_EMULATED_COPIES = true; static constexpr bool HAS_DEVICE_MEMORY_INFO = true; + static constexpr bool HAS_PIXEL_FORMAT_CONVERSIONS = true; using Runtime = OpenGL::TextureCacheRuntime; using Image = OpenGL::Image; diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index ff28b4e962..f5f8f9a74a 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -316,6 +316,7 @@ struct TextureCacheParams { static constexpr bool FRAMEBUFFER_BLITS = false; static constexpr bool HAS_EMULATED_COPIES = false; static constexpr bool HAS_DEVICE_MEMORY_INFO = true; + static constexpr bool HAS_PIXEL_FORMAT_CONVERSIONS = false; using Runtime = Vulkan::TextureCacheRuntime; using Image = Vulkan::Image; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 4d2874bf2f..241f71a91f 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -1759,6 +1759,9 @@ void TextureCache

::CopyImage(ImageId dst_id, ImageId src_id, std::vector Date: Wed, 17 Nov 2021 23:49:44 -0500 Subject: [PATCH 4/4] gl_texture_cache: Round format conversion PBO to next power of 2 --- src/video_core/renderer_opengl/gl_texture_cache.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index e560111c38..6956535e5e 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -396,6 +396,10 @@ OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_form UNREACHABLE_MSG("Invalid image format={}", format); return GL_R32UI; } + +[[nodiscard]] u32 NextPow2(u32 value) { + return 1U << (32U - std::countl_zero(value - 1U)); +} } // Anonymous namespace ImageBufferMap::~ImageBufferMap() { @@ -1304,7 +1308,7 @@ void FormatConversionPass::ConvertImage(Image& dst_image, Image& src_image, const u32 copy_size = region.width * region.height * region.depth * img_bpp; if (pbo_size < copy_size) { intermediate_pbo.Create(); - pbo_size = copy_size; + pbo_size = NextPow2(copy_size); glNamedBufferData(intermediate_pbo.handle, pbo_size, nullptr, GL_STREAM_COPY); } // Copy from source to PBO