summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp52
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h19
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h1
-rw-r--r--src/video_core/texture_cache/texture_cache.h3
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h2
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
401ImageBufferMap::~ImageBufferMap() { 405ImageBufferMap::~ImageBufferMap() {
@@ -522,6 +526,12 @@ void TextureCacheRuntime::CopyImage(Image& dst_image, Image& src_image,
522 } 526 }
523} 527}
524 528
529void 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
525bool TextureCacheRuntime::CanImageBeCopied(const Image& dst, const Image& src) { 535bool 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
1287Framebuffer::~Framebuffer() = default; 1297Framebuffer::~Framebuffer() = default;
1288 1298
1289void BGRCopyPass::CopyBGR(Image& dst_image, Image& src_image, 1299void 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
55class BGRCopyPass { 55class FormatConversionPass {
56public: 56public:
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
63private: 63private:
64 OGLBuffer bgr_pbo; 64 OGLBuffer intermediate_pbo;
65 size_t bgr_pbo_size{}; 65 size_t pbo_size{};
66}; 66};
67 67
68class TextureCacheRuntime { 68class 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;