diff --git a/src/video_core/host_shaders/convert_abgr8_srgb_to_d24s8.frag b/src/video_core/host_shaders/convert_abgr8_srgb_to_d24s8.frag index a9bd21192d..2e464fffa6 100644 --- a/src/video_core/host_shaders/convert_abgr8_srgb_to_d24s8.frag +++ b/src/video_core/host_shaders/convert_abgr8_srgb_to_d24s8.frag @@ -5,9 +5,10 @@ layout(binding = 0) uniform sampler2D color_texture; -// More accurate sRGB to linear conversion +// Even more accurate sRGB to linear conversion +// https://entropymine.com/imageworsener/srgbformula/ float srgbToLinear(float srgb) { - if (srgb <= 0.04045) { + if (srgb <= 0.0404482362771082f) { //assumes it's >= 0 return srgb / 12.92; } else { return pow((srgb + 0.055) / 1.055, 2.4); diff --git a/src/video_core/renderer_vulkan/present/filters.cpp b/src/video_core/renderer_vulkan/present/filters.cpp index e5365acde9..7843f38d2c 100644 --- a/src/video_core/renderer_vulkan/present/filters.cpp +++ b/src/video_core/renderer_vulkan/present/filters.cpp @@ -46,8 +46,12 @@ std::unique_ptr MakeBilinear(const Device& device, VkFormat fra } std::unique_ptr MakeBicubic(const Device& device, VkFormat frame_format) { + // No need for handrolled shader -- if the VK impl can do it for us ;) + if (device.IsExtFilterCubicSupported()) + return std::make_unique(device, frame_format, CreateCubicSampler(device), + BuildShader(device, VULKAN_PRESENT_FRAG_SPV)); return std::make_unique(device, frame_format, CreateBilinearSampler(device), - BuildShader(device, PRESENT_BICUBIC_FRAG_SPV)); + BuildShader(device, PRESENT_BICUBIC_FRAG_SPV)); } std::unique_ptr MakeGaussian(const Device& device, VkFormat frame_format) { diff --git a/src/video_core/renderer_vulkan/present/util.cpp b/src/video_core/renderer_vulkan/present/util.cpp index 7f27c7c1b5..6874bbae99 100644 --- a/src/video_core/renderer_vulkan/present/util.cpp +++ b/src/video_core/renderer_vulkan/present/util.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -621,6 +624,31 @@ vk::Sampler CreateNearestNeighborSampler(const Device& device) { return device.GetLogical().CreateSampler(ci_nn); } +vk::Sampler CreateCubicSampler(const Device& device) { + const VkSamplerCreateInfo ci_nn{ + .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .magFilter = VK_FILTER_CUBIC_EXT, + .minFilter = VK_FILTER_CUBIC_EXT, + .mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST, + .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, + .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, + .addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, + .mipLodBias = 0.0f, + .anisotropyEnable = VK_FALSE, + .maxAnisotropy = 0.0f, + .compareEnable = VK_FALSE, + .compareOp = VK_COMPARE_OP_NEVER, + .minLod = 0.0f, + .maxLod = 0.0f, + .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK, + .unnormalizedCoordinates = VK_FALSE, + }; + + return device.GetLogical().CreateSampler(ci_nn); +} + void ClearColorImage(vk::CommandBuffer& cmdbuf, VkImage image) { static constexpr std::array subresources{{{ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, diff --git a/src/video_core/renderer_vulkan/present/util.h b/src/video_core/renderer_vulkan/present/util.h index 5b22f0fa82..11810352df 100644 --- a/src/video_core/renderer_vulkan/present/util.h +++ b/src/video_core/renderer_vulkan/present/util.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -54,6 +57,7 @@ VkWriteDescriptorSet CreateWriteDescriptorSet(std::vector VkDescriptorSet set, u32 binding); vk::Sampler CreateBilinearSampler(const Device& device); vk::Sampler CreateNearestNeighborSampler(const Device& device); +vk::Sampler CreateCubicSampler(const Device& device); void BeginRenderPass(vk::CommandBuffer& cmdbuf, VkRenderPass render_pass, VkFramebuffer framebuffer, VkExtent2D extent); diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index ddc9451a7e..9b78f2e599 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -85,7 +88,8 @@ VK_DEFINE_HANDLE(VmaAllocator) EXTENSION(NV, GEOMETRY_SHADER_PASSTHROUGH, geometry_shader_passthrough) \ EXTENSION(NV, VIEWPORT_ARRAY2, viewport_array2) \ EXTENSION(NV, VIEWPORT_SWIZZLE, viewport_swizzle) \ - EXTENSION(EXT, DESCRIPTOR_INDEXING, descriptor_indexing) + EXTENSION(EXT, DESCRIPTOR_INDEXING, descriptor_indexing) \ + EXTENSION(EXT, FILTER_CUBIC, filter_cubic) // Define extensions which must be supported. #define FOR_EACH_VK_MANDATORY_EXTENSION(EXTENSION_NAME) \ @@ -549,6 +553,11 @@ public: return dynamic_state3_enables; } + /// Returns true if the device supports VK_EXT_filter_cubic + bool IsExtFilterCubicSupported() const { + return extensions.filter_cubic; + } + /// Returns true if the device supports VK_EXT_line_rasterization. bool IsExtLineRasterizationSupported() const { return extensions.line_rasterization;