summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ameerj2021-10-13 23:53:59 -0400
committerGravatar Fernando Sahmkow2021-11-16 22:11:31 +0100
commitebf36f23dd781c06fd100de10cc2ec25d4bec215 (patch)
tree7de3eae1418405df263079b7f6b237176825cc15 /src
parenttexture_cache: Fix infinitely recursive ImageCanRescale check (diff)
downloadyuzu-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.cpp3
-rw-r--r--src/video_core/renderer_vulkan/blit_image.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp100
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h11
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
364BlitImageHelper::~BlitImageHelper() = default; 364BlitImageHelper::~BlitImageHelper() = default;
365 365
366void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, 366void 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
1372Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM_RT> color_buffers, 1409Framebuffer::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
1421Framebuffer::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
1428void 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
1432void TextureCacheRuntime::AccelerateImageUpload( 1482void 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
150class ImageView : public VideoCommon::ImageViewBase { 153class ImageView : public VideoCommon::ImageViewBase {
@@ -221,9 +224,15 @@ private:
221 224
222class Framebuffer { 225class Framebuffer {
223public: 226public:
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 }