diff options
| author | 2021-10-22 23:46:21 -0400 | |
|---|---|---|
| committer | 2021-11-16 22:11:32 +0100 | |
| commit | 282a4501d9b8c3e68e1c4545778097888caa7a88 (patch) | |
| tree | d2204b5eae6b59a34c0f7dc38a1183111db4adca /src | |
| parent | gl_rasterizer: Fix ScissorTest and Clear when scaling (diff) | |
| download | yuzu-282a4501d9b8c3e68e1c4545778097888caa7a88.tar.gz yuzu-282a4501d9b8c3e68e1c4545778097888caa7a88.tar.xz yuzu-282a4501d9b8c3e68e1c4545778097888caa7a88.zip | |
vk_texture_cache: Refactor 3D scaling helpers
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 185 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.h | 2 |
2 files changed, 74 insertions, 113 deletions
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 413d472cd..85a1d520b 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -593,13 +593,16 @@ struct RangedBarrierRange { | |||
| 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 is_bilinear, bool up_scaling = true) { | 596 | 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{ |
| 600 | .width = info.size.width, | 600 | .width = info.size.width, |
| 601 | .height = info.size.height, | 601 | .height = info.size.height, |
| 602 | }; | 602 | }; |
| 603 | // Depth and integer formats must use NEAREST filter for blits. | ||
| 604 | const bool is_color{aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT}; | ||
| 605 | const bool is_bilinear{is_color && !IsPixelFormatInteger(info.format)}; | ||
| 603 | const VkFilter vk_filter = is_bilinear ? VK_FILTER_LINEAR : VK_FILTER_NEAREST; | 606 | const VkFilter vk_filter = is_bilinear ? VK_FILTER_LINEAR : VK_FILTER_NEAREST; |
| 604 | 607 | ||
| 605 | scheduler.RequestOutsideRenderPassOperationContext(); | 608 | scheduler.RequestOutsideRenderPassOperationContext(); |
| @@ -1144,10 +1147,10 @@ bool Image::ScaleUp(bool ignore) { | |||
| 1144 | } | 1147 | } |
| 1145 | has_scaled = true; | 1148 | has_scaled = true; |
| 1146 | const auto& device = runtime->device; | 1149 | const auto& device = runtime->device; |
| 1147 | const bool is_2d = info.type == ImageType::e2D; | ||
| 1148 | const u32 scaled_width = resolution.ScaleUp(info.size.width); | ||
| 1149 | const u32 scaled_height = is_2d ? resolution.ScaleUp(info.size.height) : info.size.height; | ||
| 1150 | if (!scaled_image) { | 1150 | if (!scaled_image) { |
| 1151 | const bool is_2d = info.type == ImageType::e2D; | ||
| 1152 | const u32 scaled_width = resolution.ScaleUp(info.size.width); | ||
| 1153 | const u32 scaled_height = is_2d ? resolution.ScaleUp(info.size.height) : info.size.height; | ||
| 1151 | auto scaled_info = info; | 1154 | auto scaled_info = info; |
| 1152 | scaled_info.size.width = scaled_width; | 1155 | scaled_info.size.width = scaled_width; |
| 1153 | scaled_info.size.height = scaled_height; | 1156 | scaled_info.size.height = scaled_height; |
| @@ -1168,61 +1171,10 @@ bool Image::ScaleUp(bool ignore) { | |||
| 1168 | const PixelFormat format = StorageFormat(info.format); | 1171 | const PixelFormat format = StorageFormat(info.format); |
| 1169 | const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format; | 1172 | const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format; |
| 1170 | const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; | 1173 | const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; |
| 1171 | const bool is_color{aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT}; | ||
| 1172 | const bool is_bilinear{is_color && !IsPixelFormatInteger(info.format)}; | ||
| 1173 | if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) { | 1174 | if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) { |
| 1174 | BlitScale(*scheduler, *original_image, *scaled_image, info, aspect_mask, resolution, | 1175 | BlitScale(*scheduler, *original_image, *scaled_image, info, aspect_mask, resolution); |
| 1175 | device.IsFormatSupported(vk_format, | ||
| 1176 | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT, | ||
| 1177 | OPTIMAL_FORMAT)); | ||
| 1178 | } else { | 1176 | } else { |
| 1179 | using namespace VideoCommon; | 1177 | return BlitScaleHelper(true); |
| 1180 | static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy; | ||
| 1181 | const auto operation = is_bilinear ? Tegra::Engines::Fermi2D::Filter::Bilinear | ||
| 1182 | : Tegra::Engines::Fermi2D::Filter::Point; | ||
| 1183 | |||
| 1184 | if (!scale_view) { | ||
| 1185 | const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format); | ||
| 1186 | scale_view = std::make_unique<ImageView>(*runtime, view_info, NULL_IMAGE_ID, *this); | ||
| 1187 | } | ||
| 1188 | auto* view_ptr = scale_view.get(); | ||
| 1189 | |||
| 1190 | const Region2D src_region{ | ||
| 1191 | .start = {0, 0}, | ||
| 1192 | .end = {static_cast<s32>(info.size.width), static_cast<s32>(info.size.height)}, | ||
| 1193 | }; | ||
| 1194 | const Region2D dst_region{ | ||
| 1195 | .start = {0, 0}, | ||
| 1196 | .end = {static_cast<s32>(scaled_width), static_cast<s32>(scaled_height)}, | ||
| 1197 | }; | ||
| 1198 | const VkExtent2D extent{ | ||
| 1199 | .width = scaled_width, | ||
| 1200 | .height = scaled_height, | ||
| 1201 | }; | ||
| 1202 | if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT) { | ||
| 1203 | if (!scale_framebuffer) { | ||
| 1204 | scale_framebuffer = | ||
| 1205 | std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent); | ||
| 1206 | } | ||
| 1207 | const auto color_view = scale_view->Handle(Shader::TextureType::Color2D); | ||
| 1208 | |||
| 1209 | runtime->blit_image_helper.BlitColor(scale_framebuffer.get(), color_view, dst_region, | ||
| 1210 | src_region, operation, BLIT_OPERATION); | ||
| 1211 | } else if (!runtime->device.IsBlitDepthStencilSupported() && | ||
| 1212 | aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { | ||
| 1213 | if (!scale_framebuffer) { | ||
| 1214 | scale_framebuffer = | ||
| 1215 | std::make_unique<Framebuffer>(*runtime, nullptr, view_ptr, extent); | ||
| 1216 | } | ||
| 1217 | runtime->blit_image_helper.BlitDepthStencil( | ||
| 1218 | scale_framebuffer.get(), scale_view->DepthView(), scale_view->StencilView(), | ||
| 1219 | dst_region, src_region, operation, BLIT_OPERATION); | ||
| 1220 | } else { | ||
| 1221 | // TODO: Use helper blits where applicable | ||
| 1222 | flags &= ~ImageFlagBits::Rescaled; | ||
| 1223 | LOG_ERROR(Render_Vulkan, "Device does not support scaling format {}", format); | ||
| 1224 | return false; | ||
| 1225 | } | ||
| 1226 | } | 1178 | } |
| 1227 | return true; | 1179 | return true; |
| 1228 | } | 1180 | } |
| @@ -1231,82 +1183,89 @@ bool Image::ScaleDown(bool ignore) { | |||
| 1231 | if (False(flags & ImageFlagBits::Rescaled)) { | 1183 | if (False(flags & ImageFlagBits::Rescaled)) { |
| 1232 | return false; | 1184 | return false; |
| 1233 | } | 1185 | } |
| 1186 | ASSERT(info.type != ImageType::Linear); | ||
| 1234 | flags &= ~ImageFlagBits::Rescaled; | 1187 | flags &= ~ImageFlagBits::Rescaled; |
| 1235 | const auto& resolution = runtime->resolution; | 1188 | const auto& resolution = runtime->resolution; |
| 1236 | if (!resolution.active) { | 1189 | if (!resolution.active) { |
| 1237 | return false; | 1190 | return false; |
| 1238 | } | 1191 | } |
| 1192 | current_image = *original_image; | ||
| 1239 | if (ignore) { | 1193 | if (ignore) { |
| 1240 | current_image = *original_image; | ||
| 1241 | return true; | 1194 | return true; |
| 1242 | } | 1195 | } |
| 1243 | const auto& device = runtime->device; | ||
| 1244 | const bool is_2d = info.type == ImageType::e2D; | ||
| 1245 | const u32 scaled_width = resolution.ScaleUp(info.size.width); | ||
| 1246 | const u32 scaled_height = is_2d ? resolution.ScaleUp(info.size.height) : info.size.height; | ||
| 1247 | if (aspect_mask == 0) { | 1196 | if (aspect_mask == 0) { |
| 1248 | aspect_mask = ImageAspectMask(info.format); | 1197 | aspect_mask = ImageAspectMask(info.format); |
| 1249 | } | 1198 | } |
| 1250 | static constexpr auto OPTIMAL_FORMAT = FormatType::Optimal; | 1199 | static constexpr auto OPTIMAL_FORMAT = FormatType::Optimal; |
| 1251 | const PixelFormat format = StorageFormat(info.format); | 1200 | const PixelFormat format = StorageFormat(info.format); |
| 1201 | const auto& device = runtime->device; | ||
| 1252 | const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format; | 1202 | const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format; |
| 1253 | const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; | 1203 | const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; |
| 1254 | const bool is_color{aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT}; | ||
| 1255 | const bool is_bilinear{is_color && !IsPixelFormatInteger(info.format)}; | ||
| 1256 | if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) { | 1204 | if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) { |
| 1257 | BlitScale(*scheduler, *scaled_image, *original_image, info, aspect_mask, resolution, | 1205 | BlitScale(*scheduler, *scaled_image, *original_image, info, aspect_mask, resolution, false); |
| 1258 | is_bilinear, false); | ||
| 1259 | } else { | 1206 | } else { |
| 1260 | using namespace VideoCommon; | 1207 | return BlitScaleHelper(false); |
| 1261 | static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy; | 1208 | } |
| 1262 | const auto operation = is_bilinear ? Tegra::Engines::Fermi2D::Filter::Bilinear | 1209 | return true; |
| 1263 | : Tegra::Engines::Fermi2D::Filter::Point; | 1210 | } |
| 1264 | |||
| 1265 | if (!normal_view) { | ||
| 1266 | const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format); | ||
| 1267 | normal_view = std::make_unique<ImageView>(*runtime, view_info, NULL_IMAGE_ID, *this); | ||
| 1268 | } | ||
| 1269 | auto* view_ptr = normal_view.get(); | ||
| 1270 | 1211 | ||
| 1271 | const Region2D src_region{ | 1212 | bool Image::BlitScaleHelper(bool scale_up) { |
| 1272 | .start = {0, 0}, | 1213 | using namespace VideoCommon; |
| 1273 | .end = {static_cast<s32>(scaled_width), static_cast<s32>(scaled_height)}, | 1214 | static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy; |
| 1274 | }; | 1215 | const bool is_color{aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT}; |
| 1275 | const Region2D dst_region{ | 1216 | const bool is_bilinear{is_color && !IsPixelFormatInteger(info.format)}; |
| 1276 | .start = {0, 0}, | 1217 | const auto operation = is_bilinear ? Tegra::Engines::Fermi2D::Filter::Bilinear |
| 1277 | .end = {static_cast<s32>(info.size.width), static_cast<s32>(info.size.height)}, | 1218 | : Tegra::Engines::Fermi2D::Filter::Point; |
| 1278 | }; | 1219 | |
| 1279 | const VkExtent2D extent{ | 1220 | const bool is_2d = info.type == ImageType::e2D; |
| 1280 | .width = scaled_width, | 1221 | const auto& resolution = runtime->resolution; |
| 1281 | .height = scaled_height, | 1222 | const u32 scaled_width = resolution.ScaleUp(info.size.width); |
| 1282 | }; | 1223 | const u32 scaled_height = is_2d ? resolution.ScaleUp(info.size.height) : info.size.height; |
| 1283 | if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT) { | 1224 | if (!scale_view) { |
| 1284 | if (!normal_framebuffer) { | 1225 | const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format); |
| 1285 | normal_framebuffer = | 1226 | scale_view = std::make_unique<ImageView>(*runtime, view_info, NULL_IMAGE_ID, *this); |
| 1286 | std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent); | 1227 | } |
| 1287 | } | 1228 | |
| 1288 | const auto color_view = normal_view->Handle(Shader::TextureType::Color2D); | 1229 | const u32 src_width = scale_up ? info.size.width : scaled_width; |
| 1289 | 1230 | const u32 src_height = scale_up ? info.size.height : scaled_height; | |
| 1290 | runtime->blit_image_helper.BlitColor(normal_framebuffer.get(), color_view, dst_region, | 1231 | const u32 dst_width = scale_up ? scaled_width : info.size.width; |
| 1291 | src_region, operation, BLIT_OPERATION); | 1232 | const u32 dst_height = scale_up ? scaled_height : info.size.height; |
| 1292 | } else if (!runtime->device.IsBlitDepthStencilSupported() && | 1233 | const Region2D src_region{ |
| 1293 | aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { | 1234 | .start = {0, 0}, |
| 1294 | if (!normal_framebuffer) { | 1235 | .end = {static_cast<s32>(src_width), static_cast<s32>(src_height)}, |
| 1295 | normal_framebuffer = | 1236 | }; |
| 1296 | std::make_unique<Framebuffer>(*runtime, nullptr, view_ptr, extent); | 1237 | const Region2D dst_region{ |
| 1297 | } | 1238 | .start = {0, 0}, |
| 1298 | runtime->blit_image_helper.BlitDepthStencil( | 1239 | .end = {static_cast<s32>(dst_width), static_cast<s32>(dst_height)}, |
| 1299 | normal_framebuffer.get(), normal_view->DepthView(), normal_view->StencilView(), | 1240 | }; |
| 1300 | dst_region, src_region, operation, BLIT_OPERATION); | 1241 | const VkExtent2D extent{ |
| 1301 | } else { | 1242 | .width = scaled_width, |
| 1302 | // TODO: Use helper blits where applicable | 1243 | .height = scaled_height, |
| 1303 | flags &= ~ImageFlagBits::Rescaled; | 1244 | }; |
| 1304 | LOG_ERROR(Render_Vulkan, "Device does not support scaling format {}", format); | 1245 | |
| 1305 | return false; | 1246 | auto* view_ptr = scale_view.get(); |
| 1247 | if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT) { | ||
| 1248 | if (!scale_framebuffer) { | ||
| 1249 | scale_framebuffer = std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent); | ||
| 1250 | } | ||
| 1251 | const auto color_view = scale_view->Handle(Shader::TextureType::Color2D); | ||
| 1252 | |||
| 1253 | runtime->blit_image_helper.BlitColor(scale_framebuffer.get(), color_view, dst_region, | ||
| 1254 | src_region, operation, BLIT_OPERATION); | ||
| 1255 | } else if (!runtime->device.IsBlitDepthStencilSupported() && | ||
| 1256 | aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { | ||
| 1257 | if (!scale_framebuffer) { | ||
| 1258 | scale_framebuffer = std::make_unique<Framebuffer>(*runtime, nullptr, view_ptr, extent); | ||
| 1306 | } | 1259 | } |
| 1260 | runtime->blit_image_helper.BlitDepthStencil( | ||
| 1261 | scale_framebuffer.get(), scale_view->DepthView(), scale_view->StencilView(), dst_region, | ||
| 1262 | src_region, operation, BLIT_OPERATION); | ||
| 1263 | } else { | ||
| 1264 | // TODO: Use helper blits where applicable | ||
| 1265 | flags &= ~ImageFlagBits::Rescaled; | ||
| 1266 | LOG_ERROR(Render_Vulkan, "Device does not support scaling format {}", info.format); | ||
| 1267 | return false; | ||
| 1307 | } | 1268 | } |
| 1308 | ASSERT(info.type != ImageType::Linear); | ||
| 1309 | current_image = *original_image; | ||
| 1310 | return true; | 1269 | return true; |
| 1311 | } | 1270 | } |
| 1312 | 1271 | ||
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 8dbddfaf7..9d149d306 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -134,6 +134,8 @@ public: | |||
| 134 | bool ScaleDown(bool ignore = false); | 134 | bool ScaleDown(bool ignore = false); |
| 135 | 135 | ||
| 136 | private: | 136 | private: |
| 137 | bool BlitScaleHelper(bool scale_up); | ||
| 138 | |||
| 137 | VKScheduler* scheduler{}; | 139 | VKScheduler* scheduler{}; |
| 138 | TextureCacheRuntime* runtime{}; | 140 | TextureCacheRuntime* runtime{}; |
| 139 | 141 | ||