diff options
| author | 2021-11-18 11:30:47 -0800 | |
|---|---|---|
| committer | 2021-11-18 11:30:47 -0800 | |
| commit | 0bc46fedd617f6a42c53716680ed99d8f42bf99a (patch) | |
| tree | aec333a588d638492cca77d7814cdc5379d2b6c0 | |
| parent | Merge pull request #7353 from v1993/no-more-epilepsy (diff) | |
| parent | gl_texture_cache: Round format conversion PBO to next power of 2 (diff) | |
| download | yuzu-0bc46fedd617f6a42c53716680ed99d8f42bf99a.tar.gz yuzu-0bc46fedd617f6a42c53716680ed99d8f42bf99a.tar.xz yuzu-0bc46fedd617f6a42c53716680ed99d8f42bf99a.zip | |
Merge pull request #7349 from ameerj/ogl-convert-image
gl_texture_cache: Implement pixel format conversions for copies
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.cpp | 52 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.h | 19 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.h | 1 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 3 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache_base.h | 2 |
5 files changed, 49 insertions, 28 deletions
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 2f7d98d8b..6956535e5 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 | |||
| 396 | UNREACHABLE_MSG("Invalid image format={}", format); | 396 | UNREACHABLE_MSG("Invalid image format={}", format); |
| 397 | return GL_R32UI; | 397 | return GL_R32UI; |
| 398 | } | 398 | } |
| 399 | |||
| 400 | [[nodiscard]] u32 NextPow2(u32 value) { | ||
| 401 | return 1U << (32U - std::countl_zero(value - 1U)); | ||
| 402 | } | ||
| 399 | } // Anonymous namespace | 403 | } // Anonymous namespace |
| 400 | 404 | ||
| 401 | ImageBufferMap::~ImageBufferMap() { | 405 | ImageBufferMap::~ImageBufferMap() { |
| @@ -522,6 +526,12 @@ void TextureCacheRuntime::CopyImage(Image& dst_image, Image& src_image, | |||
| 522 | } | 526 | } |
| 523 | } | 527 | } |
| 524 | 528 | ||
| 529 | void TextureCacheRuntime::ConvertImage(Image& dst, Image& src, | ||
| 530 | std::span<const VideoCommon::ImageCopy> copies) { | ||
| 531 | LOG_DEBUG(Render_OpenGL, "Converting {} to {}", src.info.format, dst.info.format); | ||
| 532 | format_conversion_pass.ConvertImage(dst, src, copies); | ||
| 533 | } | ||
| 534 | |||
| 525 | bool TextureCacheRuntime::CanImageBeCopied(const Image& dst, const Image& src) { | 535 | bool TextureCacheRuntime::CanImageBeCopied(const Image& dst, const Image& src) { |
| 526 | if (dst.info.type == ImageType::e3D && dst.info.format == PixelFormat::BC4_UNORM) { | 536 | if (dst.info.type == ImageType::e3D && dst.info.format == PixelFormat::BC4_UNORM) { |
| 527 | return false; | 537 | return false; |
| @@ -538,7 +548,7 @@ void TextureCacheRuntime::EmulateCopyImage(Image& dst, Image& src, | |||
| 538 | ASSERT(src.info.type == ImageType::e3D); | 548 | ASSERT(src.info.type == ImageType::e3D); |
| 539 | util_shaders.CopyBC4(dst, src, copies); | 549 | util_shaders.CopyBC4(dst, src, copies); |
| 540 | } else if (IsPixelFormatBGR(dst.info.format) || IsPixelFormatBGR(src.info.format)) { | 550 | } else if (IsPixelFormatBGR(dst.info.format) || IsPixelFormatBGR(src.info.format)) { |
| 541 | bgr_copy_pass.CopyBGR(dst, src, copies); | 551 | format_conversion_pass.ConvertImage(dst, src, copies); |
| 542 | } else { | 552 | } else { |
| 543 | UNREACHABLE(); | 553 | UNREACHABLE(); |
| 544 | } | 554 | } |
| @@ -1286,35 +1296,37 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM | |||
| 1286 | 1296 | ||
| 1287 | Framebuffer::~Framebuffer() = default; | 1297 | Framebuffer::~Framebuffer() = default; |
| 1288 | 1298 | ||
| 1289 | void BGRCopyPass::CopyBGR(Image& dst_image, Image& src_image, | 1299 | void FormatConversionPass::ConvertImage(Image& dst_image, Image& src_image, |
| 1290 | std::span<const VideoCommon::ImageCopy> copies) { | 1300 | std::span<const VideoCommon::ImageCopy> copies) { |
| 1291 | static constexpr VideoCommon::Offset3D zero_offset{0, 0, 0}; | 1301 | const GLenum dst_target = ImageTarget(dst_image.info); |
| 1302 | const GLenum src_target = ImageTarget(src_image.info); | ||
| 1292 | const u32 img_bpp = BytesPerBlock(src_image.info.format); | 1303 | const u32 img_bpp = BytesPerBlock(src_image.info.format); |
| 1293 | for (const ImageCopy& copy : copies) { | 1304 | for (const ImageCopy& copy : copies) { |
| 1294 | ASSERT(copy.src_offset == zero_offset); | 1305 | const auto src_origin = MakeCopyOrigin(copy.src_offset, copy.src_subresource, src_target); |
| 1295 | ASSERT(copy.dst_offset == zero_offset); | 1306 | const auto dst_origin = MakeCopyOrigin(copy.dst_offset, copy.dst_subresource, dst_target); |
| 1296 | const u32 num_src_layers = static_cast<u32>(copy.src_subresource.num_layers); | 1307 | const auto region = MakeCopyRegion(copy.extent, copy.dst_subresource, dst_target); |
| 1297 | const u32 copy_size = copy.extent.width * copy.extent.height * num_src_layers * img_bpp; | 1308 | const u32 copy_size = region.width * region.height * region.depth * img_bpp; |
| 1298 | if (bgr_pbo_size < copy_size) { | 1309 | if (pbo_size < copy_size) { |
| 1299 | bgr_pbo.Create(); | 1310 | intermediate_pbo.Create(); |
| 1300 | bgr_pbo_size = copy_size; | 1311 | pbo_size = NextPow2(copy_size); |
| 1301 | glNamedBufferData(bgr_pbo.handle, bgr_pbo_size, nullptr, GL_STREAM_COPY); | 1312 | glNamedBufferData(intermediate_pbo.handle, pbo_size, nullptr, GL_STREAM_COPY); |
| 1302 | } | 1313 | } |
| 1303 | // Copy from source to PBO | 1314 | // Copy from source to PBO |
| 1304 | glPixelStorei(GL_PACK_ALIGNMENT, 1); | 1315 | glPixelStorei(GL_PACK_ALIGNMENT, 1); |
| 1305 | glPixelStorei(GL_PACK_ROW_LENGTH, copy.extent.width); | 1316 | glPixelStorei(GL_PACK_ROW_LENGTH, copy.extent.width); |
| 1306 | glBindBuffer(GL_PIXEL_PACK_BUFFER, bgr_pbo.handle); | 1317 | glBindBuffer(GL_PIXEL_PACK_BUFFER, intermediate_pbo.handle); |
| 1307 | glGetTextureSubImage(src_image.Handle(), 0, 0, 0, 0, copy.extent.width, copy.extent.height, | 1318 | glGetTextureSubImage(src_image.Handle(), src_origin.level, src_origin.x, src_origin.y, |
| 1308 | num_src_layers, src_image.GlFormat(), src_image.GlType(), | 1319 | src_origin.z, region.width, region.height, region.depth, |
| 1309 | static_cast<GLsizei>(bgr_pbo_size), nullptr); | 1320 | src_image.GlFormat(), src_image.GlType(), |
| 1321 | static_cast<GLsizei>(pbo_size), nullptr); | ||
| 1310 | 1322 | ||
| 1311 | // Copy from PBO to destination in desired GL format | 1323 | // Copy from PBO to destination in desired GL format |
| 1312 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | 1324 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
| 1313 | glPixelStorei(GL_UNPACK_ROW_LENGTH, copy.extent.width); | 1325 | glPixelStorei(GL_UNPACK_ROW_LENGTH, copy.extent.width); |
| 1314 | glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bgr_pbo.handle); | 1326 | glBindBuffer(GL_PIXEL_UNPACK_BUFFER, intermediate_pbo.handle); |
| 1315 | glTextureSubImage3D(dst_image.Handle(), 0, 0, 0, 0, copy.extent.width, copy.extent.height, | 1327 | glTextureSubImage3D(dst_image.Handle(), dst_origin.level, dst_origin.x, dst_origin.y, |
| 1316 | copy.dst_subresource.num_layers, dst_image.GlFormat(), | 1328 | dst_origin.z, region.width, region.height, region.depth, |
| 1317 | dst_image.GlType(), nullptr); | 1329 | dst_image.GlFormat(), dst_image.GlType(), nullptr); |
| 1318 | } | 1330 | } |
| 1319 | } | 1331 | } |
| 1320 | 1332 | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 1bb762568..578f8d523 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 { | |||
| 52 | bool is_compressed; | 52 | bool is_compressed; |
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | class BGRCopyPass { | 55 | class FormatConversionPass { |
| 56 | public: | 56 | public: |
| 57 | BGRCopyPass() = default; | 57 | FormatConversionPass() = default; |
| 58 | ~BGRCopyPass() = default; | 58 | ~FormatConversionPass() = default; |
| 59 | 59 | ||
| 60 | void CopyBGR(Image& dst_image, Image& src_image, | 60 | void ConvertImage(Image& dst_image, Image& src_image, |
| 61 | std::span<const VideoCommon::ImageCopy> copies); | 61 | std::span<const VideoCommon::ImageCopy> copies); |
| 62 | 62 | ||
| 63 | private: | 63 | private: |
| 64 | OGLBuffer bgr_pbo; | 64 | OGLBuffer intermediate_pbo; |
| 65 | size_t bgr_pbo_size{}; | 65 | size_t pbo_size{}; |
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | class TextureCacheRuntime { | 68 | class TextureCacheRuntime { |
| @@ -86,6 +86,8 @@ public: | |||
| 86 | 86 | ||
| 87 | void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); | 87 | void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); |
| 88 | 88 | ||
| 89 | void ConvertImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); | ||
| 90 | |||
| 89 | void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled) { | 91 | void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled) { |
| 90 | UNIMPLEMENTED(); | 92 | UNIMPLEMENTED(); |
| 91 | } | 93 | } |
| @@ -144,7 +146,7 @@ private: | |||
| 144 | const Device& device; | 146 | const Device& device; |
| 145 | StateTracker& state_tracker; | 147 | StateTracker& state_tracker; |
| 146 | UtilShaders util_shaders; | 148 | UtilShaders util_shaders; |
| 147 | BGRCopyPass bgr_copy_pass; | 149 | FormatConversionPass format_conversion_pass; |
| 148 | 150 | ||
| 149 | std::array<std::unordered_map<GLenum, FormatProperties>, 3> format_properties; | 151 | std::array<std::unordered_map<GLenum, FormatProperties>, 3> format_properties; |
| 150 | bool has_broken_texture_view_formats = false; | 152 | bool has_broken_texture_view_formats = false; |
| @@ -336,6 +338,7 @@ struct TextureCacheParams { | |||
| 336 | static constexpr bool FRAMEBUFFER_BLITS = true; | 338 | static constexpr bool FRAMEBUFFER_BLITS = true; |
| 337 | static constexpr bool HAS_EMULATED_COPIES = true; | 339 | static constexpr bool HAS_EMULATED_COPIES = true; |
| 338 | static constexpr bool HAS_DEVICE_MEMORY_INFO = true; | 340 | static constexpr bool HAS_DEVICE_MEMORY_INFO = true; |
| 341 | static constexpr bool HAS_PIXEL_FORMAT_CONVERSIONS = true; | ||
| 339 | 342 | ||
| 340 | using Runtime = OpenGL::TextureCacheRuntime; | 343 | using Runtime = OpenGL::TextureCacheRuntime; |
| 341 | using Image = OpenGL::Image; | 344 | 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 ff28b4e96..f5f8f9a74 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 { | |||
| 316 | static constexpr bool FRAMEBUFFER_BLITS = false; | 316 | static constexpr bool FRAMEBUFFER_BLITS = false; |
| 317 | static constexpr bool HAS_EMULATED_COPIES = false; | 317 | static constexpr bool HAS_EMULATED_COPIES = false; |
| 318 | static constexpr bool HAS_DEVICE_MEMORY_INFO = true; | 318 | static constexpr bool HAS_DEVICE_MEMORY_INFO = true; |
| 319 | static constexpr bool HAS_PIXEL_FORMAT_CONVERSIONS = false; | ||
| 319 | 320 | ||
| 320 | using Runtime = Vulkan::TextureCacheRuntime; | 321 | using Runtime = Vulkan::TextureCacheRuntime; |
| 321 | using Image = Vulkan::Image; | 322 | 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 4d2874bf2..241f71a91 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<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag | |||
| 1759 | } | 1759 | } |
| 1760 | UNIMPLEMENTED_IF(dst.info.type != ImageType::e2D); | 1760 | UNIMPLEMENTED_IF(dst.info.type != ImageType::e2D); |
| 1761 | UNIMPLEMENTED_IF(src.info.type != ImageType::e2D); | 1761 | UNIMPLEMENTED_IF(src.info.type != ImageType::e2D); |
| 1762 | if constexpr (HAS_PIXEL_FORMAT_CONVERSIONS) { | ||
| 1763 | return runtime.ConvertImage(dst, src, copies); | ||
| 1764 | } | ||
| 1762 | for (const ImageCopy& copy : copies) { | 1765 | for (const ImageCopy& copy : copies) { |
| 1763 | UNIMPLEMENTED_IF(copy.dst_subresource.num_layers != 1); | 1766 | UNIMPLEMENTED_IF(copy.dst_subresource.num_layers != 1); |
| 1764 | UNIMPLEMENTED_IF(copy.src_subresource.num_layers != 1); | 1767 | UNIMPLEMENTED_IF(copy.src_subresource.num_layers != 1); |
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 643ad811c..a9504c0e8 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h | |||
| @@ -59,6 +59,8 @@ class TextureCache { | |||
| 59 | static constexpr bool HAS_EMULATED_COPIES = P::HAS_EMULATED_COPIES; | 59 | static constexpr bool HAS_EMULATED_COPIES = P::HAS_EMULATED_COPIES; |
| 60 | /// True when the API can provide info about the memory of the device. | 60 | /// True when the API can provide info about the memory of the device. |
| 61 | static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO; | 61 | static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO; |
| 62 | /// True when the API provides utilities for pixel format conversions. | ||
| 63 | static constexpr bool HAS_PIXEL_FORMAT_CONVERSIONS = P::HAS_PIXEL_FORMAT_CONVERSIONS; | ||
| 62 | 64 | ||
| 63 | static constexpr u64 DEFAULT_EXPECTED_MEMORY = 1_GiB; | 65 | static constexpr u64 DEFAULT_EXPECTED_MEMORY = 1_GiB; |
| 64 | static constexpr u64 DEFAULT_CRITICAL_MEMORY = 2_GiB; | 66 | static constexpr u64 DEFAULT_CRITICAL_MEMORY = 2_GiB; |