diff options
| author | 2021-10-17 18:01:18 +0200 | |
|---|---|---|
| committer | 2021-11-16 22:11:31 +0100 | |
| commit | 425ab9ef4b982213f4ee0d53196f5474e255374f (patch) | |
| tree | 467bc959ea481d58514d11ca73e8f31b3557d4aa /src/video_core/renderer_vulkan | |
| parent | Presentation: add Nearest Neighbor filter. (diff) | |
| download | yuzu-425ab9ef4b982213f4ee0d53196f5474e255374f.tar.gz yuzu-425ab9ef4b982213f4ee0d53196f5474e255374f.tar.xz yuzu-425ab9ef4b982213f4ee0d53196f5474e255374f.zip | |
Texture Cache: Fix downscaling and correct memory comsumption.
Diffstat (limited to 'src/video_core/renderer_vulkan')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 93 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.h | 3 |
2 files changed, 86 insertions, 10 deletions
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 17c62e27d..51367c01d 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -592,7 +592,8 @@ struct RangedBarrierRange { | |||
| 592 | } | 592 | } |
| 593 | 593 | ||
| 594 | void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, const ImageInfo& info, | 594 | void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, const ImageInfo& info, |
| 595 | VkImageAspectFlags aspect_mask, const Settings::ResolutionScalingInfo& resolution) { | 595 | VkImageAspectFlags aspect_mask, const Settings::ResolutionScalingInfo& resolution, |
| 596 | bool up_scaling = true) { | ||
| 596 | const bool is_2d = info.type == ImageType::e2D; | 597 | const bool is_2d = info.type == ImageType::e2D; |
| 597 | const auto resources = info.resources; | 598 | const auto resources = info.resources; |
| 598 | const VkExtent2D extent{ | 599 | const VkExtent2D extent{ |
| @@ -605,14 +606,16 @@ void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, con | |||
| 605 | 606 | ||
| 606 | scheduler.RequestOutsideRenderPassOperationContext(); | 607 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 607 | scheduler.Record([dst_image, src_image, extent, resources, aspect_mask, resolution, is_2d, | 608 | scheduler.Record([dst_image, src_image, extent, resources, aspect_mask, resolution, is_2d, |
| 608 | vk_filter](vk::CommandBuffer cmdbuf) { | 609 | vk_filter, up_scaling](vk::CommandBuffer cmdbuf) { |
| 609 | const VkOffset2D src_size{ | 610 | const VkOffset2D src_size{ |
| 610 | .x = static_cast<s32>(extent.width), | 611 | .x = static_cast<s32>(up_scaling ? extent.width : resolution.ScaleUp(extent.width)), |
| 611 | .y = static_cast<s32>(extent.height), | 612 | .y = static_cast<s32>(is_2d && up_scaling ? extent.height |
| 613 | : resolution.ScaleUp(extent.height)), | ||
| 612 | }; | 614 | }; |
| 613 | const VkOffset2D dst_size{ | 615 | const VkOffset2D dst_size{ |
| 614 | .x = static_cast<s32>(resolution.ScaleUp(extent.width)), | 616 | .x = static_cast<s32>(up_scaling ? resolution.ScaleUp(extent.width) : extent.width), |
| 615 | .y = static_cast<s32>(is_2d ? resolution.ScaleUp(extent.height) : extent.height), | 617 | .y = static_cast<s32>(is_2d && up_scaling ? resolution.ScaleUp(extent.height) |
| 618 | : extent.height), | ||
| 616 | }; | 619 | }; |
| 617 | boost::container::small_vector<VkImageBlit, 4> regions; | 620 | boost::container::small_vector<VkImageBlit, 4> regions; |
| 618 | regions.reserve(resources.levels); | 621 | regions.reserve(resources.levels); |
| @@ -1134,6 +1137,7 @@ bool Image::ScaleUp() { | |||
| 1134 | if (!resolution.active) { | 1137 | if (!resolution.active) { |
| 1135 | return false; | 1138 | return false; |
| 1136 | } | 1139 | } |
| 1140 | scale_count++; | ||
| 1137 | const auto& device = runtime->device; | 1141 | const auto& device = runtime->device; |
| 1138 | const bool is_2d = info.type == ImageType::e2D; | 1142 | const bool is_2d = info.type == ImageType::e2D; |
| 1139 | const u32 scaled_width = resolution.ScaleUp(info.size.width); | 1143 | const u32 scaled_width = resolution.ScaleUp(info.size.width); |
| @@ -1161,8 +1165,10 @@ bool Image::ScaleUp() { | |||
| 1161 | using namespace VideoCommon; | 1165 | using namespace VideoCommon; |
| 1162 | static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy; | 1166 | static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy; |
| 1163 | 1167 | ||
| 1164 | const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format); | 1168 | if (!scale_view) { |
| 1165 | scale_view = std::make_unique<ImageView>(*runtime, view_info, NULL_IMAGE_ID, *this); | 1169 | const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format); |
| 1170 | scale_view = std::make_unique<ImageView>(*runtime, view_info, NULL_IMAGE_ID, *this); | ||
| 1171 | } | ||
| 1166 | auto* view_ptr = scale_view.get(); | 1172 | auto* view_ptr = scale_view.get(); |
| 1167 | 1173 | ||
| 1168 | const Region2D src_region{ | 1174 | const Region2D src_region{ |
| @@ -1178,7 +1184,10 @@ bool Image::ScaleUp() { | |||
| 1178 | .height = scaled_height, | 1184 | .height = scaled_height, |
| 1179 | }; | 1185 | }; |
| 1180 | if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT) { | 1186 | if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT) { |
| 1181 | scale_framebuffer = std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent); | 1187 | if (!scale_framebuffer) { |
| 1188 | scale_framebuffer = | ||
| 1189 | std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent); | ||
| 1190 | } | ||
| 1182 | const auto color_view = scale_view->Handle(Shader::TextureType::Color2D); | 1191 | const auto color_view = scale_view->Handle(Shader::TextureType::Color2D); |
| 1183 | 1192 | ||
| 1184 | runtime->blit_image_helper.BlitColor( | 1193 | runtime->blit_image_helper.BlitColor( |
| @@ -1186,7 +1195,10 @@ bool Image::ScaleUp() { | |||
| 1186 | Tegra::Engines::Fermi2D::Filter::Bilinear, BLIT_OPERATION); | 1195 | Tegra::Engines::Fermi2D::Filter::Bilinear, BLIT_OPERATION); |
| 1187 | } else if (!runtime->device.IsBlitDepthStencilSupported() && | 1196 | } else if (!runtime->device.IsBlitDepthStencilSupported() && |
| 1188 | aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { | 1197 | aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { |
| 1189 | scale_framebuffer = std::make_unique<Framebuffer>(*runtime, nullptr, view_ptr, extent); | 1198 | if (!scale_framebuffer) { |
| 1199 | scale_framebuffer = | ||
| 1200 | std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent); | ||
| 1201 | } | ||
| 1190 | runtime->blit_image_helper.BlitDepthStencil( | 1202 | runtime->blit_image_helper.BlitDepthStencil( |
| 1191 | scale_framebuffer.get(), scale_view->DepthView(), scale_view->StencilView(), | 1203 | scale_framebuffer.get(), scale_view->DepthView(), scale_view->StencilView(), |
| 1192 | dst_region, src_region, Tegra::Engines::Fermi2D::Filter::Point, BLIT_OPERATION); | 1204 | dst_region, src_region, Tegra::Engines::Fermi2D::Filter::Point, BLIT_OPERATION); |
| @@ -1209,6 +1221,67 @@ bool Image::ScaleDown() { | |||
| 1209 | if (!resolution.active) { | 1221 | if (!resolution.active) { |
| 1210 | return false; | 1222 | return false; |
| 1211 | } | 1223 | } |
| 1224 | const auto& device = runtime->device; | ||
| 1225 | const bool is_2d = info.type == ImageType::e2D; | ||
| 1226 | const u32 scaled_width = resolution.ScaleUp(info.size.width); | ||
| 1227 | const u32 scaled_height = is_2d ? resolution.ScaleUp(info.size.height) : info.size.height; | ||
| 1228 | if (aspect_mask == 0) { | ||
| 1229 | aspect_mask = ImageAspectMask(info.format); | ||
| 1230 | } | ||
| 1231 | static constexpr auto OPTIMAL_FORMAT = FormatType::Optimal; | ||
| 1232 | const PixelFormat format = StorageFormat(info.format); | ||
| 1233 | const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format; | ||
| 1234 | const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; | ||
| 1235 | if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) { | ||
| 1236 | BlitScale(*scheduler, *scaled_image, *original_image, info, aspect_mask, resolution, false); | ||
| 1237 | } else { | ||
| 1238 | using namespace VideoCommon; | ||
| 1239 | static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy; | ||
| 1240 | |||
| 1241 | if (!normal_view) { | ||
| 1242 | const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format); | ||
| 1243 | normal_view = std::make_unique<ImageView>(*runtime, view_info, NULL_IMAGE_ID, *this); | ||
| 1244 | } | ||
| 1245 | auto* view_ptr = normal_view.get(); | ||
| 1246 | |||
| 1247 | const Region2D src_region{ | ||
| 1248 | .start = {0, 0}, | ||
| 1249 | .end = {static_cast<s32>(scaled_width), static_cast<s32>(scaled_height)}, | ||
| 1250 | }; | ||
| 1251 | const Region2D dst_region{ | ||
| 1252 | .start = {0, 0}, | ||
| 1253 | .end = {static_cast<s32>(info.size.width), static_cast<s32>(info.size.height)}, | ||
| 1254 | }; | ||
| 1255 | const VkExtent2D extent{ | ||
| 1256 | .width = scaled_width, | ||
| 1257 | .height = scaled_height, | ||
| 1258 | }; | ||
| 1259 | if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT) { | ||
| 1260 | if (!normal_framebuffer) { | ||
| 1261 | normal_framebuffer = | ||
| 1262 | std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent); | ||
| 1263 | } | ||
| 1264 | const auto color_view = normal_view->Handle(Shader::TextureType::Color2D); | ||
| 1265 | |||
| 1266 | runtime->blit_image_helper.BlitColor( | ||
| 1267 | normal_framebuffer.get(), color_view, dst_region, src_region, | ||
| 1268 | Tegra::Engines::Fermi2D::Filter::Bilinear, BLIT_OPERATION); | ||
| 1269 | } else if (!runtime->device.IsBlitDepthStencilSupported() && | ||
| 1270 | aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { | ||
| 1271 | if (!normal_framebuffer) { | ||
| 1272 | normal_framebuffer = | ||
| 1273 | std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent); | ||
| 1274 | } | ||
| 1275 | runtime->blit_image_helper.BlitDepthStencil( | ||
| 1276 | normal_framebuffer.get(), normal_view->DepthView(), normal_view->StencilView(), | ||
| 1277 | dst_region, src_region, Tegra::Engines::Fermi2D::Filter::Point, BLIT_OPERATION); | ||
| 1278 | } else { | ||
| 1279 | // TODO: Use helper blits where applicable | ||
| 1280 | flags &= ~ImageFlagBits::Rescaled; | ||
| 1281 | LOG_ERROR(Render_Vulkan, "Device does not support scaling format {}", format); | ||
| 1282 | return false; | ||
| 1283 | } | ||
| 1284 | } | ||
| 1212 | ASSERT(info.type != ImageType::Linear); | 1285 | ASSERT(info.type != ImageType::Linear); |
| 1213 | current_image = *original_image; | 1286 | current_image = *original_image; |
| 1214 | return true; | 1287 | return true; |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 6dc190632..df854a20c 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -148,6 +148,9 @@ private: | |||
| 148 | 148 | ||
| 149 | std::unique_ptr<Framebuffer> scale_framebuffer; | 149 | std::unique_ptr<Framebuffer> scale_framebuffer; |
| 150 | std::unique_ptr<ImageView> scale_view; | 150 | std::unique_ptr<ImageView> scale_view; |
| 151 | |||
| 152 | std::unique_ptr<Framebuffer> normal_framebuffer; | ||
| 153 | std::unique_ptr<ImageView> normal_view; | ||
| 151 | }; | 154 | }; |
| 152 | 155 | ||
| 153 | class ImageView : public VideoCommon::ImageViewBase { | 156 | class ImageView : public VideoCommon::ImageViewBase { |