diff options
Diffstat (limited to 'src')
18 files changed, 595 insertions, 23 deletions
diff --git a/src/common/bit_util.h b/src/common/bit_util.h index 64520ca4e..eef8c1c5a 100644 --- a/src/common/bit_util.h +++ b/src/common/bit_util.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <bit> | 7 | #include <bit> |
| 8 | #include <climits> | 8 | #include <climits> |
| 9 | #include <cstddef> | 9 | #include <cstddef> |
| 10 | #include <type_traits> | ||
| 10 | 11 | ||
| 11 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 12 | 13 | ||
| @@ -44,4 +45,10 @@ template <typename T> | |||
| 44 | return static_cast<u32>(log2_f + static_cast<u64>((value ^ (1ULL << log2_f)) != 0ULL)); | 45 | return static_cast<u32>(log2_f + static_cast<u64>((value ^ (1ULL << log2_f)) != 0ULL)); |
| 45 | } | 46 | } |
| 46 | 47 | ||
| 48 | template <typename T> | ||
| 49 | requires std::is_integral_v<T> | ||
| 50 | [[nodiscard]] T NextPow2(T value) { | ||
| 51 | return static_cast<T>(1ULL << ((8U * sizeof(T)) - std::countl_zero(value - 1U))); | ||
| 52 | } | ||
| 53 | |||
| 47 | } // namespace Common | 54 | } // namespace Common |
diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index d779a967a..1c91999d7 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt | |||
| @@ -10,8 +10,14 @@ set(SHADER_FILES | |||
| 10 | astc_decoder.comp | 10 | astc_decoder.comp |
| 11 | block_linear_unswizzle_2d.comp | 11 | block_linear_unswizzle_2d.comp |
| 12 | block_linear_unswizzle_3d.comp | 12 | block_linear_unswizzle_3d.comp |
| 13 | convert_abgr8_to_d24s8.frag | ||
| 14 | convert_b10g11r11_to_d24s8.frag | ||
| 15 | convert_d24s8_to_abgr8.frag | ||
| 16 | convert_d24s8_to_b10g11r11.frag | ||
| 17 | convert_d24s8_to_r16g16.frag | ||
| 13 | convert_depth_to_float.frag | 18 | convert_depth_to_float.frag |
| 14 | convert_float_to_depth.frag | 19 | convert_float_to_depth.frag |
| 20 | convert_r16g16_to_d24s8.frag | ||
| 15 | full_screen_triangle.vert | 21 | full_screen_triangle.vert |
| 16 | fxaa.frag | 22 | fxaa.frag |
| 17 | fxaa.vert | 23 | fxaa.vert |
diff --git a/src/video_core/host_shaders/convert_abgr8_to_d24s8.frag b/src/video_core/host_shaders/convert_abgr8_to_d24s8.frag new file mode 100644 index 000000000..4e4ab6a26 --- /dev/null +++ b/src/video_core/host_shaders/convert_abgr8_to_d24s8.frag | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 450 | ||
| 6 | #extension GL_ARB_shader_stencil_export : require | ||
| 7 | |||
| 8 | layout(binding = 0) uniform sampler2D color_texture; | ||
| 9 | |||
| 10 | void main() { | ||
| 11 | ivec2 coord = ivec2(gl_FragCoord.xy); | ||
| 12 | uvec4 color = uvec4(texelFetch(color_texture, coord, 0).rgba * (exp2(8) - 1.0f)); | ||
| 13 | uint depth_unorm = (color.r << 16) | (color.g << 8) | color.b; | ||
| 14 | |||
| 15 | gl_FragDepth = float(depth_unorm) / (exp2(24.0) - 1.0f); | ||
| 16 | gl_FragStencilRefARB = int(color.a); | ||
| 17 | } | ||
diff --git a/src/video_core/host_shaders/convert_b10g11r11_to_d24s8.frag b/src/video_core/host_shaders/convert_b10g11r11_to_d24s8.frag new file mode 100644 index 000000000..2999a84cf --- /dev/null +++ b/src/video_core/host_shaders/convert_b10g11r11_to_d24s8.frag | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 450 | ||
| 6 | #extension GL_ARB_shader_stencil_export : require | ||
| 7 | |||
| 8 | layout(binding = 0) uniform sampler2D color_texture; | ||
| 9 | |||
| 10 | void main() { | ||
| 11 | ivec2 coord = ivec2(gl_FragCoord.xy); | ||
| 12 | vec4 color = texelFetch(color_texture, coord, 0).rgba; | ||
| 13 | uint depth_stencil_unorm = (uint(color.b * (exp2(10) - 1.0f)) << 22) | ||
| 14 | | (uint(color.g * (exp2(11) - 1.0f)) << 11) | ||
| 15 | | (uint(color.r * (exp2(11) - 1.0f))); | ||
| 16 | |||
| 17 | gl_FragDepth = float(depth_stencil_unorm >> 8) / (exp2(24.0) - 1.0f); | ||
| 18 | gl_FragStencilRefARB = int(depth_stencil_unorm & 0x00FF); | ||
| 19 | } | ||
diff --git a/src/video_core/host_shaders/convert_d24s8_to_abgr8.frag b/src/video_core/host_shaders/convert_d24s8_to_abgr8.frag new file mode 100644 index 000000000..ff3bf8209 --- /dev/null +++ b/src/video_core/host_shaders/convert_d24s8_to_abgr8.frag | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 450 | ||
| 6 | |||
| 7 | layout(binding = 0) uniform sampler2D depth_tex; | ||
| 8 | layout(binding = 1) uniform isampler2D stencil_tex; | ||
| 9 | |||
| 10 | layout(location = 0) out vec4 color; | ||
| 11 | |||
| 12 | void main() { | ||
| 13 | ivec2 coord = ivec2(gl_FragCoord.xy); | ||
| 14 | uint depth = uint(textureLod(depth_tex, coord, 0).r * (exp2(24.0) - 1.0f)); | ||
| 15 | uint stencil = uint(textureLod(stencil_tex, coord, 0).r); | ||
| 16 | |||
| 17 | color.r = float(depth >> 16) / (exp2(8) - 1.0); | ||
| 18 | color.g = float((depth >> 8) & 0x00FF) / (exp2(8) - 1.0); | ||
| 19 | color.b = float(depth & 0x00FF) / (exp2(8) - 1.0); | ||
| 20 | color.a = float(stencil) / (exp2(8) - 1.0); | ||
| 21 | } | ||
diff --git a/src/video_core/host_shaders/convert_d24s8_to_b10g11r11.frag b/src/video_core/host_shaders/convert_d24s8_to_b10g11r11.frag new file mode 100644 index 000000000..c743d3a13 --- /dev/null +++ b/src/video_core/host_shaders/convert_d24s8_to_b10g11r11.frag | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 450 | ||
| 6 | |||
| 7 | layout(binding = 0) uniform sampler2D depth_tex; | ||
| 8 | layout(binding = 1) uniform isampler2D stencil_tex; | ||
| 9 | |||
| 10 | layout(location = 0) out vec4 color; | ||
| 11 | |||
| 12 | void main() { | ||
| 13 | ivec2 coord = ivec2(gl_FragCoord.xy); | ||
| 14 | uint depth = uint(textureLod(depth_tex, coord, 0).r * (exp2(24.0) - 1.0f)); | ||
| 15 | uint stencil = uint(textureLod(stencil_tex, coord, 0).r); | ||
| 16 | |||
| 17 | color.b = float(depth >> 22) / (exp2(10) - 1.0); | ||
| 18 | color.g = float((depth >> 11) & 0x00FF) / (exp2(11) - 1.0); | ||
| 19 | color.r = float(depth & 0x00FF) / (exp2(11) - 1.0); | ||
| 20 | color.a = 1.0f; | ||
| 21 | } | ||
diff --git a/src/video_core/host_shaders/convert_d24s8_to_r16g16.frag b/src/video_core/host_shaders/convert_d24s8_to_r16g16.frag new file mode 100644 index 000000000..2a9443d3d --- /dev/null +++ b/src/video_core/host_shaders/convert_d24s8_to_r16g16.frag | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 450 | ||
| 6 | |||
| 7 | layout(binding = 0) uniform sampler2D depth_tex; | ||
| 8 | layout(binding = 1) uniform isampler2D stencil_tex; | ||
| 9 | |||
| 10 | layout(location = 0) out vec4 color; | ||
| 11 | |||
| 12 | void main() { | ||
| 13 | ivec2 coord = ivec2(gl_FragCoord.xy); | ||
| 14 | uint depth = uint(textureLod(depth_tex, coord, 0).r * (exp2(24.0) - 1.0f)); | ||
| 15 | uint stencil = uint(textureLod(stencil_tex, coord, 0).r); | ||
| 16 | |||
| 17 | color.r = float(depth >> 16) / (exp2(16) - 1.0); | ||
| 18 | color.g = float((depth >> 16) & 0x00FF) / (exp2(16) - 1.0); | ||
| 19 | color.b = 0.0f; | ||
| 20 | color.a = 1.0f; | ||
| 21 | } | ||
diff --git a/src/video_core/host_shaders/convert_r16g16_to_d24s8.frag b/src/video_core/host_shaders/convert_r16g16_to_d24s8.frag new file mode 100644 index 000000000..3df70575e --- /dev/null +++ b/src/video_core/host_shaders/convert_r16g16_to_d24s8.frag | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 450 | ||
| 6 | #extension GL_ARB_shader_stencil_export : require | ||
| 7 | |||
| 8 | layout(binding = 0) uniform sampler2D color_texture; | ||
| 9 | |||
| 10 | void main() { | ||
| 11 | ivec2 coord = ivec2(gl_FragCoord.xy); | ||
| 12 | vec4 color = texelFetch(color_texture, coord, 0).rgba; | ||
| 13 | uint depth_stencil_unorm = (uint(color.r * (exp2(16) - 1.0f)) << 16) | ||
| 14 | | (uint(color.g * (exp2(16) - 1.0f)) << 16); | ||
| 15 | |||
| 16 | gl_FragDepth = float(depth_stencil_unorm >> 8) / (exp2(24.0) - 1.0f); | ||
| 17 | gl_FragStencilRefARB = int(depth_stencil_unorm & 0x00FF); | ||
| 18 | } | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 3dbdcc2c4..14e6522f2 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | #include <glad/glad.h> | 10 | #include <glad/glad.h> |
| 11 | 11 | ||
| 12 | #include "common/bit_util.h" | ||
| 12 | #include "common/literals.h" | 13 | #include "common/literals.h" |
| 13 | #include "common/settings.h" | 14 | #include "common/settings.h" |
| 14 | #include "video_core/renderer_opengl/gl_device.h" | 15 | #include "video_core/renderer_opengl/gl_device.h" |
| @@ -398,9 +399,6 @@ OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_form | |||
| 398 | return GL_R32UI; | 399 | return GL_R32UI; |
| 399 | } | 400 | } |
| 400 | 401 | ||
| 401 | [[nodiscard]] u32 NextPow2(u32 value) { | ||
| 402 | return 1U << (32U - std::countl_zero(value - 1U)); | ||
| 403 | } | ||
| 404 | } // Anonymous namespace | 402 | } // Anonymous namespace |
| 405 | 403 | ||
| 406 | ImageBufferMap::~ImageBufferMap() { | 404 | ImageBufferMap::~ImageBufferMap() { |
| @@ -527,8 +525,8 @@ void TextureCacheRuntime::CopyImage(Image& dst_image, Image& src_image, | |||
| 527 | } | 525 | } |
| 528 | } | 526 | } |
| 529 | 527 | ||
| 530 | void TextureCacheRuntime::ConvertImage(Image& dst, Image& src, | 528 | void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src, |
| 531 | std::span<const VideoCommon::ImageCopy> copies) { | 529 | std::span<const VideoCommon::ImageCopy> copies) { |
| 532 | LOG_DEBUG(Render_OpenGL, "Converting {} to {}", src.info.format, dst.info.format); | 530 | LOG_DEBUG(Render_OpenGL, "Converting {} to {}", src.info.format, dst.info.format); |
| 533 | format_conversion_pass.ConvertImage(dst, src, copies); | 531 | format_conversion_pass.ConvertImage(dst, src, copies); |
| 534 | } | 532 | } |
| @@ -1333,7 +1331,7 @@ void FormatConversionPass::ConvertImage(Image& dst_image, Image& src_image, | |||
| 1333 | const u32 copy_size = region.width * region.height * region.depth * img_bpp; | 1331 | const u32 copy_size = region.width * region.height * region.depth * img_bpp; |
| 1334 | if (pbo_size < copy_size) { | 1332 | if (pbo_size < copy_size) { |
| 1335 | intermediate_pbo.Create(); | 1333 | intermediate_pbo.Create(); |
| 1336 | pbo_size = NextPow2(copy_size); | 1334 | pbo_size = Common::NextPow2(copy_size); |
| 1337 | glNamedBufferData(intermediate_pbo.handle, pbo_size, nullptr, GL_STREAM_COPY); | 1335 | glNamedBufferData(intermediate_pbo.handle, pbo_size, nullptr, GL_STREAM_COPY); |
| 1338 | } | 1336 | } |
| 1339 | // Copy from source to PBO | 1337 | // Copy from source to PBO |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index c0534b1f1..37d5e6a6b 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -84,9 +84,13 @@ public: | |||
| 84 | 84 | ||
| 85 | u64 GetDeviceLocalMemory() const; | 85 | u64 GetDeviceLocalMemory() const; |
| 86 | 86 | ||
| 87 | bool ShouldReinterpret([[maybe_unused]] Image& dst, [[maybe_unused]] Image& src) { | ||
| 88 | return true; | ||
| 89 | } | ||
| 90 | |||
| 87 | void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); | 91 | void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); |
| 88 | 92 | ||
| 89 | void ConvertImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); | 93 | void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); |
| 90 | 94 | ||
| 91 | void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled) { | 95 | void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled) { |
| 92 | UNIMPLEMENTED(); | 96 | UNIMPLEMENTED(); |
| @@ -339,7 +343,6 @@ struct TextureCacheParams { | |||
| 339 | static constexpr bool FRAMEBUFFER_BLITS = true; | 343 | static constexpr bool FRAMEBUFFER_BLITS = true; |
| 340 | static constexpr bool HAS_EMULATED_COPIES = true; | 344 | static constexpr bool HAS_EMULATED_COPIES = true; |
| 341 | static constexpr bool HAS_DEVICE_MEMORY_INFO = true; | 345 | static constexpr bool HAS_DEVICE_MEMORY_INFO = true; |
| 342 | static constexpr bool HAS_PIXEL_FORMAT_CONVERSIONS = true; | ||
| 343 | 346 | ||
| 344 | using Runtime = OpenGL::TextureCacheRuntime; | 347 | using Runtime = OpenGL::TextureCacheRuntime; |
| 345 | using Image = OpenGL::Image; | 348 | using Image = OpenGL::Image; |
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index b3884a4f5..28b631f73 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp | |||
| @@ -4,8 +4,14 @@ | |||
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | 6 | ||
| 7 | #include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h" | ||
| 8 | #include "video_core/host_shaders/convert_b10g11r11_to_d24s8_frag_spv.h" | ||
| 9 | #include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h" | ||
| 10 | #include "video_core/host_shaders/convert_d24s8_to_b10g11r11_frag_spv.h" | ||
| 11 | #include "video_core/host_shaders/convert_d24s8_to_r16g16_frag_spv.h" | ||
| 7 | #include "video_core/host_shaders/convert_depth_to_float_frag_spv.h" | 12 | #include "video_core/host_shaders/convert_depth_to_float_frag_spv.h" |
| 8 | #include "video_core/host_shaders/convert_float_to_depth_frag_spv.h" | 13 | #include "video_core/host_shaders/convert_float_to_depth_frag_spv.h" |
| 14 | #include "video_core/host_shaders/convert_r16g16_to_d24s8_frag_spv.h" | ||
| 9 | #include "video_core/host_shaders/full_screen_triangle_vert_spv.h" | 15 | #include "video_core/host_shaders/full_screen_triangle_vert_spv.h" |
| 10 | #include "video_core/host_shaders/vulkan_blit_color_float_frag_spv.h" | 16 | #include "video_core/host_shaders/vulkan_blit_color_float_frag_spv.h" |
| 11 | #include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h" | 17 | #include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h" |
| @@ -354,6 +360,12 @@ BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_, | |||
| 354 | blit_color_to_color_frag(BuildShader(device, VULKAN_BLIT_COLOR_FLOAT_FRAG_SPV)), | 360 | blit_color_to_color_frag(BuildShader(device, VULKAN_BLIT_COLOR_FLOAT_FRAG_SPV)), |
| 355 | convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)), | 361 | convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)), |
| 356 | convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)), | 362 | convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)), |
| 363 | convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)), | ||
| 364 | convert_b10g11r11_to_d24s8_frag(BuildShader(device, CONVERT_B10G11R11_TO_D24S8_FRAG_SPV)), | ||
| 365 | convert_r16g16_to_d24s8_frag(BuildShader(device, CONVERT_R16G16_TO_D24S8_FRAG_SPV)), | ||
| 366 | convert_d24s8_to_abgr8_frag(BuildShader(device, CONVERT_D24S8_TO_ABGR8_FRAG_SPV)), | ||
| 367 | convert_d24s8_to_b10g11r11_frag(BuildShader(device, CONVERT_D24S8_TO_B10G11R11_FRAG_SPV)), | ||
| 368 | convert_d24s8_to_r16g16_frag(BuildShader(device, CONVERT_D24S8_TO_R16G16_FRAG_SPV)), | ||
| 357 | linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)), | 369 | linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)), |
| 358 | nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) { | 370 | nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) { |
| 359 | if (device.IsExtShaderStencilExportSupported()) { | 371 | if (device.IsExtShaderStencilExportSupported()) { |
| @@ -448,6 +460,59 @@ void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer, | |||
| 448 | Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); | 460 | Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); |
| 449 | } | 461 | } |
| 450 | 462 | ||
| 463 | void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, | ||
| 464 | const ImageView& src_image_view, u32 up_scale, | ||
| 465 | u32 down_shift) { | ||
| 466 | ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(), | ||
| 467 | convert_abgr8_to_d24s8_frag, true); | ||
| 468 | Convert(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale, | ||
| 469 | down_shift); | ||
| 470 | } | ||
| 471 | |||
| 472 | void BlitImageHelper::ConvertB10G11R11ToD24S8(const Framebuffer* dst_framebuffer, | ||
| 473 | const ImageView& src_image_view, u32 up_scale, | ||
| 474 | u32 down_shift) { | ||
| 475 | ConvertPipelineDepthTargetEx(convert_b10g11r11_to_d24s8_pipeline, dst_framebuffer->RenderPass(), | ||
| 476 | convert_b10g11r11_to_d24s8_frag, true); | ||
| 477 | Convert(*convert_b10g11r11_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale, | ||
| 478 | down_shift); | ||
| 479 | } | ||
| 480 | |||
| 481 | void BlitImageHelper::ConvertR16G16ToD24S8(const Framebuffer* dst_framebuffer, | ||
| 482 | const ImageView& src_image_view, u32 up_scale, | ||
| 483 | u32 down_shift) { | ||
| 484 | ConvertPipelineDepthTargetEx(convert_r16g16_to_d24s8_pipeline, dst_framebuffer->RenderPass(), | ||
| 485 | convert_r16g16_to_d24s8_frag, true); | ||
| 486 | Convert(*convert_r16g16_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale, | ||
| 487 | down_shift); | ||
| 488 | } | ||
| 489 | |||
| 490 | void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, | ||
| 491 | ImageView& src_image_view, u32 up_scale, u32 down_shift) { | ||
| 492 | ConvertPipelineColorTargetEx(convert_d24s8_to_abgr8_pipeline, dst_framebuffer->RenderPass(), | ||
| 493 | convert_d24s8_to_abgr8_frag, false); | ||
| 494 | ConvertDepthStencil(*convert_d24s8_to_abgr8_pipeline, dst_framebuffer, src_image_view, up_scale, | ||
| 495 | down_shift); | ||
| 496 | } | ||
| 497 | |||
| 498 | void BlitImageHelper::ConvertD24S8ToB10G11R11(const Framebuffer* dst_framebuffer, | ||
| 499 | ImageView& src_image_view, u32 up_scale, | ||
| 500 | u32 down_shift) { | ||
| 501 | ConvertPipelineColorTargetEx(convert_d24s8_to_b10g11r11_pipeline, dst_framebuffer->RenderPass(), | ||
| 502 | convert_d24s8_to_b10g11r11_frag, false); | ||
| 503 | ConvertDepthStencil(*convert_d24s8_to_b10g11r11_pipeline, dst_framebuffer, src_image_view, | ||
| 504 | up_scale, down_shift); | ||
| 505 | } | ||
| 506 | |||
| 507 | void BlitImageHelper::ConvertD24S8ToR16G16(const Framebuffer* dst_framebuffer, | ||
| 508 | ImageView& src_image_view, u32 up_scale, | ||
| 509 | u32 down_shift) { | ||
| 510 | ConvertPipelineColorTargetEx(convert_d24s8_to_r16g16_pipeline, dst_framebuffer->RenderPass(), | ||
| 511 | convert_d24s8_to_r16g16_frag, false); | ||
| 512 | ConvertDepthStencil(*convert_d24s8_to_r16g16_pipeline, dst_framebuffer, src_image_view, | ||
| 513 | up_scale, down_shift); | ||
| 514 | } | ||
| 515 | |||
| 451 | void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, | 516 | void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, |
| 452 | const ImageView& src_image_view, u32 up_scale, u32 down_shift) { | 517 | const ImageView& src_image_view, u32 up_scale, u32 down_shift) { |
| 453 | const VkPipelineLayout layout = *one_texture_pipeline_layout; | 518 | const VkPipelineLayout layout = *one_texture_pipeline_layout; |
| @@ -495,6 +560,54 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb | |||
| 495 | scheduler.InvalidateState(); | 560 | scheduler.InvalidateState(); |
| 496 | } | 561 | } |
| 497 | 562 | ||
| 563 | void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer, | ||
| 564 | ImageView& src_image_view, u32 up_scale, u32 down_shift) { | ||
| 565 | const VkPipelineLayout layout = *two_textures_pipeline_layout; | ||
| 566 | const VkImageView src_depth_view = src_image_view.DepthView(); | ||
| 567 | const VkImageView src_stencil_view = src_image_view.StencilView(); | ||
| 568 | const VkSampler sampler = *nearest_sampler; | ||
| 569 | const VkExtent2D extent{ | ||
| 570 | .width = std::max((src_image_view.size.width * up_scale) >> down_shift, 1U), | ||
| 571 | .height = std::max((src_image_view.size.height * up_scale) >> down_shift, 1U), | ||
| 572 | }; | ||
| 573 | scheduler.RequestRenderpass(dst_framebuffer); | ||
| 574 | scheduler.Record([pipeline, layout, sampler, src_depth_view, src_stencil_view, extent, up_scale, | ||
| 575 | down_shift, this](vk::CommandBuffer cmdbuf) { | ||
| 576 | const VkOffset2D offset{ | ||
| 577 | .x = 0, | ||
| 578 | .y = 0, | ||
| 579 | }; | ||
| 580 | const VkViewport viewport{ | ||
| 581 | .x = 0.0f, | ||
| 582 | .y = 0.0f, | ||
| 583 | .width = static_cast<float>(extent.width), | ||
| 584 | .height = static_cast<float>(extent.height), | ||
| 585 | .minDepth = 0.0f, | ||
| 586 | .maxDepth = 0.0f, | ||
| 587 | }; | ||
| 588 | const VkRect2D scissor{ | ||
| 589 | .offset = offset, | ||
| 590 | .extent = extent, | ||
| 591 | }; | ||
| 592 | const PushConstants push_constants{ | ||
| 593 | .tex_scale = {viewport.width, viewport.height}, | ||
| 594 | .tex_offset = {0.0f, 0.0f}, | ||
| 595 | }; | ||
| 596 | const VkDescriptorSet descriptor_set = two_textures_descriptor_allocator.Commit(); | ||
| 597 | UpdateTwoTexturesDescriptorSet(device, descriptor_set, sampler, src_depth_view, | ||
| 598 | src_stencil_view); | ||
| 599 | // TODO: Barriers | ||
| 600 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); | ||
| 601 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set, | ||
| 602 | nullptr); | ||
| 603 | cmdbuf.SetViewport(0, viewport); | ||
| 604 | cmdbuf.SetScissor(0, scissor); | ||
| 605 | cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants); | ||
| 606 | cmdbuf.Draw(3, 1, 0, 0); | ||
| 607 | }); | ||
| 608 | scheduler.InvalidateState(); | ||
| 609 | } | ||
| 610 | |||
| 498 | VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key) { | 611 | VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key) { |
| 499 | const auto it = std::ranges::find(blit_color_keys, key); | 612 | const auto it = std::ranges::find(blit_color_keys, key); |
| 500 | if (it != blit_color_keys.end()) { | 613 | if (it != blit_color_keys.end()) { |
| @@ -636,4 +749,62 @@ void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRend | |||
| 636 | }); | 749 | }); |
| 637 | } | 750 | } |
| 638 | 751 | ||
| 752 | void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, | ||
| 753 | vk::ShaderModule& module, bool single_texture) { | ||
| 754 | if (pipeline) { | ||
| 755 | return; | ||
| 756 | } | ||
| 757 | const std::array stages = MakeStages(*full_screen_vert, *module); | ||
| 758 | pipeline = device.GetLogical().CreateGraphicsPipeline({ | ||
| 759 | .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | ||
| 760 | .pNext = nullptr, | ||
| 761 | .flags = 0, | ||
| 762 | .stageCount = static_cast<u32>(stages.size()), | ||
| 763 | .pStages = stages.data(), | ||
| 764 | .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, | ||
| 765 | .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, | ||
| 766 | .pTessellationState = nullptr, | ||
| 767 | .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, | ||
| 768 | .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, | ||
| 769 | .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, | ||
| 770 | .pDepthStencilState = nullptr, | ||
| 771 | .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, | ||
| 772 | .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, | ||
| 773 | .layout = single_texture ? *one_texture_pipeline_layout : *two_textures_pipeline_layout, | ||
| 774 | .renderPass = renderpass, | ||
| 775 | .subpass = 0, | ||
| 776 | .basePipelineHandle = VK_NULL_HANDLE, | ||
| 777 | .basePipelineIndex = 0, | ||
| 778 | }); | ||
| 779 | } | ||
| 780 | |||
| 781 | void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, | ||
| 782 | vk::ShaderModule& module, bool single_texture) { | ||
| 783 | if (pipeline) { | ||
| 784 | return; | ||
| 785 | } | ||
| 786 | const std::array stages = MakeStages(*full_screen_vert, *module); | ||
| 787 | pipeline = device.GetLogical().CreateGraphicsPipeline({ | ||
| 788 | .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | ||
| 789 | .pNext = nullptr, | ||
| 790 | .flags = 0, | ||
| 791 | .stageCount = static_cast<u32>(stages.size()), | ||
| 792 | .pStages = stages.data(), | ||
| 793 | .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, | ||
| 794 | .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, | ||
| 795 | .pTessellationState = nullptr, | ||
| 796 | .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, | ||
| 797 | .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, | ||
| 798 | .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, | ||
| 799 | .pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, | ||
| 800 | .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO, | ||
| 801 | .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, | ||
| 802 | .layout = single_texture ? *one_texture_pipeline_layout : *two_textures_pipeline_layout, | ||
| 803 | .renderPass = renderpass, | ||
| 804 | .subpass = 0, | ||
| 805 | .basePipelineHandle = VK_NULL_HANDLE, | ||
| 806 | .basePipelineIndex = 0, | ||
| 807 | }); | ||
| 808 | } | ||
| 809 | |||
| 639 | } // namespace Vulkan | 810 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index d77f76678..cec095341 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h | |||
| @@ -56,10 +56,31 @@ public: | |||
| 56 | void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 56 | void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, |
| 57 | u32 up_scale, u32 down_shift); | 57 | u32 up_scale, u32 down_shift); |
| 58 | 58 | ||
| 59 | void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | ||
| 60 | u32 up_scale, u32 down_shift); | ||
| 61 | |||
| 62 | void ConvertB10G11R11ToD24S8(const Framebuffer* dst_framebuffer, | ||
| 63 | const ImageView& src_image_view, u32 up_scale, u32 down_shift); | ||
| 64 | |||
| 65 | void ConvertR16G16ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | ||
| 66 | u32 up_scale, u32 down_shift); | ||
| 67 | |||
| 68 | void ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view, | ||
| 69 | u32 up_scale, u32 down_shift); | ||
| 70 | |||
| 71 | void ConvertD24S8ToB10G11R11(const Framebuffer* dst_framebuffer, ImageView& src_image_view, | ||
| 72 | u32 up_scale, u32 down_shift); | ||
| 73 | |||
| 74 | void ConvertD24S8ToR16G16(const Framebuffer* dst_framebuffer, ImageView& src_image_view, | ||
| 75 | u32 up_scale, u32 down_shift); | ||
| 76 | |||
| 59 | private: | 77 | private: |
| 60 | void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, | 78 | void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, |
| 61 | const ImageView& src_image_view, u32 up_scale, u32 down_shift); | 79 | const ImageView& src_image_view, u32 up_scale, u32 down_shift); |
| 62 | 80 | ||
| 81 | void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer, | ||
| 82 | ImageView& src_image_view, u32 up_scale, u32 down_shift); | ||
| 83 | |||
| 63 | [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key); | 84 | [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key); |
| 64 | 85 | ||
| 65 | [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key); | 86 | [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key); |
| @@ -68,6 +89,12 @@ private: | |||
| 68 | 89 | ||
| 69 | void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); | 90 | void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); |
| 70 | 91 | ||
| 92 | void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, | ||
| 93 | vk::ShaderModule& module, bool single_texture); | ||
| 94 | |||
| 95 | void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, | ||
| 96 | vk::ShaderModule& module, bool single_texture); | ||
| 97 | |||
| 71 | const Device& device; | 98 | const Device& device; |
| 72 | VKScheduler& scheduler; | 99 | VKScheduler& scheduler; |
| 73 | StateTracker& state_tracker; | 100 | StateTracker& state_tracker; |
| @@ -83,6 +110,12 @@ private: | |||
| 83 | vk::ShaderModule blit_depth_stencil_frag; | 110 | vk::ShaderModule blit_depth_stencil_frag; |
| 84 | vk::ShaderModule convert_depth_to_float_frag; | 111 | vk::ShaderModule convert_depth_to_float_frag; |
| 85 | vk::ShaderModule convert_float_to_depth_frag; | 112 | vk::ShaderModule convert_float_to_depth_frag; |
| 113 | vk::ShaderModule convert_abgr8_to_d24s8_frag; | ||
| 114 | vk::ShaderModule convert_b10g11r11_to_d24s8_frag; | ||
| 115 | vk::ShaderModule convert_r16g16_to_d24s8_frag; | ||
| 116 | vk::ShaderModule convert_d24s8_to_abgr8_frag; | ||
| 117 | vk::ShaderModule convert_d24s8_to_b10g11r11_frag; | ||
| 118 | vk::ShaderModule convert_d24s8_to_r16g16_frag; | ||
| 86 | vk::Sampler linear_sampler; | 119 | vk::Sampler linear_sampler; |
| 87 | vk::Sampler nearest_sampler; | 120 | vk::Sampler nearest_sampler; |
| 88 | 121 | ||
| @@ -94,6 +127,12 @@ private: | |||
| 94 | vk::Pipeline convert_r32_to_d32_pipeline; | 127 | vk::Pipeline convert_r32_to_d32_pipeline; |
| 95 | vk::Pipeline convert_d16_to_r16_pipeline; | 128 | vk::Pipeline convert_d16_to_r16_pipeline; |
| 96 | vk::Pipeline convert_r16_to_d16_pipeline; | 129 | vk::Pipeline convert_r16_to_d16_pipeline; |
| 130 | vk::Pipeline convert_abgr8_to_d24s8_pipeline; | ||
| 131 | vk::Pipeline convert_b10g11r11_to_d24s8_pipeline; | ||
| 132 | vk::Pipeline convert_r16g16_to_d24s8_pipeline; | ||
| 133 | vk::Pipeline convert_d24s8_to_abgr8_pipeline; | ||
| 134 | vk::Pipeline convert_d24s8_to_b10g11r11_pipeline; | ||
| 135 | vk::Pipeline convert_d24s8_to_r16g16_pipeline; | ||
| 97 | }; | 136 | }; |
| 98 | 137 | ||
| 99 | } // namespace Vulkan | 138 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 9bc846b94..3964424af 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | 9 | ||
| 10 | #include "common/bit_cast.h" | 10 | #include "common/bit_cast.h" |
| 11 | #include "common/bit_util.h" | ||
| 11 | #include "common/settings.h" | 12 | #include "common/settings.h" |
| 12 | 13 | ||
| 13 | #include "video_core/engines/fermi_2d.h" | 14 | #include "video_core/engines/fermi_2d.h" |
| @@ -313,6 +314,19 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 313 | }; | 314 | }; |
| 314 | } | 315 | } |
| 315 | 316 | ||
| 317 | [[nodiscard]] VkBufferImageCopy MakeBufferImageCopy(const VideoCommon::ImageCopy& copy, bool is_src, | ||
| 318 | VkImageAspectFlags aspect_mask) noexcept { | ||
| 319 | return VkBufferImageCopy{ | ||
| 320 | .bufferOffset = 0, | ||
| 321 | .bufferRowLength = 0, | ||
| 322 | .bufferImageHeight = 0, | ||
| 323 | .imageSubresource = MakeImageSubresourceLayers( | ||
| 324 | is_src ? copy.src_subresource : copy.dst_subresource, aspect_mask), | ||
| 325 | .imageOffset = MakeOffset3D(is_src ? copy.src_offset : copy.dst_offset), | ||
| 326 | .imageExtent = MakeExtent3D(copy.extent), | ||
| 327 | }; | ||
| 328 | } | ||
| 329 | |||
| 316 | [[maybe_unused]] [[nodiscard]] std::vector<VkBufferCopy> TransformBufferCopies( | 330 | [[maybe_unused]] [[nodiscard]] std::vector<VkBufferCopy> TransformBufferCopies( |
| 317 | std::span<const VideoCommon::BufferCopy> copies, size_t buffer_offset) { | 331 | std::span<const VideoCommon::BufferCopy> copies, size_t buffer_offset) { |
| 318 | std::vector<VkBufferCopy> result(copies.size()); | 332 | std::vector<VkBufferCopy> result(copies.size()); |
| @@ -759,6 +773,163 @@ StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size) { | |||
| 759 | return staging_buffer_pool.Request(size, MemoryUsage::Download); | 773 | return staging_buffer_pool.Request(size, MemoryUsage::Download); |
| 760 | } | 774 | } |
| 761 | 775 | ||
| 776 | bool TextureCacheRuntime::ShouldReinterpret(Image& dst, Image& src) { | ||
| 777 | if (VideoCore::Surface::GetFormatType(dst.info.format) == | ||
| 778 | VideoCore::Surface::SurfaceType::DepthStencil) { | ||
| 779 | return !device.IsExtShaderStencilExportSupported(); | ||
| 780 | } | ||
| 781 | return false; | ||
| 782 | } | ||
| 783 | |||
| 784 | VkBuffer TextureCacheRuntime::GetTemporaryBuffer(size_t needed_size) { | ||
| 785 | const auto level = (8 * sizeof(size_t)) - std::countl_zero(needed_size - 1ULL); | ||
| 786 | if (buffer_commits[level]) { | ||
| 787 | return *buffers[level]; | ||
| 788 | } | ||
| 789 | const auto new_size = Common::NextPow2(needed_size); | ||
| 790 | VkBufferUsageFlags flags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | | ||
| 791 | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | | ||
| 792 | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; | ||
| 793 | buffers[level] = device.GetLogical().CreateBuffer({ | ||
| 794 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | ||
| 795 | .pNext = nullptr, | ||
| 796 | .flags = 0, | ||
| 797 | .size = new_size, | ||
| 798 | .usage = flags, | ||
| 799 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | ||
| 800 | .queueFamilyIndexCount = 0, | ||
| 801 | .pQueueFamilyIndices = nullptr, | ||
| 802 | }); | ||
| 803 | buffer_commits[level] = std::make_unique<MemoryCommit>( | ||
| 804 | memory_allocator.Commit(buffers[level], MemoryUsage::DeviceLocal)); | ||
| 805 | return *buffers[level]; | ||
| 806 | } | ||
| 807 | |||
| 808 | void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src, | ||
| 809 | std::span<const VideoCommon::ImageCopy> copies) { | ||
| 810 | std::vector<VkBufferImageCopy> vk_in_copies(copies.size()); | ||
| 811 | std::vector<VkBufferImageCopy> vk_out_copies(copies.size()); | ||
| 812 | const VkImageAspectFlags src_aspect_mask = src.AspectMask(); | ||
| 813 | const VkImageAspectFlags dst_aspect_mask = dst.AspectMask(); | ||
| 814 | |||
| 815 | std::ranges::transform(copies, vk_in_copies.begin(), [src_aspect_mask](const auto& copy) { | ||
| 816 | return MakeBufferImageCopy(copy, true, src_aspect_mask); | ||
| 817 | }); | ||
| 818 | std::ranges::transform(copies, vk_out_copies.begin(), [dst_aspect_mask](const auto& copy) { | ||
| 819 | return MakeBufferImageCopy(copy, false, dst_aspect_mask); | ||
| 820 | }); | ||
| 821 | const u32 img_bpp = BytesPerBlock(src.info.format); | ||
| 822 | size_t total_size = 0; | ||
| 823 | for (const auto& copy : copies) { | ||
| 824 | total_size += copy.extent.width * copy.extent.height * copy.extent.depth * img_bpp; | ||
| 825 | } | ||
| 826 | const VkBuffer copy_buffer = GetTemporaryBuffer(total_size); | ||
| 827 | const VkImage dst_image = dst.Handle(); | ||
| 828 | const VkImage src_image = src.Handle(); | ||
| 829 | scheduler.RequestOutsideRenderPassOperationContext(); | ||
| 830 | scheduler.Record([dst_image, src_image, copy_buffer, src_aspect_mask, dst_aspect_mask, | ||
| 831 | vk_in_copies, vk_out_copies](vk::CommandBuffer cmdbuf) { | ||
| 832 | RangedBarrierRange dst_range; | ||
| 833 | RangedBarrierRange src_range; | ||
| 834 | for (const VkBufferImageCopy& copy : vk_in_copies) { | ||
| 835 | src_range.AddLayers(copy.imageSubresource); | ||
| 836 | } | ||
| 837 | for (const VkBufferImageCopy& copy : vk_out_copies) { | ||
| 838 | dst_range.AddLayers(copy.imageSubresource); | ||
| 839 | } | ||
| 840 | static constexpr VkMemoryBarrier READ_BARRIER{ | ||
| 841 | .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, | ||
| 842 | .pNext = nullptr, | ||
| 843 | .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, | ||
| 844 | .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, | ||
| 845 | }; | ||
| 846 | static constexpr VkMemoryBarrier WRITE_BARRIER{ | ||
| 847 | .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, | ||
| 848 | .pNext = nullptr, | ||
| 849 | .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, | ||
| 850 | .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, | ||
| 851 | }; | ||
| 852 | const std::array pre_barriers{ | ||
| 853 | VkImageMemoryBarrier{ | ||
| 854 | .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||
| 855 | .pNext = nullptr, | ||
| 856 | .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | | ||
| 857 | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | | ||
| 858 | VK_ACCESS_TRANSFER_WRITE_BIT, | ||
| 859 | .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, | ||
| 860 | .oldLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 861 | .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, | ||
| 862 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 863 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 864 | .image = src_image, | ||
| 865 | .subresourceRange = src_range.SubresourceRange(src_aspect_mask), | ||
| 866 | }, | ||
| 867 | }; | ||
| 868 | const std::array middle_in_barrier{ | ||
| 869 | VkImageMemoryBarrier{ | ||
| 870 | .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||
| 871 | .pNext = nullptr, | ||
| 872 | .srcAccessMask = 0, | ||
| 873 | .dstAccessMask = 0, | ||
| 874 | .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, | ||
| 875 | .newLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 876 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 877 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 878 | .image = src_image, | ||
| 879 | .subresourceRange = src_range.SubresourceRange(src_aspect_mask), | ||
| 880 | }, | ||
| 881 | }; | ||
| 882 | const std::array middle_out_barrier{ | ||
| 883 | VkImageMemoryBarrier{ | ||
| 884 | .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||
| 885 | .pNext = nullptr, | ||
| 886 | .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | | ||
| 887 | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | | ||
| 888 | VK_ACCESS_TRANSFER_WRITE_BIT, | ||
| 889 | .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, | ||
| 890 | .oldLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 891 | .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | ||
| 892 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 893 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 894 | .image = dst_image, | ||
| 895 | .subresourceRange = dst_range.SubresourceRange(dst_aspect_mask), | ||
| 896 | }, | ||
| 897 | }; | ||
| 898 | const std::array post_barriers{ | ||
| 899 | VkImageMemoryBarrier{ | ||
| 900 | .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||
| 901 | .pNext = nullptr, | ||
| 902 | .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, | ||
| 903 | .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | | ||
| 904 | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | | ||
| 905 | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | | ||
| 906 | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | | ||
| 907 | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | | ||
| 908 | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, | ||
| 909 | .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | ||
| 910 | .newLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 911 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 912 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 913 | .image = dst_image, | ||
| 914 | .subresourceRange = dst_range.SubresourceRange(dst_aspect_mask), | ||
| 915 | }, | ||
| 916 | }; | ||
| 917 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, | ||
| 918 | 0, {}, {}, pre_barriers); | ||
| 919 | |||
| 920 | cmdbuf.CopyImageToBuffer(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, copy_buffer, | ||
| 921 | vk_in_copies); | ||
| 922 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, | ||
| 923 | 0, WRITE_BARRIER, nullptr, middle_in_barrier); | ||
| 924 | |||
| 925 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, | ||
| 926 | 0, READ_BARRIER, {}, middle_out_barrier); | ||
| 927 | cmdbuf.CopyBufferToImage(copy_buffer, dst_image, VK_IMAGE_LAYOUT_GENERAL, vk_out_copies); | ||
| 928 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, | ||
| 929 | 0, {}, {}, post_barriers); | ||
| 930 | }); | ||
| 931 | } | ||
| 932 | |||
| 762 | void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, | 933 | void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, |
| 763 | const Region2D& dst_region, const Region2D& src_region, | 934 | const Region2D& dst_region, const Region2D& src_region, |
| 764 | Tegra::Engines::Fermi2D::Filter filter, | 935 | Tegra::Engines::Fermi2D::Filter filter, |
| @@ -886,6 +1057,22 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im | |||
| 886 | return blit_image_helper.ConvertD16ToR16(dst, src_view, up_scale, down_shift); | 1057 | return blit_image_helper.ConvertD16ToR16(dst, src_view, up_scale, down_shift); |
| 887 | } | 1058 | } |
| 888 | break; | 1059 | break; |
| 1060 | case PixelFormat::A8B8G8R8_UNORM: | ||
| 1061 | case PixelFormat::B8G8R8A8_UNORM: | ||
| 1062 | if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) { | ||
| 1063 | return blit_image_helper.ConvertD24S8ToABGR8(dst, src_view, up_scale, down_shift); | ||
| 1064 | } | ||
| 1065 | break; | ||
| 1066 | case PixelFormat::B10G11R11_FLOAT: | ||
| 1067 | if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) { | ||
| 1068 | return blit_image_helper.ConvertD24S8ToB10G11R11(dst, src_view, up_scale, down_shift); | ||
| 1069 | } | ||
| 1070 | break; | ||
| 1071 | case PixelFormat::R16G16_UNORM: | ||
| 1072 | if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) { | ||
| 1073 | return blit_image_helper.ConvertD24S8ToR16G16(dst, src_view, up_scale, down_shift); | ||
| 1074 | } | ||
| 1075 | break; | ||
| 889 | case PixelFormat::R32_FLOAT: | 1076 | case PixelFormat::R32_FLOAT: |
| 890 | if (src_view.format == PixelFormat::D32_FLOAT) { | 1077 | if (src_view.format == PixelFormat::D32_FLOAT) { |
| 891 | return blit_image_helper.ConvertD32ToR32(dst, src_view, up_scale, down_shift); | 1078 | return blit_image_helper.ConvertD32ToR32(dst, src_view, up_scale, down_shift); |
| @@ -896,6 +1083,18 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im | |||
| 896 | return blit_image_helper.ConvertR16ToD16(dst, src_view, up_scale, down_shift); | 1083 | return blit_image_helper.ConvertR16ToD16(dst, src_view, up_scale, down_shift); |
| 897 | } | 1084 | } |
| 898 | break; | 1085 | break; |
| 1086 | case PixelFormat::S8_UINT_D24_UNORM: | ||
| 1087 | if (src_view.format == PixelFormat::A8B8G8R8_UNORM || | ||
| 1088 | src_view.format == PixelFormat::B8G8R8A8_UNORM) { | ||
| 1089 | return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view, up_scale, down_shift); | ||
| 1090 | } | ||
| 1091 | if (src_view.format == PixelFormat::B10G11R11_FLOAT) { | ||
| 1092 | return blit_image_helper.ConvertB10G11R11ToD24S8(dst, src_view, up_scale, down_shift); | ||
| 1093 | } | ||
| 1094 | if (src_view.format == PixelFormat::R16G16_UNORM) { | ||
| 1095 | return blit_image_helper.ConvertR16G16ToD24S8(dst, src_view, up_scale, down_shift); | ||
| 1096 | } | ||
| 1097 | break; | ||
| 899 | case PixelFormat::D32_FLOAT: | 1098 | case PixelFormat::D32_FLOAT: |
| 900 | if (src_view.format == PixelFormat::R32_FLOAT) { | 1099 | if (src_view.format == PixelFormat::R32_FLOAT) { |
| 901 | return blit_image_helper.ConvertR32ToD32(dst, src_view, up_scale, down_shift); | 1100 | return blit_image_helper.ConvertR32ToD32(dst, src_view, up_scale, down_shift); |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index f5f8f9a74..44e9dcee4 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -61,6 +61,10 @@ public: | |||
| 61 | 61 | ||
| 62 | void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); | 62 | void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); |
| 63 | 63 | ||
| 64 | bool ShouldReinterpret(Image& dst, Image& src); | ||
| 65 | |||
| 66 | void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); | ||
| 67 | |||
| 64 | void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled); | 68 | void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled); |
| 65 | 69 | ||
| 66 | bool CanAccelerateImageUpload(Image&) const noexcept { | 70 | bool CanAccelerateImageUpload(Image&) const noexcept { |
| @@ -82,6 +86,8 @@ public: | |||
| 82 | return true; | 86 | return true; |
| 83 | } | 87 | } |
| 84 | 88 | ||
| 89 | [[nodiscard]] VkBuffer GetTemporaryBuffer(size_t needed_size); | ||
| 90 | |||
| 85 | const Device& device; | 91 | const Device& device; |
| 86 | VKScheduler& scheduler; | 92 | VKScheduler& scheduler; |
| 87 | MemoryAllocator& memory_allocator; | 93 | MemoryAllocator& memory_allocator; |
| @@ -90,6 +96,10 @@ public: | |||
| 90 | ASTCDecoderPass& astc_decoder_pass; | 96 | ASTCDecoderPass& astc_decoder_pass; |
| 91 | RenderPassCache& render_pass_cache; | 97 | RenderPassCache& render_pass_cache; |
| 92 | const Settings::ResolutionScalingInfo& resolution; | 98 | const Settings::ResolutionScalingInfo& resolution; |
| 99 | |||
| 100 | constexpr static size_t indexing_slots = 8 * sizeof(size_t); | ||
| 101 | std::array<vk::Buffer, indexing_slots> buffers{}; | ||
| 102 | std::array<std::unique_ptr<MemoryCommit>, indexing_slots> buffer_commits{}; | ||
| 93 | }; | 103 | }; |
| 94 | 104 | ||
| 95 | class Image : public VideoCommon::ImageBase { | 105 | class Image : public VideoCommon::ImageBase { |
| @@ -316,7 +326,6 @@ struct TextureCacheParams { | |||
| 316 | static constexpr bool FRAMEBUFFER_BLITS = false; | 326 | static constexpr bool FRAMEBUFFER_BLITS = false; |
| 317 | static constexpr bool HAS_EMULATED_COPIES = false; | 327 | static constexpr bool HAS_EMULATED_COPIES = false; |
| 318 | static constexpr bool HAS_DEVICE_MEMORY_INFO = true; | 328 | static constexpr bool HAS_DEVICE_MEMORY_INFO = true; |
| 319 | static constexpr bool HAS_PIXEL_FORMAT_CONVERSIONS = false; | ||
| 320 | 329 | ||
| 321 | using Runtime = Vulkan::TextureCacheRuntime; | 330 | using Runtime = Vulkan::TextureCacheRuntime; |
| 322 | using Image = Vulkan::Image; | 331 | 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 241f71a91..44a0d42ba 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -475,6 +475,7 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | |||
| 475 | const BlitImages images = GetBlitImages(dst, src); | 475 | const BlitImages images = GetBlitImages(dst, src); |
| 476 | const ImageId dst_id = images.dst_id; | 476 | const ImageId dst_id = images.dst_id; |
| 477 | const ImageId src_id = images.src_id; | 477 | const ImageId src_id = images.src_id; |
| 478 | |||
| 478 | PrepareImage(src_id, false, false); | 479 | PrepareImage(src_id, false, false); |
| 479 | PrepareImage(dst_id, true, false); | 480 | PrepareImage(dst_id, true, false); |
| 480 | 481 | ||
| @@ -758,7 +759,8 @@ ImageId TextureCache<P>::FindImage(const ImageInfo& info, GPUVAddr gpu_addr, | |||
| 758 | return ImageId{}; | 759 | return ImageId{}; |
| 759 | } | 760 | } |
| 760 | } | 761 | } |
| 761 | const bool broken_views = runtime.HasBrokenTextureViewFormats(); | 762 | const bool broken_views = |
| 763 | runtime.HasBrokenTextureViewFormats() || True(options & RelaxedOptions::ForceBrokenViews); | ||
| 762 | const bool native_bgr = runtime.HasNativeBgr(); | 764 | const bool native_bgr = runtime.HasNativeBgr(); |
| 763 | ImageId image_id; | 765 | ImageId image_id; |
| 764 | const auto lambda = [&](ImageId existing_image_id, ImageBase& existing_image) { | 766 | const auto lambda = [&](ImageId existing_image_id, ImageBase& existing_image) { |
| @@ -1094,12 +1096,13 @@ typename TextureCache<P>::BlitImages TextureCache<P>::GetBlitImages( | |||
| 1094 | if (GetFormatType(dst_info.format) != GetFormatType(src_info.format)) { | 1096 | if (GetFormatType(dst_info.format) != GetFormatType(src_info.format)) { |
| 1095 | continue; | 1097 | continue; |
| 1096 | } | 1098 | } |
| 1097 | if (!dst_id) { | 1099 | RelaxedOptions find_options{}; |
| 1098 | dst_id = InsertImage(dst_info, dst_addr, RelaxedOptions{}); | 1100 | if (src_info.num_samples > 1) { |
| 1099 | } | 1101 | // it's a resolve, we must enforce the same format. |
| 1100 | if (!src_id) { | 1102 | find_options = RelaxedOptions::ForceBrokenViews; |
| 1101 | src_id = InsertImage(src_info, src_addr, RelaxedOptions{}); | ||
| 1102 | } | 1103 | } |
| 1104 | src_id = FindOrInsertImage(src_info, src_addr, find_options); | ||
| 1105 | dst_id = FindOrInsertImage(dst_info, dst_addr, find_options); | ||
| 1103 | } while (has_deleted_images); | 1106 | } while (has_deleted_images); |
| 1104 | return BlitImages{ | 1107 | return BlitImages{ |
| 1105 | .dst_id = dst_id, | 1108 | .dst_id = dst_id, |
| @@ -1759,8 +1762,8 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag | |||
| 1759 | } | 1762 | } |
| 1760 | UNIMPLEMENTED_IF(dst.info.type != ImageType::e2D); | 1763 | UNIMPLEMENTED_IF(dst.info.type != ImageType::e2D); |
| 1761 | UNIMPLEMENTED_IF(src.info.type != ImageType::e2D); | 1764 | UNIMPLEMENTED_IF(src.info.type != ImageType::e2D); |
| 1762 | if constexpr (HAS_PIXEL_FORMAT_CONVERSIONS) { | 1765 | if (runtime.ShouldReinterpret(dst, src)) { |
| 1763 | return runtime.ConvertImage(dst, src, copies); | 1766 | return runtime.ReinterpretImage(dst, src, copies); |
| 1764 | } | 1767 | } |
| 1765 | for (const ImageCopy& copy : copies) { | 1768 | for (const ImageCopy& copy : copies) { |
| 1766 | UNIMPLEMENTED_IF(copy.dst_subresource.num_layers != 1); | 1769 | UNIMPLEMENTED_IF(copy.dst_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 a9504c0e8..643ad811c 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h | |||
| @@ -59,8 +59,6 @@ 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; | ||
| 64 | 62 | ||
| 65 | static constexpr u64 DEFAULT_EXPECTED_MEMORY = 1_GiB; | 63 | static constexpr u64 DEFAULT_EXPECTED_MEMORY = 1_GiB; |
| 66 | static constexpr u64 DEFAULT_CRITICAL_MEMORY = 2_GiB; | 64 | static constexpr u64 DEFAULT_CRITICAL_MEMORY = 2_GiB; |
diff --git a/src/video_core/texture_cache/types.h b/src/video_core/texture_cache/types.h index 5c274abdf..5ac27b3a7 100644 --- a/src/video_core/texture_cache/types.h +++ b/src/video_core/texture_cache/types.h | |||
| @@ -54,6 +54,7 @@ enum class RelaxedOptions : u32 { | |||
| 54 | Size = 1 << 0, | 54 | Size = 1 << 0, |
| 55 | Format = 1 << 1, | 55 | Format = 1 << 1, |
| 56 | Samples = 1 << 2, | 56 | Samples = 1 << 2, |
| 57 | ForceBrokenViews = 1 << 3, | ||
| 57 | }; | 58 | }; |
| 58 | DECLARE_ENUM_FLAG_OPERATORS(RelaxedOptions) | 59 | DECLARE_ENUM_FLAG_OPERATORS(RelaxedOptions) |
| 59 | 60 | ||
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp index ddc9fb13a..e4d82631e 100644 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp | |||
| @@ -1151,18 +1151,39 @@ bool IsSubresource(const ImageInfo& candidate, const ImageBase& image, GPUVAddr | |||
| 1151 | 1151 | ||
| 1152 | void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase* dst, | 1152 | void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase* dst, |
| 1153 | const ImageBase* src) { | 1153 | const ImageBase* src) { |
| 1154 | if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) { | 1154 | bool is_resolve = false; |
| 1155 | src_info.format = src->info.format; | 1155 | const auto original_src_format = src_info.format; |
| 1156 | const auto original_dst_format = dst_info.format; | ||
| 1157 | if (src) { | ||
| 1158 | if (GetFormatType(src->info.format) != SurfaceType::ColorTexture) { | ||
| 1159 | src_info.format = src->info.format; | ||
| 1160 | } | ||
| 1161 | is_resolve = src->info.num_samples > 1; | ||
| 1162 | src_info.num_samples = src->info.num_samples; | ||
| 1163 | src_info.size = src->info.size; | ||
| 1156 | } | 1164 | } |
| 1157 | if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) { | 1165 | if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) { |
| 1158 | dst_info.format = dst->info.format; | 1166 | dst_info.format = dst->info.format; |
| 1159 | } | 1167 | } |
| 1160 | if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) { | 1168 | if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) { |
| 1161 | dst_info.format = src->info.format; | 1169 | if (dst) { |
| 1170 | if (GetFormatType(dst->info.format) == SurfaceType::ColorTexture) { | ||
| 1171 | src_info.format = original_src_format; | ||
| 1172 | } | ||
| 1173 | } else { | ||
| 1174 | dst_info.format = src->info.format; | ||
| 1175 | } | ||
| 1162 | } | 1176 | } |
| 1163 | if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) { | 1177 | if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) { |
| 1164 | src_info.format = dst->info.format; | 1178 | if (src) { |
| 1179 | if (GetFormatType(src->info.format) == SurfaceType::ColorTexture) { | ||
| 1180 | dst_info.format = original_dst_format; | ||
| 1181 | } | ||
| 1182 | } else { | ||
| 1183 | src_info.format = dst->info.format; | ||
| 1184 | } | ||
| 1165 | } | 1185 | } |
| 1186 | ASSERT(!is_resolve || dst_info.format == src_info.format); | ||
| 1166 | } | 1187 | } |
| 1167 | 1188 | ||
| 1168 | u32 MapSizeBytes(const ImageBase& image) { | 1189 | u32 MapSizeBytes(const ImageBase& image) { |