summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar FernandoS272021-10-19 17:46:01 +0200
committerGravatar Fernando Sahmkow2021-11-16 22:11:31 +0100
commitf3ff8bdc0e8c6c25c1725b82d6862b93a8df3c84 (patch)
tree8a0915c032125a6b8f6217227ede508100e815b9 /src
parentTexture Cache: fix memory managment and optimize scaled downloads, uploads. (diff)
downloadyuzu-f3ff8bdc0e8c6c25c1725b82d6862b93a8df3c84.tar.gz
yuzu-f3ff8bdc0e8c6c25c1725b82d6862b93a8df3c84.tar.xz
yuzu-f3ff8bdc0e8c6c25c1725b82d6862b93a8df3c84.zip
TextureCache: Fix blitting filter in Vulkan and correct viewport/scissor calculation when downscaling.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp24
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp40
2 files changed, 44 insertions, 20 deletions
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 1ceffa718..a9334e101 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -60,10 +60,19 @@ struct DrawParams {
60 60
61VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t index, float scale) { 61VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t index, float scale) {
62 const auto& src = regs.viewport_transform[index]; 62 const auto& src = regs.viewport_transform[index];
63 const float x = (src.translate_x - src.scale_x) * scale; 63 const auto conv = [scale](float value) {
64 const float width = src.scale_x * 2.0f * scale; 64 float new_value = value * scale;
65 float y = (src.translate_y - src.scale_y) * scale; 65 if (scale < 1.0f) {
66 float height = src.scale_y * 2.0f * scale; 66 bool sign = std::signbit(new_value);
67 new_value = std::round(std::abs(new_value));
68 new_value = sign ? -new_value : new_value;
69 }
70 return new_value;
71 };
72 const float x = conv(src.translate_x - src.scale_x);
73 const float width = conv(src.scale_x * 2.0f);
74 float y = conv(src.translate_y - src.scale_y);
75 float height = conv(src.scale_y * 2.0f);
67 if (regs.screen_y_control.y_negate) { 76 if (regs.screen_y_control.y_negate) {
68 y += height; 77 y += height;
69 height = -height; 78 height = -height;
@@ -91,8 +100,13 @@ VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u3
91 if (value == 0) { 100 if (value == 0) {
92 return 0U; 101 return 0U;
93 } 102 }
103 const u32 upset = value * up_scale;
104 u32 acumm = 0;
105 if ((up_scale >> down_shift) == 0) {
106 acumm = upset & 0x1;
107 }
94 const u32 converted_value = (value * up_scale) >> down_shift; 108 const u32 converted_value = (value * up_scale) >> down_shift;
95 return std::max<u32>(converted_value, 1U); 109 return std::max<u32>(converted_value + acumm, 1U);
96 }; 110 };
97 if (src.enable) { 111 if (src.enable) {
98 scissor.offset.x = static_cast<s32>(scale_up(src.min_x)); 112 scissor.offset.x = static_cast<s32>(scale_up(src.min_x));
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 02aac3b98..84ec803ba 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -593,7 +593,7 @@ struct RangedBarrierRange {
593 593
594void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, const ImageInfo& info, 594void 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 bool is_bilinear, bool up_scaling = true) {
597 const bool is_2d = info.type == ImageType::e2D; 597 const bool is_2d = info.type == ImageType::e2D;
598 const auto resources = info.resources; 598 const auto resources = info.resources;
599 const VkExtent2D extent{ 599 const VkExtent2D extent{
@@ -602,7 +602,7 @@ void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, con
602 }; 602 };
603 const bool is_zeta = (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; 603 const bool is_zeta = (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
604 const bool is_int_format = IsPixelFormatInteger(info.format); 604 const bool is_int_format = IsPixelFormatInteger(info.format);
605 const VkFilter vk_filter = (is_zeta || is_int_format) ? VK_FILTER_NEAREST : VK_FILTER_LINEAR; 605 const VkFilter vk_filter = is_bilinear ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
606 606
607 scheduler.RequestOutsideRenderPassOperationContext(); 607 scheduler.RequestOutsideRenderPassOperationContext();
608 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,
@@ -1160,7 +1160,7 @@ bool Image::ScaleUp(bool ignore) {
1160 } 1160 }
1161 current_image = *scaled_image; 1161 current_image = *scaled_image;
1162 if (ignore) { 1162 if (ignore) {
1163 return true; 1163 return true;
1164 } 1164 }
1165 1165
1166 if (aspect_mask == 0) { 1166 if (aspect_mask == 0) {
@@ -1170,11 +1170,18 @@ bool Image::ScaleUp(bool ignore) {
1170 const PixelFormat format = StorageFormat(info.format); 1170 const PixelFormat format = StorageFormat(info.format);
1171 const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format; 1171 const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format;
1172 const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; 1172 const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
1173 const bool is_color{aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT};
1174 const bool is_bilinear{is_color && !IsPixelFormatInteger(info.format)};
1173 if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) { 1175 if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) {
1174 BlitScale(*scheduler, *original_image, *scaled_image, info, aspect_mask, resolution); 1176 BlitScale(*scheduler, *original_image, *scaled_image, info, aspect_mask, resolution,
1177 device.IsFormatSupported(vk_format,
1178 VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT,
1179 OPTIMAL_FORMAT));
1175 } else { 1180 } else {
1176 using namespace VideoCommon; 1181 using namespace VideoCommon;
1177 static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy; 1182 static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy;
1183 const auto operation = is_bilinear ? Tegra::Engines::Fermi2D::Filter::Bilinear
1184 : Tegra::Engines::Fermi2D::Filter::Point;
1178 1185
1179 if (!scale_view) { 1186 if (!scale_view) {
1180 const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format); 1187 const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format);
@@ -1201,9 +1208,8 @@ bool Image::ScaleUp(bool ignore) {
1201 } 1208 }
1202 const auto color_view = scale_view->Handle(Shader::TextureType::Color2D); 1209 const auto color_view = scale_view->Handle(Shader::TextureType::Color2D);
1203 1210
1204 runtime->blit_image_helper.BlitColor( 1211 runtime->blit_image_helper.BlitColor(scale_framebuffer.get(), color_view, dst_region,
1205 scale_framebuffer.get(), color_view, dst_region, src_region, 1212 src_region, operation, BLIT_OPERATION);
1206 Tegra::Engines::Fermi2D::Filter::Bilinear, BLIT_OPERATION);
1207 } else if (!runtime->device.IsBlitDepthStencilSupported() && 1213 } else if (!runtime->device.IsBlitDepthStencilSupported() &&
1208 aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { 1214 aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
1209 if (!scale_framebuffer) { 1215 if (!scale_framebuffer) {
@@ -1212,7 +1218,7 @@ bool Image::ScaleUp(bool ignore) {
1212 } 1218 }
1213 runtime->blit_image_helper.BlitDepthStencil( 1219 runtime->blit_image_helper.BlitDepthStencil(
1214 scale_framebuffer.get(), scale_view->DepthView(), scale_view->StencilView(), 1220 scale_framebuffer.get(), scale_view->DepthView(), scale_view->StencilView(),
1215 dst_region, src_region, Tegra::Engines::Fermi2D::Filter::Point, BLIT_OPERATION); 1221 dst_region, src_region, operation, BLIT_OPERATION);
1216 } else { 1222 } else {
1217 // TODO: Use helper blits where applicable 1223 // TODO: Use helper blits where applicable
1218 flags &= ~ImageFlagBits::Rescaled; 1224 flags &= ~ImageFlagBits::Rescaled;
@@ -1233,8 +1239,8 @@ bool Image::ScaleDown(bool ignore) {
1233 return false; 1239 return false;
1234 } 1240 }
1235 if (ignore) { 1241 if (ignore) {
1236 current_image = *original_image; 1242 current_image = *original_image;
1237 return true; 1243 return true;
1238 } 1244 }
1239 const auto& device = runtime->device; 1245 const auto& device = runtime->device;
1240 const bool is_2d = info.type == ImageType::e2D; 1246 const bool is_2d = info.type == ImageType::e2D;
@@ -1247,11 +1253,16 @@ bool Image::ScaleDown(bool ignore) {
1247 const PixelFormat format = StorageFormat(info.format); 1253 const PixelFormat format = StorageFormat(info.format);
1248 const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format; 1254 const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format;
1249 const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; 1255 const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
1256 const bool is_color{aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT};
1257 const bool is_bilinear{is_color && !IsPixelFormatInteger(info.format)};
1250 if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) { 1258 if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) {
1251 BlitScale(*scheduler, *scaled_image, *original_image, info, aspect_mask, resolution, false); 1259 BlitScale(*scheduler, *scaled_image, *original_image, info, aspect_mask, resolution,
1260 is_bilinear, false);
1252 } else { 1261 } else {
1253 using namespace VideoCommon; 1262 using namespace VideoCommon;
1254 static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy; 1263 static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy;
1264 const auto operation = is_bilinear ? Tegra::Engines::Fermi2D::Filter::Bilinear
1265 : Tegra::Engines::Fermi2D::Filter::Point;
1255 1266
1256 if (!normal_view) { 1267 if (!normal_view) {
1257 const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format); 1268 const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format);
@@ -1278,9 +1289,8 @@ bool Image::ScaleDown(bool ignore) {
1278 } 1289 }
1279 const auto color_view = normal_view->Handle(Shader::TextureType::Color2D); 1290 const auto color_view = normal_view->Handle(Shader::TextureType::Color2D);
1280 1291
1281 runtime->blit_image_helper.BlitColor( 1292 runtime->blit_image_helper.BlitColor(normal_framebuffer.get(), color_view, dst_region,
1282 normal_framebuffer.get(), color_view, dst_region, src_region, 1293 src_region, operation, BLIT_OPERATION);
1283 Tegra::Engines::Fermi2D::Filter::Bilinear, BLIT_OPERATION);
1284 } else if (!runtime->device.IsBlitDepthStencilSupported() && 1294 } else if (!runtime->device.IsBlitDepthStencilSupported() &&
1285 aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { 1295 aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
1286 if (!normal_framebuffer) { 1296 if (!normal_framebuffer) {
@@ -1289,7 +1299,7 @@ bool Image::ScaleDown(bool ignore) {
1289 } 1299 }
1290 runtime->blit_image_helper.BlitDepthStencil( 1300 runtime->blit_image_helper.BlitDepthStencil(
1291 normal_framebuffer.get(), normal_view->DepthView(), normal_view->StencilView(), 1301 normal_framebuffer.get(), normal_view->DepthView(), normal_view->StencilView(),
1292 dst_region, src_region, Tegra::Engines::Fermi2D::Filter::Point, BLIT_OPERATION); 1302 dst_region, src_region, operation, BLIT_OPERATION);
1293 } else { 1303 } else {
1294 // TODO: Use helper blits where applicable 1304 // TODO: Use helper blits where applicable
1295 flags &= ~ImageFlagBits::Rescaled; 1305 flags &= ~ImageFlagBits::Rescaled;