mirror of
				https://git.suyu.dev/suyu/suyu.git
				synced 2025-10-31 14:56:40 +08:00 
			
		
		
		
	TextureCache: Fix blitting filter in Vulkan and correct viewport/scissor calculation when downscaling.
This commit is contained in:
		
							parent
							
								
									3b61de74e6
								
							
						
					
					
						commit
						f3ff8bdc0e
					
				| @ -60,10 +60,19 @@ struct DrawParams { | |||||||
| 
 | 
 | ||||||
| VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t index, float scale) { | VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t index, float scale) { | ||||||
|     const auto& src = regs.viewport_transform[index]; |     const auto& src = regs.viewport_transform[index]; | ||||||
|     const float x = (src.translate_x - src.scale_x) * scale; |     const auto conv = [scale](float value) { | ||||||
|     const float width = src.scale_x * 2.0f * scale; |         float new_value = value * scale; | ||||||
|     float y = (src.translate_y - src.scale_y) * scale; |         if (scale < 1.0f) { | ||||||
|     float height = src.scale_y * 2.0f * scale; |             bool sign = std::signbit(new_value); | ||||||
|  |             new_value = std::round(std::abs(new_value)); | ||||||
|  |             new_value = sign ? -new_value : new_value; | ||||||
|  |         } | ||||||
|  |         return new_value; | ||||||
|  |     }; | ||||||
|  |     const float x = conv(src.translate_x - src.scale_x); | ||||||
|  |     const float width = conv(src.scale_x * 2.0f); | ||||||
|  |     float y = conv(src.translate_y - src.scale_y); | ||||||
|  |     float height = conv(src.scale_y * 2.0f); | ||||||
|     if (regs.screen_y_control.y_negate) { |     if (regs.screen_y_control.y_negate) { | ||||||
|         y += height; |         y += height; | ||||||
|         height = -height; |         height = -height; | ||||||
| @ -91,8 +100,13 @@ VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u3 | |||||||
|         if (value == 0) { |         if (value == 0) { | ||||||
|             return 0U; |             return 0U; | ||||||
|         } |         } | ||||||
|  |         const u32 upset = value * up_scale; | ||||||
|  |         u32 acumm = 0; | ||||||
|  |         if ((up_scale >> down_shift) == 0) { | ||||||
|  |             acumm = upset & 0x1; | ||||||
|  |         } | ||||||
|         const u32 converted_value = (value * up_scale) >> down_shift; |         const u32 converted_value = (value * up_scale) >> down_shift; | ||||||
|         return std::max<u32>(converted_value, 1U); |         return std::max<u32>(converted_value + acumm, 1U); | ||||||
|     }; |     }; | ||||||
|     if (src.enable) { |     if (src.enable) { | ||||||
|         scissor.offset.x = static_cast<s32>(scale_up(src.min_x)); |         scissor.offset.x = static_cast<s32>(scale_up(src.min_x)); | ||||||
|  | |||||||
| @ -593,7 +593,7 @@ struct RangedBarrierRange { | |||||||
| 
 | 
 | ||||||
| void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, const ImageInfo& info, | void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, const ImageInfo& info, | ||||||
|                VkImageAspectFlags aspect_mask, const Settings::ResolutionScalingInfo& resolution, |                VkImageAspectFlags aspect_mask, const Settings::ResolutionScalingInfo& resolution, | ||||||
|                bool up_scaling = true) { |                bool is_bilinear, bool up_scaling = true) { | ||||||
|     const bool is_2d = info.type == ImageType::e2D; |     const bool is_2d = info.type == ImageType::e2D; | ||||||
|     const auto resources = info.resources; |     const auto resources = info.resources; | ||||||
|     const VkExtent2D extent{ |     const VkExtent2D extent{ | ||||||
| @ -602,7 +602,7 @@ void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, con | |||||||
|     }; |     }; | ||||||
|     const bool is_zeta = (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; |     const bool is_zeta = (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; | ||||||
|     const bool is_int_format = IsPixelFormatInteger(info.format); |     const bool is_int_format = IsPixelFormatInteger(info.format); | ||||||
|     const VkFilter vk_filter = (is_zeta || is_int_format) ? VK_FILTER_NEAREST : VK_FILTER_LINEAR; |     const VkFilter vk_filter = is_bilinear ? VK_FILTER_LINEAR : VK_FILTER_NEAREST; | ||||||
| 
 | 
 | ||||||
|     scheduler.RequestOutsideRenderPassOperationContext(); |     scheduler.RequestOutsideRenderPassOperationContext(); | ||||||
|     scheduler.Record([dst_image, src_image, extent, resources, aspect_mask, resolution, is_2d, |     scheduler.Record([dst_image, src_image, extent, resources, aspect_mask, resolution, is_2d, | ||||||
| @ -1170,11 +1170,18 @@ bool Image::ScaleUp(bool ignore) { | |||||||
|     const PixelFormat format = StorageFormat(info.format); |     const PixelFormat format = StorageFormat(info.format); | ||||||
|     const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format; |     const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format; | ||||||
|     const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; |     const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; | ||||||
|  |     const bool is_color{aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT}; | ||||||
|  |     const bool is_bilinear{is_color && !IsPixelFormatInteger(info.format)}; | ||||||
|     if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) { |     if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) { | ||||||
|         BlitScale(*scheduler, *original_image, *scaled_image, info, aspect_mask, resolution); |         BlitScale(*scheduler, *original_image, *scaled_image, info, aspect_mask, resolution, | ||||||
|  |                   device.IsFormatSupported(vk_format, | ||||||
|  |                                            VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT, | ||||||
|  |                                            OPTIMAL_FORMAT)); | ||||||
|     } else { |     } else { | ||||||
|         using namespace VideoCommon; |         using namespace VideoCommon; | ||||||
|         static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy; |         static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy; | ||||||
|  |         const auto operation = is_bilinear ? Tegra::Engines::Fermi2D::Filter::Bilinear | ||||||
|  |                                            : Tegra::Engines::Fermi2D::Filter::Point; | ||||||
| 
 | 
 | ||||||
|         if (!scale_view) { |         if (!scale_view) { | ||||||
|             const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format); |             const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format); | ||||||
| @ -1201,9 +1208,8 @@ bool Image::ScaleUp(bool ignore) { | |||||||
|             } |             } | ||||||
|             const auto color_view = scale_view->Handle(Shader::TextureType::Color2D); |             const auto color_view = scale_view->Handle(Shader::TextureType::Color2D); | ||||||
| 
 | 
 | ||||||
|             runtime->blit_image_helper.BlitColor( |             runtime->blit_image_helper.BlitColor(scale_framebuffer.get(), color_view, dst_region, | ||||||
|                 scale_framebuffer.get(), color_view, dst_region, src_region, |                                                  src_region, operation, BLIT_OPERATION); | ||||||
|                 Tegra::Engines::Fermi2D::Filter::Bilinear, BLIT_OPERATION); |  | ||||||
|         } else if (!runtime->device.IsBlitDepthStencilSupported() && |         } else if (!runtime->device.IsBlitDepthStencilSupported() && | ||||||
|                    aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { |                    aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { | ||||||
|             if (!scale_framebuffer) { |             if (!scale_framebuffer) { | ||||||
| @ -1212,7 +1218,7 @@ bool Image::ScaleUp(bool ignore) { | |||||||
|             } |             } | ||||||
|             runtime->blit_image_helper.BlitDepthStencil( |             runtime->blit_image_helper.BlitDepthStencil( | ||||||
|                 scale_framebuffer.get(), scale_view->DepthView(), scale_view->StencilView(), |                 scale_framebuffer.get(), scale_view->DepthView(), scale_view->StencilView(), | ||||||
|                 dst_region, src_region, Tegra::Engines::Fermi2D::Filter::Point, BLIT_OPERATION); |                 dst_region, src_region, operation, BLIT_OPERATION); | ||||||
|         } else { |         } else { | ||||||
|             // TODO: Use helper blits where applicable
 |             // TODO: Use helper blits where applicable
 | ||||||
|             flags &= ~ImageFlagBits::Rescaled; |             flags &= ~ImageFlagBits::Rescaled; | ||||||
| @ -1247,11 +1253,16 @@ bool Image::ScaleDown(bool ignore) { | |||||||
|     const PixelFormat format = StorageFormat(info.format); |     const PixelFormat format = StorageFormat(info.format); | ||||||
|     const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format; |     const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format; | ||||||
|     const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; |     const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; | ||||||
|  |     const bool is_color{aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT}; | ||||||
|  |     const bool is_bilinear{is_color && !IsPixelFormatInteger(info.format)}; | ||||||
|     if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) { |     if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) { | ||||||
|         BlitScale(*scheduler, *scaled_image, *original_image, info, aspect_mask, resolution, false); |         BlitScale(*scheduler, *scaled_image, *original_image, info, aspect_mask, resolution, | ||||||
|  |                   is_bilinear, false); | ||||||
|     } else { |     } else { | ||||||
|         using namespace VideoCommon; |         using namespace VideoCommon; | ||||||
|         static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy; |         static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy; | ||||||
|  |         const auto operation = is_bilinear ? Tegra::Engines::Fermi2D::Filter::Bilinear | ||||||
|  |                                            : Tegra::Engines::Fermi2D::Filter::Point; | ||||||
| 
 | 
 | ||||||
|         if (!normal_view) { |         if (!normal_view) { | ||||||
|             const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format); |             const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format); | ||||||
| @ -1278,9 +1289,8 @@ bool Image::ScaleDown(bool ignore) { | |||||||
|             } |             } | ||||||
|             const auto color_view = normal_view->Handle(Shader::TextureType::Color2D); |             const auto color_view = normal_view->Handle(Shader::TextureType::Color2D); | ||||||
| 
 | 
 | ||||||
|             runtime->blit_image_helper.BlitColor( |             runtime->blit_image_helper.BlitColor(normal_framebuffer.get(), color_view, dst_region, | ||||||
|                 normal_framebuffer.get(), color_view, dst_region, src_region, |                                                  src_region, operation, BLIT_OPERATION); | ||||||
|                 Tegra::Engines::Fermi2D::Filter::Bilinear, BLIT_OPERATION); |  | ||||||
|         } else if (!runtime->device.IsBlitDepthStencilSupported() && |         } else if (!runtime->device.IsBlitDepthStencilSupported() && | ||||||
|                    aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { |                    aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { | ||||||
|             if (!normal_framebuffer) { |             if (!normal_framebuffer) { | ||||||
| @ -1289,7 +1299,7 @@ bool Image::ScaleDown(bool ignore) { | |||||||
|             } |             } | ||||||
|             runtime->blit_image_helper.BlitDepthStencil( |             runtime->blit_image_helper.BlitDepthStencil( | ||||||
|                 normal_framebuffer.get(), normal_view->DepthView(), normal_view->StencilView(), |                 normal_framebuffer.get(), normal_view->DepthView(), normal_view->StencilView(), | ||||||
|                 dst_region, src_region, Tegra::Engines::Fermi2D::Filter::Point, BLIT_OPERATION); |                 dst_region, src_region, operation, BLIT_OPERATION); | ||||||
|         } else { |         } else { | ||||||
|             // TODO: Use helper blits where applicable
 |             // TODO: Use helper blits where applicable
 | ||||||
|             flags &= ~ImageFlagBits::Rescaled; |             flags &= ~ImageFlagBits::Rescaled; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user