summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_vulkan
diff options
context:
space:
mode:
authorFernando Sahmkow <fsahmkow27@gmail.com>2021-10-17 18:01:18 +0200
committerFernando Sahmkow <fsahmkow27@gmail.com>2021-11-16 22:11:31 +0100
commit425ab9ef4b982213f4ee0d53196f5474e255374f (patch)
tree467bc959ea481d58514d11ca73e8f31b3557d4aa /src/video_core/renderer_vulkan
parentPresentation: add Nearest Neighbor filter. (diff)
downloadyuzu-425ab9ef4b982213f4ee0d53196f5474e255374f.tar
yuzu-425ab9ef4b982213f4ee0d53196f5474e255374f.tar.gz
yuzu-425ab9ef4b982213f4ee0d53196f5474e255374f.tar.bz2
yuzu-425ab9ef4b982213f4ee0d53196f5474e255374f.tar.lz
yuzu-425ab9ef4b982213f4ee0d53196f5474e255374f.tar.xz
yuzu-425ab9ef4b982213f4ee0d53196f5474e255374f.tar.zst
yuzu-425ab9ef4b982213f4ee0d53196f5474e255374f.zip
Diffstat (limited to 'src/video_core/renderer_vulkan')
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp93
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h3
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 {
}
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) {
const bool is_2d = info.type == ImageType::e2D;
const auto resources = info.resources;
const VkExtent2D extent{
@@ -605,14 +606,16 @@ void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, con
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([dst_image, src_image, extent, resources, aspect_mask, resolution, is_2d,
- vk_filter](vk::CommandBuffer cmdbuf) {
+ vk_filter, up_scaling](vk::CommandBuffer cmdbuf) {
const VkOffset2D src_size{
- .x = static_cast<s32>(extent.width),
- .y = static_cast<s32>(extent.height),
+ .x = static_cast<s32>(up_scaling ? extent.width : resolution.ScaleUp(extent.width)),
+ .y = static_cast<s32>(is_2d && up_scaling ? extent.height
+ : resolution.ScaleUp(extent.height)),
};
const VkOffset2D dst_size{
- .x = static_cast<s32>(resolution.ScaleUp(extent.width)),
- .y = static_cast<s32>(is_2d ? resolution.ScaleUp(extent.height) : extent.height),
+ .x = static_cast<s32>(up_scaling ? resolution.ScaleUp(extent.width) : extent.width),
+ .y = static_cast<s32>(is_2d && up_scaling ? resolution.ScaleUp(extent.height)
+ : extent.height),
};
boost::container::small_vector<VkImageBlit, 4> regions;
regions.reserve(resources.levels);
@@ -1134,6 +1137,7 @@ bool Image::ScaleUp() {
if (!resolution.active) {
return false;
}
+ scale_count++;
const auto& device = runtime->device;
const bool is_2d = info.type == ImageType::e2D;
const u32 scaled_width = resolution.ScaleUp(info.size.width);
@@ -1161,8 +1165,10 @@ bool Image::ScaleUp() {
using namespace VideoCommon;
static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy;
- const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format);
- scale_view = std::make_unique<ImageView>(*runtime, view_info, NULL_IMAGE_ID, *this);
+ if (!scale_view) {
+ const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format);
+ scale_view = std::make_unique<ImageView>(*runtime, view_info, NULL_IMAGE_ID, *this);
+ }
auto* view_ptr = scale_view.get();
const Region2D src_region{
@@ -1178,7 +1184,10 @@ bool Image::ScaleUp() {
.height = scaled_height,
};
if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT) {
- scale_framebuffer = std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent);
+ if (!scale_framebuffer) {
+ scale_framebuffer =
+ std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent);
+ }
const auto color_view = scale_view->Handle(Shader::TextureType::Color2D);
runtime->blit_image_helper.BlitColor(
@@ -1186,7 +1195,10 @@ bool Image::ScaleUp() {
Tegra::Engines::Fermi2D::Filter::Bilinear, BLIT_OPERATION);
} else if (!runtime->device.IsBlitDepthStencilSupported() &&
aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
- scale_framebuffer = std::make_unique<Framebuffer>(*runtime, nullptr, view_ptr, extent);
+ if (!scale_framebuffer) {
+ scale_framebuffer =
+ std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent);
+ }
runtime->blit_image_helper.BlitDepthStencil(
scale_framebuffer.get(), scale_view->DepthView(), scale_view->StencilView(),
dst_region, src_region, Tegra::Engines::Fermi2D::Filter::Point, BLIT_OPERATION);
@@ -1209,6 +1221,67 @@ bool Image::ScaleDown() {
if (!resolution.active) {
return false;
}
+ const auto& device = runtime->device;
+ const bool is_2d = info.type == ImageType::e2D;
+ const u32 scaled_width = resolution.ScaleUp(info.size.width);
+ const u32 scaled_height = is_2d ? resolution.ScaleUp(info.size.height) : info.size.height;
+ if (aspect_mask == 0) {
+ aspect_mask = ImageAspectMask(info.format);
+ }
+ static constexpr auto OPTIMAL_FORMAT = FormatType::Optimal;
+ const PixelFormat format = StorageFormat(info.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;
+ if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) {
+ BlitScale(*scheduler, *scaled_image, *original_image, info, aspect_mask, resolution, false);
+ } else {
+ using namespace VideoCommon;
+ static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy;
+
+ if (!normal_view) {
+ const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format);
+ normal_view = std::make_unique<ImageView>(*runtime, view_info, NULL_IMAGE_ID, *this);
+ }
+ auto* view_ptr = normal_view.get();
+
+ const Region2D src_region{
+ .start = {0, 0},
+ .end = {static_cast<s32>(scaled_width), static_cast<s32>(scaled_height)},
+ };
+ const Region2D dst_region{
+ .start = {0, 0},
+ .end = {static_cast<s32>(info.size.width), static_cast<s32>(info.size.height)},
+ };
+ const VkExtent2D extent{
+ .width = scaled_width,
+ .height = scaled_height,
+ };
+ if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT) {
+ if (!normal_framebuffer) {
+ normal_framebuffer =
+ std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent);
+ }
+ const auto color_view = normal_view->Handle(Shader::TextureType::Color2D);
+
+ runtime->blit_image_helper.BlitColor(
+ normal_framebuffer.get(), color_view, dst_region, src_region,
+ Tegra::Engines::Fermi2D::Filter::Bilinear, BLIT_OPERATION);
+ } else if (!runtime->device.IsBlitDepthStencilSupported() &&
+ aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
+ if (!normal_framebuffer) {
+ normal_framebuffer =
+ std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent);
+ }
+ runtime->blit_image_helper.BlitDepthStencil(
+ normal_framebuffer.get(), normal_view->DepthView(), normal_view->StencilView(),
+ dst_region, src_region, Tegra::Engines::Fermi2D::Filter::Point, BLIT_OPERATION);
+ } else {
+ // TODO: Use helper blits where applicable
+ flags &= ~ImageFlagBits::Rescaled;
+ LOG_ERROR(Render_Vulkan, "Device does not support scaling format {}", format);
+ return false;
+ }
+ }
ASSERT(info.type != ImageType::Linear);
current_image = *original_image;
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:
std::unique_ptr<Framebuffer> scale_framebuffer;
std::unique_ptr<ImageView> scale_view;
+
+ std::unique_ptr<Framebuffer> normal_framebuffer;
+ std::unique_ptr<ImageView> normal_view;
};
class ImageView : public VideoCommon::ImageViewBase {