diff options
| author | 2021-10-13 23:53:59 -0400 | |
|---|---|---|
| committer | 2021-11-16 22:11:31 +0100 | |
| commit | ebf36f23dd781c06fd100de10cc2ec25d4bec215 (patch) | |
| tree | 7de3eae1418405df263079b7f6b237176825cc15 /src | |
| parent | texture_cache: Fix infinitely recursive ImageCanRescale check (diff) | |
| download | yuzu-ebf36f23dd781c06fd100de10cc2ec25d4bec215.tar.gz yuzu-ebf36f23dd781c06fd100de10cc2ec25d4bec215.tar.xz yuzu-ebf36f23dd781c06fd100de10cc2ec25d4bec215.zip | |
vk_texture_cache: Use 3D to scale images when blit is unsupported
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_vulkan/blit_image.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/blit_image.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 100 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.h | 11 |
4 files changed, 87 insertions, 29 deletions
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 6c1b2f063..b97aac550 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp | |||
| @@ -363,7 +363,7 @@ BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_, | |||
| 363 | 363 | ||
| 364 | BlitImageHelper::~BlitImageHelper() = default; | 364 | BlitImageHelper::~BlitImageHelper() = default; |
| 365 | 365 | ||
| 366 | void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 366 | void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView src_view, |
| 367 | const Region2D& dst_region, const Region2D& src_region, | 367 | const Region2D& dst_region, const Region2D& src_region, |
| 368 | Tegra::Engines::Fermi2D::Filter filter, | 368 | Tegra::Engines::Fermi2D::Filter filter, |
| 369 | Tegra::Engines::Fermi2D::Operation operation) { | 369 | Tegra::Engines::Fermi2D::Operation operation) { |
| @@ -373,7 +373,6 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageV | |||
| 373 | .operation = operation, | 373 | .operation = operation, |
| 374 | }; | 374 | }; |
| 375 | const VkPipelineLayout layout = *one_texture_pipeline_layout; | 375 | const VkPipelineLayout layout = *one_texture_pipeline_layout; |
| 376 | const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D); | ||
| 377 | const VkSampler sampler = is_linear ? *linear_sampler : *nearest_sampler; | 376 | const VkSampler sampler = is_linear ? *linear_sampler : *nearest_sampler; |
| 378 | const VkPipeline pipeline = FindOrEmplacePipeline(key); | 377 | const VkPipeline pipeline = FindOrEmplacePipeline(key); |
| 379 | scheduler.RequestRenderpass(dst_framebuffer); | 378 | scheduler.RequestRenderpass(dst_framebuffer); |
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index 33ee095c1..e11f8c214 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h | |||
| @@ -34,7 +34,7 @@ public: | |||
| 34 | StateTracker& state_tracker, DescriptorPool& descriptor_pool); | 34 | StateTracker& state_tracker, DescriptorPool& descriptor_pool); |
| 35 | ~BlitImageHelper(); | 35 | ~BlitImageHelper(); |
| 36 | 36 | ||
| 37 | void BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 37 | void BlitColor(const Framebuffer* dst_framebuffer, VkImageView src_image_view, |
| 38 | const Region2D& dst_region, const Region2D& src_region, | 38 | const Region2D& dst_region, const Region2D& src_region, |
| 39 | Tegra::Engines::Fermi2D::Filter filter, | 39 | Tegra::Engines::Fermi2D::Filter filter, |
| 40 | Tegra::Engines::Fermi2D::Operation operation); | 40 | Tegra::Engines::Fermi2D::Operation operation); |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index ccfdf64ea..9b90c7d9b 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -762,8 +762,8 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst | |||
| 762 | return; | 762 | return; |
| 763 | } | 763 | } |
| 764 | if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT && !is_src_msaa && !is_dst_msaa) { | 764 | if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT && !is_src_msaa && !is_dst_msaa) { |
| 765 | blit_image_helper.BlitColor(dst_framebuffer, src, dst_region, src_region, filter, | 765 | blit_image_helper.BlitColor(dst_framebuffer, src.Handle(Shader::TextureType::Color2D), |
| 766 | operation); | 766 | dst_region, src_region, filter, operation); |
| 767 | return; | 767 | return; |
| 768 | } | 768 | } |
| 769 | if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { | 769 | if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { |
| @@ -1131,18 +1131,10 @@ bool Image::ScaleUp() { | |||
| 1131 | return false; | 1131 | return false; |
| 1132 | } | 1132 | } |
| 1133 | const auto& device = runtime->device; | 1133 | const auto& device = runtime->device; |
| 1134 | const PixelFormat format = StorageFormat(info.format); | 1134 | const bool is_2d = info.type == ImageType::e2D; |
| 1135 | const auto format_info = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, format); | 1135 | const u32 scaled_width = resolution.ScaleUp(info.size.width); |
| 1136 | const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; | 1136 | const u32 scaled_height = is_2d ? resolution.ScaleUp(info.size.height) : info.size.height; |
| 1137 | if (!device.IsFormatSupported(format_info.format, blit_usage, FormatType::Optimal)) { | ||
| 1138 | LOG_ERROR(Render_Vulkan, "Device does not support scaling format {}", format); | ||
| 1139 | // TODO: Use helper blits where applicable | ||
| 1140 | return false; | ||
| 1141 | } | ||
| 1142 | if (!scaled_image) { | 1137 | if (!scaled_image) { |
| 1143 | const bool is_2d = info.type == ImageType::e2D; | ||
| 1144 | const u32 scaled_width = resolution.ScaleUp(info.size.width); | ||
| 1145 | const u32 scaled_height = is_2d ? resolution.ScaleUp(info.size.height) : info.size.height; | ||
| 1146 | auto scaled_info = info; | 1138 | auto scaled_info = info; |
| 1147 | scaled_info.size.width = scaled_width; | 1139 | scaled_info.size.width = scaled_width; |
| 1148 | scaled_info.size.height = scaled_height; | 1140 | scaled_info.size.height = scaled_height; |
| @@ -1150,11 +1142,56 @@ bool Image::ScaleUp() { | |||
| 1150 | auto& allocator = runtime->memory_allocator; | 1142 | auto& allocator = runtime->memory_allocator; |
| 1151 | scaled_commit = MemoryCommit(allocator.Commit(scaled_image, MemoryUsage::DeviceLocal)); | 1143 | scaled_commit = MemoryCommit(allocator.Commit(scaled_image, MemoryUsage::DeviceLocal)); |
| 1152 | } | 1144 | } |
| 1145 | current_image = *scaled_image; | ||
| 1146 | |||
| 1153 | if (aspect_mask == 0) { | 1147 | if (aspect_mask == 0) { |
| 1154 | aspect_mask = ImageAspectMask(info.format); | 1148 | aspect_mask = ImageAspectMask(info.format); |
| 1155 | } | 1149 | } |
| 1156 | BlitScale(*scheduler, *original_image, *scaled_image, info, aspect_mask, resolution); | 1150 | static constexpr auto OPTIMAL_FORMAT = FormatType::Optimal; |
| 1157 | current_image = *scaled_image; | 1151 | const PixelFormat format = StorageFormat(info.format); |
| 1152 | const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format; | ||
| 1153 | const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; | ||
| 1154 | if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) { | ||
| 1155 | BlitScale(*scheduler, *original_image, *scaled_image, info, aspect_mask, resolution); | ||
| 1156 | } else { | ||
| 1157 | using namespace VideoCommon; | ||
| 1158 | static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy; | ||
| 1159 | |||
| 1160 | const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format); | ||
| 1161 | scale_view = std::make_unique<ImageView>(*runtime, view_info, NULL_IMAGE_ID, *this); | ||
| 1162 | auto* view_ptr = scale_view.get(); | ||
| 1163 | |||
| 1164 | const Region2D src_region{ | ||
| 1165 | .start = {0, 0}, | ||
| 1166 | .end = {static_cast<s32>(info.size.width), static_cast<s32>(info.size.height)}, | ||
| 1167 | }; | ||
| 1168 | const Region2D dst_region{ | ||
| 1169 | .start = {0, 0}, | ||
| 1170 | .end = {static_cast<s32>(scaled_width), static_cast<s32>(scaled_height)}, | ||
| 1171 | }; | ||
| 1172 | const VkExtent2D extent{ | ||
| 1173 | .width = scaled_width, | ||
| 1174 | .height = scaled_height, | ||
| 1175 | }; | ||
| 1176 | if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT) { | ||
| 1177 | scale_framebuffer = std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent); | ||
| 1178 | const auto color_view = scale_view->Handle(Shader::TextureType::Color2D); | ||
| 1179 | |||
| 1180 | runtime->blit_image_helper.BlitColor( | ||
| 1181 | scale_framebuffer.get(), color_view, dst_region, src_region, | ||
| 1182 | Tegra::Engines::Fermi2D::Filter::Bilinear, BLIT_OPERATION); | ||
| 1183 | } else if (!runtime->device.IsBlitDepthStencilSupported() && | ||
| 1184 | aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { | ||
| 1185 | scale_framebuffer = std::make_unique<Framebuffer>(*runtime, nullptr, view_ptr, extent); | ||
| 1186 | runtime->blit_image_helper.BlitDepthStencil( | ||
| 1187 | scale_framebuffer.get(), scale_view->DepthView(), scale_view->StencilView(), | ||
| 1188 | dst_region, src_region, Tegra::Engines::Fermi2D::Filter::Point, BLIT_OPERATION); | ||
| 1189 | } else { | ||
| 1190 | // TODO: Use helper blits where applicable | ||
| 1191 | LOG_ERROR(Render_Vulkan, "Device does not support scaling format {}", format); | ||
| 1192 | return false; | ||
| 1193 | } | ||
| 1194 | } | ||
| 1158 | flags |= ImageFlagBits::Rescaled; | 1195 | flags |= ImageFlagBits::Rescaled; |
| 1159 | return true; | 1196 | return true; |
| 1160 | } | 1197 | } |
| @@ -1370,7 +1407,27 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t | |||
| 1370 | } | 1407 | } |
| 1371 | 1408 | ||
| 1372 | Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM_RT> color_buffers, | 1409 | Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM_RT> color_buffers, |
| 1373 | ImageView* depth_buffer, const VideoCommon::RenderTargets& key) { | 1410 | ImageView* depth_buffer, const VideoCommon::RenderTargets& key) |
| 1411 | : render_area{VkExtent2D{ | ||
| 1412 | .width = key.size.width, | ||
| 1413 | .height = key.size.height, | ||
| 1414 | }} { | ||
| 1415 | CreateFramebuffer(runtime, color_buffers, depth_buffer); | ||
| 1416 | if (runtime.device.HasDebuggingToolAttached()) { | ||
| 1417 | framebuffer.SetObjectNameEXT(VideoCommon::Name(key).c_str()); | ||
| 1418 | } | ||
| 1419 | } | ||
| 1420 | |||
| 1421 | Framebuffer::Framebuffer(TextureCacheRuntime& runtime, ImageView* color_buffer, | ||
| 1422 | ImageView* depth_buffer, VkExtent2D extent) | ||
| 1423 | : render_area{extent} { | ||
| 1424 | std::array<ImageView*, NUM_RT> color_buffers{color_buffer}; | ||
| 1425 | CreateFramebuffer(runtime, color_buffers, depth_buffer); | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, | ||
| 1429 | std::span<ImageView*, NUM_RT> color_buffers, | ||
| 1430 | ImageView* depth_buffer) { | ||
| 1374 | std::vector<VkImageView> attachments; | 1431 | std::vector<VkImageView> attachments; |
| 1375 | RenderPassKey renderpass_key{}; | 1432 | RenderPassKey renderpass_key{}; |
| 1376 | s32 num_layers = 1; | 1433 | s32 num_layers = 1; |
| @@ -1408,10 +1465,6 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM | |||
| 1408 | 1465 | ||
| 1409 | renderpass = runtime.render_pass_cache.Get(renderpass_key); | 1466 | renderpass = runtime.render_pass_cache.Get(renderpass_key); |
| 1410 | 1467 | ||
| 1411 | render_area = VkExtent2D{ | ||
| 1412 | .width = key.size.width, | ||
| 1413 | .height = key.size.height, | ||
| 1414 | }; | ||
| 1415 | num_color_buffers = static_cast<u32>(num_colors); | 1468 | num_color_buffers = static_cast<u32>(num_colors); |
| 1416 | framebuffer = runtime.device.GetLogical().CreateFramebuffer({ | 1469 | framebuffer = runtime.device.GetLogical().CreateFramebuffer({ |
| 1417 | .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, | 1470 | .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, |
| @@ -1420,13 +1473,10 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM | |||
| 1420 | .renderPass = renderpass, | 1473 | .renderPass = renderpass, |
| 1421 | .attachmentCount = static_cast<u32>(attachments.size()), | 1474 | .attachmentCount = static_cast<u32>(attachments.size()), |
| 1422 | .pAttachments = attachments.data(), | 1475 | .pAttachments = attachments.data(), |
| 1423 | .width = key.size.width, | 1476 | .width = render_area.width, |
| 1424 | .height = key.size.height, | 1477 | .height = render_area.height, |
| 1425 | .layers = static_cast<u32>(std::max(num_layers, 1)), | 1478 | .layers = static_cast<u32>(std::max(num_layers, 1)), |
| 1426 | }); | 1479 | }); |
| 1427 | if (runtime.device.HasDebuggingToolAttached()) { | ||
| 1428 | framebuffer.SetObjectNameEXT(VideoCommon::Name(key).c_str()); | ||
| 1429 | } | ||
| 1430 | } | 1480 | } |
| 1431 | 1481 | ||
| 1432 | void TextureCacheRuntime::AccelerateImageUpload( | 1482 | void TextureCacheRuntime::AccelerateImageUpload( |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 5381343e9..dc9175ee1 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -145,6 +145,9 @@ private: | |||
| 145 | vk::Image scaled_image{}; | 145 | vk::Image scaled_image{}; |
| 146 | MemoryCommit scaled_commit{}; | 146 | MemoryCommit scaled_commit{}; |
| 147 | VkImage current_image{}; | 147 | VkImage current_image{}; |
| 148 | |||
| 149 | std::unique_ptr<Framebuffer> scale_framebuffer; | ||
| 150 | std::unique_ptr<ImageView> scale_view; | ||
| 148 | }; | 151 | }; |
| 149 | 152 | ||
| 150 | class ImageView : public VideoCommon::ImageViewBase { | 153 | class ImageView : public VideoCommon::ImageViewBase { |
| @@ -221,9 +224,15 @@ private: | |||
| 221 | 224 | ||
| 222 | class Framebuffer { | 225 | class Framebuffer { |
| 223 | public: | 226 | public: |
| 224 | explicit Framebuffer(TextureCacheRuntime&, std::span<ImageView*, NUM_RT> color_buffers, | 227 | explicit Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM_RT> color_buffers, |
| 225 | ImageView* depth_buffer, const VideoCommon::RenderTargets& key); | 228 | ImageView* depth_buffer, const VideoCommon::RenderTargets& key); |
| 226 | 229 | ||
| 230 | explicit Framebuffer(TextureCacheRuntime& runtime, ImageView* color_buffer, | ||
| 231 | ImageView* depth_buffer, VkExtent2D extent); | ||
| 232 | |||
| 233 | void CreateFramebuffer(TextureCacheRuntime& runtime, | ||
| 234 | std::span<ImageView*, NUM_RT> color_buffers, ImageView* depth_buffer); | ||
| 235 | |||
| 227 | [[nodiscard]] VkFramebuffer Handle() const noexcept { | 236 | [[nodiscard]] VkFramebuffer Handle() const noexcept { |
| 228 | return *framebuffer; | 237 | return *framebuffer; |
| 229 | } | 238 | } |