From 7087d889bb2e214d1d5e96d6a802b655254f9569 Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 13 Jan 2026 13:09:17 +0000 Subject: [PATCH 01/37] [video_core/host_shaders] add Snapdragon GSRv1 fragment shaders Signed-off-by: lizzie --- .patch/snapdragon_gsr/0001-glslang-fix.patch | 61 ++++++++++++++++++++ CMakeLists.txt | 3 + cpmfile.json | 9 +++ src/video_core/host_shaders/CMakeLists.txt | 36 +++++++++++- 4 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 .patch/snapdragon_gsr/0001-glslang-fix.patch diff --git a/.patch/snapdragon_gsr/0001-glslang-fix.patch b/.patch/snapdragon_gsr/0001-glslang-fix.patch new file mode 100644 index 0000000000..2eb0099d64 --- /dev/null +++ b/.patch/snapdragon_gsr/0001-glslang-fix.patch @@ -0,0 +1,61 @@ +diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +index 7074999..69927af 100644 +--- a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag ++++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +@@ -1,4 +1,4 @@ +-#version 300 es ++#version 320 es + + //============================================================================================================ + // +@@ -63,9 +63,9 @@ vec2 weightY(float dx, float dy,float c, float std) + + void main() + { +- int mode = OperationMode; +- float edgeThreshold = EdgeThreshold; +- float edgeSharpness = EdgeSharpness; ++ const int mode = OperationMode; ++ const float edgeThreshold = EdgeThreshold; ++ const float edgeSharpness = EdgeSharpness; + + vec4 color; + if(mode == 1) +@@ -93,10 +93,10 @@ void main() + { + coord.x += ViewportInfo[0].x; + +- vec4 right = textureGather(ps0,coord + highp vec2(ViewportInfo[0].x, 0.0), mode); ++ vec4 right = textureGather(ps0,coord + vec2(ViewportInfo[0].x, 0.0), mode); + vec4 upDown; +- upDown.xy = textureGather(ps0,coord + highp vec2(0.0, -ViewportInfo[0].y),mode).wz; +- upDown.zw = textureGather(ps0,coord+ highp vec2(0.0, ViewportInfo[0].y), mode).yx; ++ upDown.xy = textureGather(ps0,coord + vec2(0.0, -ViewportInfo[0].y),mode).wz; ++ upDown.zw = textureGather(ps0,coord+ vec2(0.0, ViewportInfo[0].y), mode).yx; + + float mean = (left.y+left.z+right.x+right.w)*0.25; + left = left - vec4(mean); +diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +index d2df646..1f1daa6 100644 +--- a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag ++++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +@@ -1,4 +1,4 @@ +-#version 300 es ++#version 320 es + + //============================================================================================================ + // +@@ -124,10 +124,10 @@ void main() + { + coord.x += ViewportInfo[0].x; + +- vec4 right = textureGather(ps0,coord + highp vec2(ViewportInfo[0].x, 0.0), OperationMode); ++ vec4 right = textureGather(ps0,coord + vec2(ViewportInfo[0].x, 0.0), OperationMode); + vec4 upDown; +- upDown.xy = textureGather(ps0,coord + highp vec2(0.0, -ViewportInfo[0].y),OperationMode).wz; +- upDown.zw = textureGather(ps0,coord+ highp vec2(0.0, ViewportInfo[0].y), OperationMode).yx; ++ upDown.xy = textureGather(ps0,coord + vec2(0.0, -ViewportInfo[0].y),OperationMode).wz; ++ upDown.zw = textureGather(ps0,coord+ vec2(0.0, ViewportInfo[0].y), OperationMode).yx; + + float mean = (left.y+left.z+right.x+right.w)*0.25; + left = left - vec4(mean); diff --git a/CMakeLists.txt b/CMakeLists.txt index 42717c496d..c071c6e1f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -233,6 +233,9 @@ endif() option(YUZU_USE_BUNDLED_OPENSSL "Download bundled OpenSSL build" ${DEFAULT_YUZU_USE_BUNDLED_OPENSSL}) +AddJsonPackage(snapdragon_gsr) + +# TODO(crueter): CPM this if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL) AddJsonPackage(vulkan-validation-layers) diff --git a/cpmfile.json b/cpmfile.json index 1bb29afae4..b9a1110106 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -102,6 +102,15 @@ "artifact": "android-binaries-%VERSION%.zip", "hash": "8812ae84cbe49e6a3418ade9c458d3be6d74a3dffd319d4502007b564d580998056e8190414368ec11b27bc83993c7a0dad713c31bcc3d9553b51243efee3753" }, + "snapdragon_gsr": { + "repo": "SnapdragonStudios/snapdragon-gsr", + "package": "snapdragon_gsr", + "hash": "dsfsdfsd", + "sha": "d926f074bcb9d714e179f1ce0fcb9ee2eeb5074e", + "patches": [ + "0001-glslang-fix.patch" + ] + }, "quazip": { "package": "QuaZip-Qt6", "repo": "stachenov/quazip", diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 60b399ccba..30daaa9cde 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -2,6 +2,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later set(FIDELITYFX_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/externals/FidelityFX-FSR/ffx-fsr) +set(SNAPDRAGON_GSR_INCLUDE_DIR ${snapdragon_gsr_SOURCE_DIR}/sgsr/v1/include/glsl/) set(FIDELITYFX_FILES ${FIDELITYFX_INCLUDE_DIR}/ffx_a.h @@ -76,6 +77,8 @@ set(SHADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_quad_indexed.comp ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_turbo_mode.comp ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_uint8.comp + ${SNAPDRAGON_GSR_INCLUDE_DIR}/sgsr1_shader_mobile.frag + ${SNAPDRAGON_GSR_INCLUDE_DIR}/sgsr1_shader_mobile_edge_direction.frag ) if (PLATFORM_HAIKU) @@ -145,11 +148,42 @@ foreach(SOURCE_FILE IN ITEMS ${SHADER_FILES}) OUTPUT ${SPIRV_HEADER_FILE} COMMAND - ${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -I"${FIDELITYFX_INCLUDE_DIR}" ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} --target-env ${SPIR_V_VERSION} + ${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -DUseUniformBlock=1 ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} --target-env ${SPIR_V_VERSION} MAIN_DEPENDENCY ${SOURCE_FILE} ) set(SHADER_HEADERS ${SHADER_HEADERS} ${SPIRV_HEADER_FILE}) + else() + # Skip generating source headers on Vulkan exclusive files + if (NOT ${FILENAME} MATCHES "vulkan.*" AND NOT ${FILENAME} MATCHES "sgsr1.*") + set(SOURCE_HEADER_FILE ${SHADER_DIR}/${SHADER_NAME}.h) + add_custom_command( + OUTPUT + ${SOURCE_HEADER_FILE} + COMMAND + ${CMAKE_COMMAND} -P ${HEADER_GENERATOR} ${SOURCE_FILE} ${SOURCE_HEADER_FILE} ${INPUT_FILE} + MAIN_DEPENDENCY + ${SOURCE_FILE} + DEPENDS + ${INPUT_FILE} + # HEADER_GENERATOR should be included here but msbuild seems to assume it's always modified + ) + set(SHADER_HEADERS ${SHADER_HEADERS} ${SOURCE_HEADER_FILE}) + endif() + # Skip compiling to SPIR-V OpenGL exclusive files + if (NOT ${FILENAME} MATCHES "opengl.*") + string(TOUPPER ${SHADER_NAME}_SPV SPIRV_VARIABLE_NAME) + set(SPIRV_HEADER_FILE ${SHADER_DIR}/${SHADER_NAME}_spv.h) + add_custom_command( + OUTPUT + ${SPIRV_HEADER_FILE} + COMMAND + ${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -I"${FIDELITYFX_INCLUDE_DIR}" ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} --target-env ${SPIR_V_VERSION} + MAIN_DEPENDENCY + ${SOURCE_FILE} + ) + set(SHADER_HEADERS ${SHADER_HEADERS} ${SPIRV_HEADER_FILE}) + endif() endif() endforeach() From 6cc91a9bcc62d9a18f96bace6fb73079a854c669 Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 13 Jan 2026 13:13:57 +0000 Subject: [PATCH 02/37] fix --- src/video_core/host_shaders/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 30daaa9cde..1a54082ffb 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -2,7 +2,6 @@ # SPDX-License-Identifier: GPL-3.0-or-later set(FIDELITYFX_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/externals/FidelityFX-FSR/ffx-fsr) -set(SNAPDRAGON_GSR_INCLUDE_DIR ${snapdragon_gsr_SOURCE_DIR}/sgsr/v1/include/glsl/) set(FIDELITYFX_FILES ${FIDELITYFX_INCLUDE_DIR}/ffx_a.h From a6408a5292495864a775fa4604df27d0e7d6fc96 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 02:01:04 +0000 Subject: [PATCH 03/37] [android] add sgsr to ui --- .../app/src/main/res/values/arrays.xml | 1 + .../app/src/main/res/values/strings.xml | 1 + src/common/settings_enums.h | 2 +- src/qt_common/config/shared_translation.cpp | 1 + src/qt_common/config/shared_translation.h | 1 + src/video_core/host_shaders/sgsr1_shader.vert | 13 ++ .../renderer_opengl/gl_blit_screen.cpp | 1 + .../renderer_vulkan/present/layer.cpp | 2 + .../renderer_vulkan/present/layer.h | 1 + .../renderer_vulkan/present/sgsr.cpp | 150 ++++++++++++++++++ src/video_core/renderer_vulkan/present/sgsr.h | 50 ++++++ .../renderer_vulkan/vk_blit_screen.cpp | 1 + src/yuzu/main_window.cpp | 3 +- 13 files changed, 224 insertions(+), 3 deletions(-) create mode 100644 src/video_core/host_shaders/sgsr1_shader.vert create mode 100644 src/video_core/renderer_vulkan/present/sgsr.cpp create mode 100644 src/video_core/renderer_vulkan/present/sgsr.h diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 99838b98cc..81383e1bfc 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -240,6 +240,7 @@ @string/scaling_filter_bspline @string/scaling_filter_mitchell @string/scaling_filter_spline1 + @string/scaling_filter_sgsr diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index d42fb37d58..3e98222f7e 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -1074,6 +1074,7 @@ B-Spline Mitchell MMPX + Snapdragon Game Super Resolution None diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index 638be4127f..389b16608f 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h @@ -143,7 +143,7 @@ ENUM(ConfirmStop, Ask_Always, Ask_Based_On_Game, Ask_Never); ENUM(FullscreenMode, Borderless, Exclusive); ENUM(NvdecEmulation, Off, Cpu, Gpu); ENUM(ResolutionSetup, Res1_4X, Res1_2X, Res3_4X, Res1X, Res5_4X, Res3_2X, Res2X, Res3X, Res4X, Res5X, Res6X, Res7X, Res8X); -ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Gaussian, Lanczos, ScaleForce, Fsr, Area, ZeroTangent, BSpline, Mitchell, Spline1, Mmpx, MaxEnum); +ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Gaussian, Lanczos, ScaleForce, Fsr, Area, ZeroTangent, BSpline, Mitchell, Spline1, Mmpx, Sgsr, MaxEnum); ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum); ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch); ENUM(ConsoleMode, Handheld, Docked); diff --git a/src/qt_common/config/shared_translation.cpp b/src/qt_common/config/shared_translation.cpp index 5e0c0d8b44..f6b509c77b 100644 --- a/src/qt_common/config/shared_translation.cpp +++ b/src/qt_common/config/shared_translation.cpp @@ -493,6 +493,7 @@ std::unique_ptr ComboboxEnumeration(QObject* parent) { PAIR(ScalingFilter, BSpline, tr("B-Spline")), PAIR(ScalingFilter, Mitchell, tr("Mitchell")), PAIR(ScalingFilter, Spline1, tr("Spline-1")), + PAIR(ScalingFilter, Sgsr, tr("Snapdragon Game Super Resolution")), }}); translations->insert({Settings::EnumMetadata::Index(), { diff --git a/src/qt_common/config/shared_translation.h b/src/qt_common/config/shared_translation.h index 6529c7bf40..edadf5eb9b 100644 --- a/src/qt_common/config/shared_translation.h +++ b/src/qt_common/config/shared_translation.h @@ -53,6 +53,7 @@ static const std::map scaling_filter_texts_map {Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "FSR"))}, {Settings::ScalingFilter::Area, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Area"))}, {Settings::ScalingFilter::Mmpx, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "MMPX"))}, + {Settings::ScalingFilter::Sgsr, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "SGSR"))}, }; static const std::map use_docked_mode_texts_map = { diff --git a/src/video_core/host_shaders/sgsr1_shader.vert b/src/video_core/host_shaders/sgsr1_shader.vert new file mode 100644 index 0000000000..6a87a7cac0 --- /dev/null +++ b/src/video_core/host_shaders/sgsr1_shader.vert @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#version 450 + +layout(location = 0) out vec2 texcoord; + +void main() { + float x = float((gl_VertexIndex & 1) << 2); + float y = float((gl_VertexIndex & 2) << 1); + gl_Position = vec4(x - 1.0, y - 1.0, 0.0, 1.0); + texcoord = vec2(x, y) / 2.0; +} diff --git a/src/video_core/renderer_opengl/gl_blit_screen.cpp b/src/video_core/renderer_opengl/gl_blit_screen.cpp index 4b75e1b949..b03fc3ecbd 100644 --- a/src/video_core/renderer_opengl/gl_blit_screen.cpp +++ b/src/video_core/renderer_opengl/gl_blit_screen.cpp @@ -115,6 +115,7 @@ void BlitScreen::CreateWindowAdapt() { window_adapt = MakeMmpx(device); break; case Settings::ScalingFilter::Fsr: + case Settings::ScalingFilter::Sgsr: case Settings::ScalingFilter::Bilinear: default: window_adapt = MakeBilinear(device); diff --git a/src/video_core/renderer_vulkan/present/layer.cpp b/src/video_core/renderer_vulkan/present/layer.cpp index b462c672cc..8b61e0ef28 100644 --- a/src/video_core/renderer_vulkan/present/layer.cpp +++ b/src/video_core/renderer_vulkan/present/layer.cpp @@ -64,6 +64,8 @@ Layer::Layer(const Device& device_, MemoryAllocator& memory_allocator_, Schedule CreateDescriptorSets(layout); if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr) { fsr.emplace(device, memory_allocator, image_count, output_size); + } else if (filters.get_scaling_filter() == Settings::ScalingFilter::Sgsr) { + sgsr.emplace(device, memory_allocator, image_count, output_size); } } diff --git a/src/video_core/renderer_vulkan/present/layer.h b/src/video_core/renderer_vulkan/present/layer.h index d38b81823e..6de7a66087 100644 --- a/src/video_core/renderer_vulkan/present/layer.h +++ b/src/video_core/renderer_vulkan/present/layer.h @@ -96,6 +96,7 @@ private: Settings::AntiAliasing anti_alias_setting{}; std::variant anti_alias{}; std::optional fsr{}; + std::unique_ptr sgsr{}; std::vector resource_ticks{}; }; diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp new file mode 100644 index 0000000000..8a1e23d5e7 --- /dev/null +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -0,0 +1,150 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "common/common_types.h" +#include "common/div_ceil.h" +#include "common/settings.h" + +#include "video_core/fsr.h" +#include "video_core/host_shaders/sgsr1_shader_mobile_frag_spv.h" +#include "video_core/host_shaders/sgsr1_shader_mobile_edge_direction_frag_spv.h" +#include "video_core/host_shaders/sgsr1_shader_vert_spv.h" +#include "video_core/renderer_vulkan/present/fsr.h" +#include "video_core/renderer_vulkan/present/util.h" +#include "video_core/renderer_vulkan/vk_scheduler.h" +#include "video_core/renderer_vulkan/vk_shader_util.h" +#include "video_core/vulkan_common/vulkan_device.h" + +namespace Vulkan { +using namespace SGSR; + +using PushConstants = std::array; + +SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent) + : m_device{device}, m_memory_allocator{memory_allocator} + , m_image_count{image_count}, m_extent{extent} +{ + m_dynamic_images.resize(m_image_count); + for (auto& images : m_dynamic_images) { + images.images[0] = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); + images.images[1] = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); + images.image_views[0] = CreateWrappedImageView(m_device, images.images[0], VK_FORMAT_R16G16B16A16_SFLOAT); + images.image_views[1] = CreateWrappedImageView(m_device, images.images[1], VK_FORMAT_R16G16B16A16_SFLOAT); + } + + m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); + for (auto& images : m_dynamic_images) { + images.framebuffers[0] = CreateWrappedFramebuffer(m_device, m_renderpass, images.image_views[0], m_extent); + images.framebuffers[1] = CreateWrappedFramebuffer(m_device, m_renderpass, images.image_views[1], m_extent); + } + + m_sampler = CreateBilinearSampler(m_device); + m_vert_shader = BuildShader(m_device, SGSR1_SHADER_VERT_SPV); + m_stage_shader[0] = BuildShader(m_device, SGSR1_SHADER_MOBILE_FRAG_SPV); + m_stage_shader[1] = BuildShader(m_device, SGSR1_SHADER_MOBILE_EDGE_DIRECTION_FRAG_SPV); + // 2 descriptors, 2 descriptor sets per invocation + m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 2 * m_image_count, 2 * m_image_count); + m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); + + std::vector layouts(MaxSgsrStage, *m_descriptor_set_layout); + for (auto& images : m_dynamic_images) + images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layouts); + + const VkPushConstantRange range{ + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + .offset = 0, + .size = sizeof(PushConstants), + }; + VkPipelineLayoutCreateInfo ci{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .setLayoutCount = 1, + .pSetLayouts = m_descriptor_set_layout.address(), + .pushConstantRangeCount = 1, + .pPushConstantRanges = &range, + }; + m_pipeline_layout = m_device.GetLogical().CreatePipelineLayout(ci); + + m_stage_pipeline[0] = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, std::tie(m_vert_shader, m_stage_shader[0])); + m_stage_pipeline[1] = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, std::tie(m_vert_shader, m_stage_shader[1])); +} + +void SGSR::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { + Images& images = m_dynamic_images[image_index]; + std::vector image_infos; + std::vector updates; + image_infos.reserve(2); + updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, images.descriptor_sets[0], 0)); + updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[0], images.descriptor_sets[1], 0)); + m_device.GetLogical().UpdateDescriptorSets(updates, {}); +} + +void SGSR::UploadImages(Scheduler& scheduler) { + if (!m_images_ready) { + scheduler.Record([&](vk::CommandBuffer cmdbuf) { + for (auto& image : m_dynamic_images) { + ClearColorImage(cmdbuf, *image.images[0]); + ClearColorImage(cmdbuf, *image.images[1]); + } + }); + scheduler.Finish(); + m_images_ready = true; + } +} + +VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect) { + Images& images = m_dynamic_images[image_index]; + VkImage stage0_image = *images.images[0]; + VkImage stage1_image = *images.images[1]; + VkDescriptorSet stage0_descriptor_set = images.descriptor_sets[0]; + VkDescriptorSet stage1_descriptor_set = images.descriptor_sets[1]; + VkFramebuffer stage0_framebuffer = *images.framebuffers[0]; + VkFramebuffer stage1_framebuffer = *images.framebuffers[1]; + VkPipelineLayout pipeline_layout = *m_pipeline_layout; + VkRenderPass renderpass = *m_renderpass; + VkExtent2D extent = m_extent; + + const f32 input_image_width = f32(input_image_extent.width); + const f32 input_image_height = f32(input_image_extent.height); + const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_image_width; + const f32 viewport_x = crop_rect.left * input_image_width; + const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_image_height; + const f32 viewport_y = crop_rect.top * input_image_height; + + // highp vec4 + PushConstants viewport_con{}; + *reinterpret_cast(viewport_con.data() + 0) = viewport_x; + *reinterpret_cast(viewport_con.data() + 1) = viewport_y; + *reinterpret_cast(viewport_con.data() + 2) = viewport_width; + *reinterpret_cast(viewport_con.data() + 3) = viewport_height; + + UploadImages(scheduler); + UpdateDescriptorSets(source_image_view, image_index); + + scheduler.RequestOutsideRenderPassOperationContext(); + scheduler.Record([=](vk::CommandBuffer cmdbuf) { + TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL); + TransitionImageLayout(cmdbuf, stage0_image, VK_IMAGE_LAYOUT_GENERAL); + BeginRenderPass(cmdbuf, renderpass, stage0_framebuffer, extent); + cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, m_stage_pipeline[0]); + cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, stage0_descriptor_set, {}); + cmdbuf.PushConstants(pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, viewport_con); + cmdbuf.Draw(3, 1, 0, 0); + cmdbuf.EndRenderPass(); + // + TransitionImageLayout(cmdbuf, stage0_image, VK_IMAGE_LAYOUT_GENERAL); + TransitionImageLayout(cmdbuf, stage1_image, VK_IMAGE_LAYOUT_GENERAL); + BeginRenderPass(cmdbuf, renderpass, stage1_framebuffer, extent); + cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, m_stage_pipeline[1]); + cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, stage1_descriptor_set, {}); + cmdbuf.PushConstants(pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, viewport_con); + cmdbuf.Draw(3, 1, 0, 0); + cmdbuf.EndRenderPass(); + TransitionImageLayout(cmdbuf, stage1_image, VK_IMAGE_LAYOUT_GENERAL); + }); + + return *images.image_views[1]; +} + +} // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/present/sgsr.h b/src/video_core/renderer_vulkan/present/sgsr.h new file mode 100644 index 0000000000..97691c9a90 --- /dev/null +++ b/src/video_core/renderer_vulkan/present/sgsr.h @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/math_util.h" +#include "video_core/vulkan_common/vulkan_memory_allocator.h" +#include "video_core/vulkan_common/vulkan_wrapper.h" + +namespace Vulkan { + +class Device; +class Scheduler; + +class SGSR { +public: + explicit SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent); + VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, + VkImageView source_image_view, VkExtent2D input_image_extent, + const Common::Rectangle& crop_rect); + +private: + void UploadImages(Scheduler& scheduler); + void UpdateDescriptorSets(VkImageView image_view, size_t image_index); + + const Device& m_device; + MemoryAllocator& m_memory_allocator; + const size_t m_image_count; + const VkExtent2D m_extent; + + vk::DescriptorPool m_descriptor_pool; + vk::DescriptorSetLayout m_descriptor_set_layout; + vk::PipelineLayout m_pipeline_layout; + vk::ShaderModule m_vert_shader; + vk::ShaderModule m_stage_shader[2]; + vk::Pipeline m_stage_pipeline[2]; + vk::RenderPass m_renderpass; + vk::Sampler m_sampler; + + struct Images { + vk::DescriptorSets descriptor_sets; + std::array images; + std::array image_views; + std::array framebuffers; + }; + std::vector m_dynamic_images; + bool m_images_ready{}; +}; + +} // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index bb7eb9bdaa..f7c6bc0cd1 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp @@ -73,6 +73,7 @@ void BlitScreen::SetWindowAdaptPass() { window_adapt = MakeMmpx(device, swapchain_view_format); break; case Settings::ScalingFilter::Fsr: + case Settings::ScalingFilter::Sgsr: case Settings::ScalingFilter::Bilinear: default: window_adapt = MakeBilinear(device, swapchain_view_format); diff --git a/src/yuzu/main_window.cpp b/src/yuzu/main_window.cpp index 2e7cef0953..d22be2ec67 100644 --- a/src/yuzu/main_window.cpp +++ b/src/yuzu/main_window.cpp @@ -4394,8 +4394,7 @@ void MainWindow::UpdateAPIText() { void MainWindow::UpdateFilterText() { const auto filter = Settings::values.scaling_filter.GetValue(); const auto filter_text = ConfigurationShared::scaling_filter_texts_map.find(filter)->second; - filter_status_button->setText(filter == Settings::ScalingFilter::Fsr ? tr("FSR") - : filter_text.toUpper()); + filter_status_button->setText(filter_text.toUpper()); } void MainWindow::UpdateAAText() { From a5c6692e349c16505e595313853c31ab423164b5 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 02:33:31 +0000 Subject: [PATCH 04/37] extra stuffs --- src/video_core/CMakeLists.txt | 2 ++ src/video_core/host_shaders/CMakeLists.txt | 7 +++++-- src/video_core/renderer_vulkan/present/layer.cpp | 1 + src/video_core/renderer_vulkan/present/sgsr.cpp | 13 ++++++------- src/video_core/renderer_vulkan/present/sgsr.h | 11 ++++++----- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 362b068656..07683dcbeb 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -131,6 +131,8 @@ add_library(video_core STATIC renderer_vulkan/present/present_push_constants.h renderer_vulkan/present/smaa.cpp renderer_vulkan/present/smaa.h + renderer_vulkan/present/sgsr.cpp + renderer_vulkan/present/sgsr.h renderer_vulkan/present/util.cpp renderer_vulkan/present/util.h renderer_vulkan/present/window_adapt_pass.cpp diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 1a54082ffb..dc05853326 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -76,8 +76,11 @@ set(SHADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_quad_indexed.comp ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_turbo_mode.comp ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_uint8.comp - ${SNAPDRAGON_GSR_INCLUDE_DIR}/sgsr1_shader_mobile.frag - ${SNAPDRAGON_GSR_INCLUDE_DIR}/sgsr1_shader_mobile_edge_direction.frag + + # Snapdragon Game Super Resolution + ${CMAKE_CURRENT_SOURCE_DIR}/sgsr1_shader.vert + ${snapdragon_gsr_SOURCE_DIR}/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag + ${snapdragon_gsr_SOURCE_DIR}/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag ) if (PLATFORM_HAIKU) diff --git a/src/video_core/renderer_vulkan/present/layer.cpp b/src/video_core/renderer_vulkan/present/layer.cpp index 8b61e0ef28..e15fa7553a 100644 --- a/src/video_core/renderer_vulkan/present/layer.cpp +++ b/src/video_core/renderer_vulkan/present/layer.cpp @@ -15,6 +15,7 @@ #include "common/settings.h" #include "video_core/framebuffer_config.h" #include "video_core/renderer_vulkan/present/fsr.h" +#include "video_core/renderer_vulkan/present/sgsr.h" #include "video_core/renderer_vulkan/present/fxaa.h" #include "video_core/renderer_vulkan/present/layer.h" #include "video_core/renderer_vulkan/present/present_push_constants.h" diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 8a1e23d5e7..f873acfb48 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -5,18 +5,17 @@ #include "common/div_ceil.h" #include "common/settings.h" -#include "video_core/fsr.h" +//#include "video_core/sgsr.h" #include "video_core/host_shaders/sgsr1_shader_mobile_frag_spv.h" #include "video_core/host_shaders/sgsr1_shader_mobile_edge_direction_frag_spv.h" #include "video_core/host_shaders/sgsr1_shader_vert_spv.h" -#include "video_core/renderer_vulkan/present/fsr.h" +#include "video_core/renderer_vulkan/present/sgsr.h" #include "video_core/renderer_vulkan/present/util.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_shader_util.h" #include "video_core/vulkan_common/vulkan_device.h" namespace Vulkan { -using namespace SGSR; using PushConstants = std::array; @@ -46,7 +45,7 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 2 * m_image_count, 2 * m_image_count); m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); - std::vector layouts(MaxSgsrStage, *m_descriptor_set_layout); + std::vector layouts(SGSR_STAGE_COUNT, *m_descriptor_set_layout); for (auto& images : m_dynamic_images) images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layouts); @@ -123,11 +122,11 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ UpdateDescriptorSets(source_image_view, image_index); scheduler.RequestOutsideRenderPassOperationContext(); - scheduler.Record([=](vk::CommandBuffer cmdbuf) { + scheduler.Record([=, this](vk::CommandBuffer cmdbuf) { TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL); TransitionImageLayout(cmdbuf, stage0_image, VK_IMAGE_LAYOUT_GENERAL); BeginRenderPass(cmdbuf, renderpass, stage0_framebuffer, extent); - cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, m_stage_pipeline[0]); + cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stage_pipeline[0]); cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, stage0_descriptor_set, {}); cmdbuf.PushConstants(pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, viewport_con); cmdbuf.Draw(3, 1, 0, 0); @@ -136,7 +135,7 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ TransitionImageLayout(cmdbuf, stage0_image, VK_IMAGE_LAYOUT_GENERAL); TransitionImageLayout(cmdbuf, stage1_image, VK_IMAGE_LAYOUT_GENERAL); BeginRenderPass(cmdbuf, renderpass, stage1_framebuffer, extent); - cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, m_stage_pipeline[1]); + cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stage_pipeline[1]); cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, stage1_descriptor_set, {}); cmdbuf.PushConstants(pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, viewport_con); cmdbuf.Draw(3, 1, 0, 0); diff --git a/src/video_core/renderer_vulkan/present/sgsr.h b/src/video_core/renderer_vulkan/present/sgsr.h index 97691c9a90..14650a4143 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.h +++ b/src/video_core/renderer_vulkan/present/sgsr.h @@ -14,6 +14,7 @@ class Scheduler; class SGSR { public: + static constexpr size_t SGSR_STAGE_COUNT = 2; explicit SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent); VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, @@ -32,16 +33,16 @@ private: vk::DescriptorSetLayout m_descriptor_set_layout; vk::PipelineLayout m_pipeline_layout; vk::ShaderModule m_vert_shader; - vk::ShaderModule m_stage_shader[2]; - vk::Pipeline m_stage_pipeline[2]; + std::array m_stage_shader; + std::array m_stage_pipeline; vk::RenderPass m_renderpass; vk::Sampler m_sampler; struct Images { vk::DescriptorSets descriptor_sets; - std::array images; - std::array image_views; - std::array framebuffers; + std::array images; + std::array image_views; + std::array framebuffers; }; std::vector m_dynamic_images; bool m_images_ready{}; From 6e5b800d0942ac32d07adc52a30b1cc9e7b2a942 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 03:11:16 +0000 Subject: [PATCH 05/37] fix for push constants --- .../0002-push-constants-retrofit.patch | 97 +++++++++++++++++++ .../renderer_vulkan/present/layer.cpp | 3 + .../renderer_vulkan/present/sgsr.cpp | 26 ++--- 3 files changed, 114 insertions(+), 12 deletions(-) create mode 100644 .patch/snapdragon_gsr/0002-push-constants-retrofit.patch diff --git a/.patch/snapdragon_gsr/0002-push-constants-retrofit.patch b/.patch/snapdragon_gsr/0002-push-constants-retrofit.patch new file mode 100644 index 0000000000..33f13b0c65 --- /dev/null +++ b/.patch/snapdragon_gsr/0002-push-constants-retrofit.patch @@ -0,0 +1,97 @@ +diff --git a/d926/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/d926/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +index 69927af..c942bbc 100644 +--- a/d926/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag ++++ b/d926/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +@@ -34,11 +34,10 @@ precision highp int; + //////////////////////// + + #if defined(UseUniformBlock) +-layout (set=0, binding = 0) uniform UniformBlock +-{ +- highp vec4 ViewportInfo[1]; ++layout( push_constant ) uniform constants { ++ highp vec4 ViewportInfo; + }; +-layout(set = 0, binding = 1) uniform mediump sampler2D ps0; ++layout(set = 0, binding = 0) uniform mediump sampler2D ps0; + #else + uniform highp vec4 ViewportInfo[1]; + uniform mediump sampler2D ps0; +@@ -82,21 +81,21 @@ void main() + //if ( mode!=4 && xCenter*xCenter+yCenter*yCenter<=0.4 * 0.4) + if ( mode!=4) + { +- highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo[0].zw)+vec2(-0.5,0.5)); ++ highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo.zw)+vec2(-0.5,0.5)); + highp vec2 imgCoordPixel = floor(imgCoord); +- highp vec2 coord = (imgCoordPixel*ViewportInfo[0].xy); ++ highp vec2 coord = (imgCoordPixel*ViewportInfo.xy); + vec2 pl = (imgCoord+(-imgCoordPixel)); + vec4 left = textureGather(ps0,coord, mode); + + float edgeVote = abs(left.z - left.y) + abs(color[mode] - left.y) + abs(color[mode] - left.z) ; + if(edgeVote > edgeThreshold) + { +- coord.x += ViewportInfo[0].x; ++ coord.x += ViewportInfo.x; + +- vec4 right = textureGather(ps0,coord + vec2(ViewportInfo[0].x, 0.0), mode); ++ vec4 right = textureGather(ps0,coord + vec2(ViewportInfo.x, 0.0), mode); + vec4 upDown; +- upDown.xy = textureGather(ps0,coord + vec2(0.0, -ViewportInfo[0].y),mode).wz; +- upDown.zw = textureGather(ps0,coord+ vec2(0.0, ViewportInfo[0].y), mode).yx; ++ upDown.xy = textureGather(ps0,coord + vec2(0.0, -ViewportInfo.y),mode).wz; ++ upDown.zw = textureGather(ps0,coord+ vec2(0.0, ViewportInfo.y), mode).yx; + + float mean = (left.y+left.z+right.x+right.w)*0.25; + left = left - vec4(mean); +diff --git a/d926/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/d926/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +index 1f1daa6..128a348 100644 +--- a/d926/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag ++++ b/d926/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +@@ -40,13 +40,12 @@ precision highp int; + //////////////////////// + + #if defined(UseUniformBlock) +-layout (set=0, binding = 0) uniform UniformBlock +-{ +- highp vec4 ViewportInfo[1]; ++layout( push_constant ) uniform constants { ++ highp vec4 ViewportInfo; + }; +-layout(set = 0, binding = 1) uniform mediump sampler2D ps0; ++layout(set = 0, binding = 0) uniform mediump sampler2D ps0; + #else +-uniform highp vec4 ViewportInfo[1]; ++uniform highp vec4 ViewportInfo; + uniform mediump sampler2D ps0; + #endif + +@@ -113,21 +112,21 @@ void main() + //if ( OperationMode!=4 && xCenter*xCenter+yCenter*yCenter<=0.4 * 0.4) + if ( OperationMode!=4) + { +- highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo[0].zw)+vec2(-0.5,0.5)); ++ highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo.zw)+vec2(-0.5,0.5)); + highp vec2 imgCoordPixel = floor(imgCoord); +- highp vec2 coord = (imgCoordPixel*ViewportInfo[0].xy); ++ highp vec2 coord = (imgCoordPixel*ViewportInfo.xy); + vec2 pl = (imgCoord+(-imgCoordPixel)); + vec4 left = textureGather(ps0,coord, OperationMode); + + float edgeVote = abs(left.z - left.y) + abs(color[OperationMode] - left.y) + abs(color[OperationMode] - left.z) ; + if(edgeVote > EdgeThreshold) + { +- coord.x += ViewportInfo[0].x; ++ coord.x += ViewportInfo.x; + +- vec4 right = textureGather(ps0,coord + vec2(ViewportInfo[0].x, 0.0), OperationMode); ++ vec4 right = textureGather(ps0,coord + vec2(ViewportInfo.x, 0.0), OperationMode); + vec4 upDown; +- upDown.xy = textureGather(ps0,coord + vec2(0.0, -ViewportInfo[0].y),OperationMode).wz; +- upDown.zw = textureGather(ps0,coord+ vec2(0.0, ViewportInfo[0].y), OperationMode).yx; ++ upDown.xy = textureGather(ps0,coord + vec2(0.0, -ViewportInfo.y),OperationMode).wz; ++ upDown.zw = textureGather(ps0,coord+ vec2(0.0, ViewportInfo.y), OperationMode).yx; + + float mean = (left.y+left.z+right.x+right.w)*0.25; + left = left - vec4(mean); diff --git a/src/video_core/renderer_vulkan/present/layer.cpp b/src/video_core/renderer_vulkan/present/layer.cpp index e15fa7553a..d6c0ca082f 100644 --- a/src/video_core/renderer_vulkan/present/layer.cpp +++ b/src/video_core/renderer_vulkan/present/layer.cpp @@ -120,6 +120,9 @@ void Layer::ConfigureDraw(PresentPushConstants* out_push_constants, if (fsr) { source_image_view = fsr->Draw(scheduler, image_index, source_image, source_image_view, render_extent, crop_rect); crop_rect = {0, 0, 1, 1}; + } else if (sgsr) { + source_image_view = sgsr->Draw(scheduler, image_index, source_image, source_image_view, render_extent, crop_rect); + crop_rect = {0, 0, 1, 1}; } SetMatrixData(*out_push_constants, layout); diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index f873acfb48..6fe3415aa4 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -94,22 +94,25 @@ void SGSR::UploadImages(Scheduler& scheduler) { VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect) { Images& images = m_dynamic_images[image_index]; - VkImage stage0_image = *images.images[0]; - VkImage stage1_image = *images.images[1]; - VkDescriptorSet stage0_descriptor_set = images.descriptor_sets[0]; - VkDescriptorSet stage1_descriptor_set = images.descriptor_sets[1]; - VkFramebuffer stage0_framebuffer = *images.framebuffers[0]; - VkFramebuffer stage1_framebuffer = *images.framebuffers[1]; + auto const stage0_image = *images.images[0]; + auto const stage1_image = *images.images[1]; + auto const stage0_descriptor_set = images.descriptor_sets[0]; + auto const stage1_descriptor_set = images.descriptor_sets[1]; + auto const stage0_framebuffer = *images.framebuffers[0]; + auto const stage1_framebuffer = *images.framebuffers[1]; + auto const stage0_pipeline = *m_stage_pipeline[0]; + auto const stage1_pipeline = *m_stage_pipeline[1]; + VkPipelineLayout pipeline_layout = *m_pipeline_layout; VkRenderPass renderpass = *m_renderpass; VkExtent2D extent = m_extent; const f32 input_image_width = f32(input_image_extent.width); const f32 input_image_height = f32(input_image_extent.height); - const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_image_width; const f32 viewport_x = crop_rect.left * input_image_width; - const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_image_height; const f32 viewport_y = crop_rect.top * input_image_height; + const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_image_width; + const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_image_height; // highp vec4 PushConstants viewport_con{}; @@ -122,20 +125,19 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ UpdateDescriptorSets(source_image_view, image_index); scheduler.RequestOutsideRenderPassOperationContext(); - scheduler.Record([=, this](vk::CommandBuffer cmdbuf) { + scheduler.Record([=](vk::CommandBuffer cmdbuf) { TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL); TransitionImageLayout(cmdbuf, stage0_image, VK_IMAGE_LAYOUT_GENERAL); BeginRenderPass(cmdbuf, renderpass, stage0_framebuffer, extent); - cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stage_pipeline[0]); + cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, stage0_pipeline); cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, stage0_descriptor_set, {}); cmdbuf.PushConstants(pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, viewport_con); cmdbuf.Draw(3, 1, 0, 0); cmdbuf.EndRenderPass(); - // TransitionImageLayout(cmdbuf, stage0_image, VK_IMAGE_LAYOUT_GENERAL); TransitionImageLayout(cmdbuf, stage1_image, VK_IMAGE_LAYOUT_GENERAL); BeginRenderPass(cmdbuf, renderpass, stage1_framebuffer, extent); - cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stage_pipeline[1]); + cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, stage1_pipeline); cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, stage1_descriptor_set, {}); cmdbuf.PushConstants(pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, viewport_con); cmdbuf.Draw(3, 1, 0, 0); From 5117039552686efed137bbce90e1fa736e981d49 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 03:51:23 +0000 Subject: [PATCH 06/37] fuck this --- .../0002-push-constants-retrofit.patch | 12 ++++---- docs/user/Graphics.md | 3 ++ .../renderer_vulkan/present/sgsr.cpp | 28 +++++++++---------- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/.patch/snapdragon_gsr/0002-push-constants-retrofit.patch b/.patch/snapdragon_gsr/0002-push-constants-retrofit.patch index 33f13b0c65..7faf70bcc1 100644 --- a/.patch/snapdragon_gsr/0002-push-constants-retrofit.patch +++ b/.patch/snapdragon_gsr/0002-push-constants-retrofit.patch @@ -1,7 +1,7 @@ -diff --git a/d926/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/d926/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag index 69927af..c942bbc 100644 ---- a/d926/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -+++ b/d926/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +--- a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag ++++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag @@ -34,11 +34,10 @@ precision highp int; //////////////////////// @@ -45,10 +45,10 @@ index 69927af..c942bbc 100644 float mean = (left.y+left.z+right.x+right.w)*0.25; left = left - vec4(mean); -diff --git a/d926/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/d926/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag index 1f1daa6..128a348 100644 ---- a/d926/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -+++ b/d926/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +--- a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag ++++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag @@ -40,13 +40,12 @@ precision highp int; //////////////////////// diff --git a/docs/user/Graphics.md b/docs/user/Graphics.md index ad359b9049..49ee0e68b2 100644 --- a/docs/user/Graphics.md +++ b/docs/user/Graphics.md @@ -44,6 +44,9 @@ Various graphical filters exist - each of them aimed at a specific target/image - **MMPX**: Nearest-neighbour filter aimed at providing higher pixel-art quality. - **Pros**: Offers decent pixel-art upscaling. - **Cons**: Only works for pixel-art. +- **SGSR**: Uses Snapdragon Studios Game Super Resolution to enhance image quality (similar to FSR, but for Adreno devices). + - **Pros**: Optimized for Adreno devices. + - **Cons**: Doesn't play nicely with non-Adreno devices. ### Anisotropy values diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 6fe3415aa4..1f334cbc92 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -116,10 +116,10 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ // highp vec4 PushConstants viewport_con{}; - *reinterpret_cast(viewport_con.data() + 0) = viewport_x; - *reinterpret_cast(viewport_con.data() + 1) = viewport_y; - *reinterpret_cast(viewport_con.data() + 2) = viewport_width; - *reinterpret_cast(viewport_con.data() + 3) = viewport_height; + viewport_con[0] = std::bit_cast(viewport_x); + viewport_con[1] = std::bit_cast(viewport_y); + viewport_con[2] = std::bit_cast(viewport_width); + viewport_con[3] = std::bit_cast(viewport_height); UploadImages(scheduler); UpdateDescriptorSets(source_image_view, image_index); @@ -135,17 +135,17 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ cmdbuf.Draw(3, 1, 0, 0); cmdbuf.EndRenderPass(); TransitionImageLayout(cmdbuf, stage0_image, VK_IMAGE_LAYOUT_GENERAL); - TransitionImageLayout(cmdbuf, stage1_image, VK_IMAGE_LAYOUT_GENERAL); - BeginRenderPass(cmdbuf, renderpass, stage1_framebuffer, extent); - cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, stage1_pipeline); - cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, stage1_descriptor_set, {}); - cmdbuf.PushConstants(pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, viewport_con); - cmdbuf.Draw(3, 1, 0, 0); - cmdbuf.EndRenderPass(); - TransitionImageLayout(cmdbuf, stage1_image, VK_IMAGE_LAYOUT_GENERAL); + // TransitionImageLayout(cmdbuf, stage1_image, VK_IMAGE_LAYOUT_GENERAL); + // BeginRenderPass(cmdbuf, renderpass, stage1_framebuffer, extent); + // cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, stage1_pipeline); + // cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, stage1_descriptor_set, {}); + // cmdbuf.PushConstants(pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, viewport_con); + // cmdbuf.Draw(3, 1, 0, 0); + // cmdbuf.EndRenderPass(); + // TransitionImageLayout(cmdbuf, stage1_image, VK_IMAGE_LAYOUT_GENERAL); }); - - return *images.image_views[1]; + //return *images.image_views[1]; + return *images.image_views[0]; } } // namespace Vulkan From af44f1113990a752b2e715efeb4c7a49772378c8 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 03:55:41 +0000 Subject: [PATCH 07/37] fix deps --- src/video_core/host_shaders/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index dc05853326..8533984db6 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -214,6 +214,7 @@ list(APPEND SHADER_SOURCES ${GLSL_INCLUDES}) add_custom_target(host_shaders DEPENDS ${SHADER_HEADERS} + snapdragon_gsr SOURCES ${SHADER_SOURCES} ) From ec5bc4ed67dee2336f947b5a23ffa8cd75f5ce31 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 04:10:47 +0000 Subject: [PATCH 08/37] fix everything --- .patch/snapdragon_gsr/0001-fix-glsl.patch | 99 +++++++++++++++++++ .patch/snapdragon_gsr/0001-glslang-fix.patch | 61 ------------ .../0002-push-constants-retrofit.patch | 97 ------------------ src/video_core/host_shaders/CMakeLists.txt | 3 +- 4 files changed, 100 insertions(+), 160 deletions(-) create mode 100644 .patch/snapdragon_gsr/0001-fix-glsl.patch delete mode 100644 .patch/snapdragon_gsr/0001-glslang-fix.patch delete mode 100644 .patch/snapdragon_gsr/0002-push-constants-retrofit.patch diff --git a/.patch/snapdragon_gsr/0001-fix-glsl.patch b/.patch/snapdragon_gsr/0001-fix-glsl.patch new file mode 100644 index 0000000000..794eed8a21 --- /dev/null +++ b/.patch/snapdragon_gsr/0001-fix-glsl.patch @@ -0,0 +1,99 @@ +diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +index 7074999..2d322fb 100644 +--- a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag ++++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +@@ -1,4 +1,5 @@ +-#version 300 es ++#version 310 es ++#extension GL_EXT_spec_constant_composites:require + + //============================================================================================================ + // +@@ -34,11 +35,10 @@ precision highp int; + //////////////////////// + + #if defined(UseUniformBlock) +-layout (set=0, binding = 0) uniform UniformBlock +-{ +- highp vec4 ViewportInfo[1]; ++layout( push_constant ) uniform constants { ++ highp vec4 ViewportInfo[1]; + }; +-layout(set = 0, binding = 1) uniform mediump sampler2D ps0; ++layout(set = 0, binding = 0) uniform mediump sampler2D ps0; + #else + uniform highp vec4 ViewportInfo[1]; + uniform mediump sampler2D ps0; +@@ -63,9 +63,9 @@ vec2 weightY(float dx, float dy,float c, float std) + + void main() + { +- int mode = OperationMode; +- float edgeThreshold = EdgeThreshold; +- float edgeSharpness = EdgeSharpness; ++ const int mode = OperationMode; ++ const float edgeThreshold = EdgeThreshold; ++ const float edgeSharpness = EdgeSharpness; + + vec4 color; + if(mode == 1) +@@ -93,10 +93,13 @@ void main() + { + coord.x += ViewportInfo[0].x; + +- vec4 right = textureGather(ps0,coord + highp vec2(ViewportInfo[0].x, 0.0), mode); ++ highp vec2 IR_highp_vec2_0 = vec2(ViewportInfo[0].x, 0.0); ++ vec4 right = textureGather(ps0,coord + IR_highp_vec2_0, mode); + vec4 upDown; +- upDown.xy = textureGather(ps0,coord + highp vec2(0.0, -ViewportInfo[0].y),mode).wz; +- upDown.zw = textureGather(ps0,coord+ highp vec2(0.0, ViewportInfo[0].y), mode).yx; ++ highp vec2 IR_highp_vec2_1 = vec2(0.0, -ViewportInfo[0].y); ++ upDown.xy = textureGather(ps0,coord + IR_highp_vec2_1,mode).wz; ++ highp vec2 IR_highp_vec2_2 = vec2(0.0, ViewportInfo[0].y); ++ upDown.zw = textureGather(ps0,coord+ IR_highp_vec2_2, mode).yx; + + float mean = (left.y+left.z+right.x+right.w)*0.25; + left = left - vec4(mean); +diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +index d2df646..875cdbf 100644 +--- a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag ++++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +@@ -1,4 +1,5 @@ +-#version 300 es ++#version 310 es ++#extension GL_EXT_spec_constant_composites:require + + //============================================================================================================ + // +@@ -40,11 +41,10 @@ precision highp int; + //////////////////////// + + #if defined(UseUniformBlock) +-layout (set=0, binding = 0) uniform UniformBlock +-{ +- highp vec4 ViewportInfo[1]; ++layout( push_constant ) uniform constants { ++ highp vec4 ViewportInfo[1]; + }; +-layout(set = 0, binding = 1) uniform mediump sampler2D ps0; ++layout(set = 0, binding = 0) uniform mediump sampler2D ps0; + #else + uniform highp vec4 ViewportInfo[1]; + uniform mediump sampler2D ps0; +@@ -124,10 +124,13 @@ void main() + { + coord.x += ViewportInfo[0].x; + +- vec4 right = textureGather(ps0,coord + highp vec2(ViewportInfo[0].x, 0.0), OperationMode); ++ highp vec2 IR_highp_vec2_0 = vec2(ViewportInfo[0].x, 0.0); ++ vec4 right = textureGather(ps0,coord + IR_highp_vec2_0, OperationMode); + vec4 upDown; +- upDown.xy = textureGather(ps0,coord + highp vec2(0.0, -ViewportInfo[0].y),OperationMode).wz; +- upDown.zw = textureGather(ps0,coord+ highp vec2(0.0, ViewportInfo[0].y), OperationMode).yx; ++ highp vec2 IR_highp_vec2_1 = vec2(0.0, -ViewportInfo[0].y); ++ upDown.xy = textureGather(ps0,coord + IR_highp_vec2_1,OperationMode).wz; ++ highp vec2 IR_highp_vec2_2 = vec2(0.0, ViewportInfo[0].y); ++ upDown.zw = textureGather(ps0,coord+ IR_highp_vec2_2, OperationMode).yx; + + float mean = (left.y+left.z+right.x+right.w)*0.25; + left = left - vec4(mean); diff --git a/.patch/snapdragon_gsr/0001-glslang-fix.patch b/.patch/snapdragon_gsr/0001-glslang-fix.patch deleted file mode 100644 index 2eb0099d64..0000000000 --- a/.patch/snapdragon_gsr/0001-glslang-fix.patch +++ /dev/null @@ -1,61 +0,0 @@ -diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -index 7074999..69927af 100644 ---- a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -+++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -@@ -1,4 +1,4 @@ --#version 300 es -+#version 320 es - - //============================================================================================================ - // -@@ -63,9 +63,9 @@ vec2 weightY(float dx, float dy,float c, float std) - - void main() - { -- int mode = OperationMode; -- float edgeThreshold = EdgeThreshold; -- float edgeSharpness = EdgeSharpness; -+ const int mode = OperationMode; -+ const float edgeThreshold = EdgeThreshold; -+ const float edgeSharpness = EdgeSharpness; - - vec4 color; - if(mode == 1) -@@ -93,10 +93,10 @@ void main() - { - coord.x += ViewportInfo[0].x; - -- vec4 right = textureGather(ps0,coord + highp vec2(ViewportInfo[0].x, 0.0), mode); -+ vec4 right = textureGather(ps0,coord + vec2(ViewportInfo[0].x, 0.0), mode); - vec4 upDown; -- upDown.xy = textureGather(ps0,coord + highp vec2(0.0, -ViewportInfo[0].y),mode).wz; -- upDown.zw = textureGather(ps0,coord+ highp vec2(0.0, ViewportInfo[0].y), mode).yx; -+ upDown.xy = textureGather(ps0,coord + vec2(0.0, -ViewportInfo[0].y),mode).wz; -+ upDown.zw = textureGather(ps0,coord+ vec2(0.0, ViewportInfo[0].y), mode).yx; - - float mean = (left.y+left.z+right.x+right.w)*0.25; - left = left - vec4(mean); -diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -index d2df646..1f1daa6 100644 ---- a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -+++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -@@ -1,4 +1,4 @@ --#version 300 es -+#version 320 es - - //============================================================================================================ - // -@@ -124,10 +124,10 @@ void main() - { - coord.x += ViewportInfo[0].x; - -- vec4 right = textureGather(ps0,coord + highp vec2(ViewportInfo[0].x, 0.0), OperationMode); -+ vec4 right = textureGather(ps0,coord + vec2(ViewportInfo[0].x, 0.0), OperationMode); - vec4 upDown; -- upDown.xy = textureGather(ps0,coord + highp vec2(0.0, -ViewportInfo[0].y),OperationMode).wz; -- upDown.zw = textureGather(ps0,coord+ highp vec2(0.0, ViewportInfo[0].y), OperationMode).yx; -+ upDown.xy = textureGather(ps0,coord + vec2(0.0, -ViewportInfo[0].y),OperationMode).wz; -+ upDown.zw = textureGather(ps0,coord+ vec2(0.0, ViewportInfo[0].y), OperationMode).yx; - - float mean = (left.y+left.z+right.x+right.w)*0.25; - left = left - vec4(mean); diff --git a/.patch/snapdragon_gsr/0002-push-constants-retrofit.patch b/.patch/snapdragon_gsr/0002-push-constants-retrofit.patch deleted file mode 100644 index 7faf70bcc1..0000000000 --- a/.patch/snapdragon_gsr/0002-push-constants-retrofit.patch +++ /dev/null @@ -1,97 +0,0 @@ -diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -index 69927af..c942bbc 100644 ---- a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -+++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -@@ -34,11 +34,10 @@ precision highp int; - //////////////////////// - - #if defined(UseUniformBlock) --layout (set=0, binding = 0) uniform UniformBlock --{ -- highp vec4 ViewportInfo[1]; -+layout( push_constant ) uniform constants { -+ highp vec4 ViewportInfo; - }; --layout(set = 0, binding = 1) uniform mediump sampler2D ps0; -+layout(set = 0, binding = 0) uniform mediump sampler2D ps0; - #else - uniform highp vec4 ViewportInfo[1]; - uniform mediump sampler2D ps0; -@@ -82,21 +81,21 @@ void main() - //if ( mode!=4 && xCenter*xCenter+yCenter*yCenter<=0.4 * 0.4) - if ( mode!=4) - { -- highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo[0].zw)+vec2(-0.5,0.5)); -+ highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo.zw)+vec2(-0.5,0.5)); - highp vec2 imgCoordPixel = floor(imgCoord); -- highp vec2 coord = (imgCoordPixel*ViewportInfo[0].xy); -+ highp vec2 coord = (imgCoordPixel*ViewportInfo.xy); - vec2 pl = (imgCoord+(-imgCoordPixel)); - vec4 left = textureGather(ps0,coord, mode); - - float edgeVote = abs(left.z - left.y) + abs(color[mode] - left.y) + abs(color[mode] - left.z) ; - if(edgeVote > edgeThreshold) - { -- coord.x += ViewportInfo[0].x; -+ coord.x += ViewportInfo.x; - -- vec4 right = textureGather(ps0,coord + vec2(ViewportInfo[0].x, 0.0), mode); -+ vec4 right = textureGather(ps0,coord + vec2(ViewportInfo.x, 0.0), mode); - vec4 upDown; -- upDown.xy = textureGather(ps0,coord + vec2(0.0, -ViewportInfo[0].y),mode).wz; -- upDown.zw = textureGather(ps0,coord+ vec2(0.0, ViewportInfo[0].y), mode).yx; -+ upDown.xy = textureGather(ps0,coord + vec2(0.0, -ViewportInfo.y),mode).wz; -+ upDown.zw = textureGather(ps0,coord+ vec2(0.0, ViewportInfo.y), mode).yx; - - float mean = (left.y+left.z+right.x+right.w)*0.25; - left = left - vec4(mean); -diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -index 1f1daa6..128a348 100644 ---- a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -+++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -@@ -40,13 +40,12 @@ precision highp int; - //////////////////////// - - #if defined(UseUniformBlock) --layout (set=0, binding = 0) uniform UniformBlock --{ -- highp vec4 ViewportInfo[1]; -+layout( push_constant ) uniform constants { -+ highp vec4 ViewportInfo; - }; --layout(set = 0, binding = 1) uniform mediump sampler2D ps0; -+layout(set = 0, binding = 0) uniform mediump sampler2D ps0; - #else --uniform highp vec4 ViewportInfo[1]; -+uniform highp vec4 ViewportInfo; - uniform mediump sampler2D ps0; - #endif - -@@ -113,21 +112,21 @@ void main() - //if ( OperationMode!=4 && xCenter*xCenter+yCenter*yCenter<=0.4 * 0.4) - if ( OperationMode!=4) - { -- highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo[0].zw)+vec2(-0.5,0.5)); -+ highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo.zw)+vec2(-0.5,0.5)); - highp vec2 imgCoordPixel = floor(imgCoord); -- highp vec2 coord = (imgCoordPixel*ViewportInfo[0].xy); -+ highp vec2 coord = (imgCoordPixel*ViewportInfo.xy); - vec2 pl = (imgCoord+(-imgCoordPixel)); - vec4 left = textureGather(ps0,coord, OperationMode); - - float edgeVote = abs(left.z - left.y) + abs(color[OperationMode] - left.y) + abs(color[OperationMode] - left.z) ; - if(edgeVote > EdgeThreshold) - { -- coord.x += ViewportInfo[0].x; -+ coord.x += ViewportInfo.x; - -- vec4 right = textureGather(ps0,coord + vec2(ViewportInfo[0].x, 0.0), OperationMode); -+ vec4 right = textureGather(ps0,coord + vec2(ViewportInfo.x, 0.0), OperationMode); - vec4 upDown; -- upDown.xy = textureGather(ps0,coord + vec2(0.0, -ViewportInfo[0].y),OperationMode).wz; -- upDown.zw = textureGather(ps0,coord+ vec2(0.0, ViewportInfo[0].y), OperationMode).yx; -+ upDown.xy = textureGather(ps0,coord + vec2(0.0, -ViewportInfo.y),OperationMode).wz; -+ upDown.zw = textureGather(ps0,coord+ vec2(0.0, ViewportInfo.y), OperationMode).yx; - - float mean = (left.y+left.z+right.x+right.w)*0.25; - left = left - vec4(mean); diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 8533984db6..7b0d8e03e9 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -150,7 +150,7 @@ foreach(SOURCE_FILE IN ITEMS ${SHADER_FILES}) OUTPUT ${SPIRV_HEADER_FILE} COMMAND - ${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -DUseUniformBlock=1 ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} --target-env ${SPIR_V_VERSION} + ${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -DUseUniformBlock=1 ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} --target-env ${SPIR_V_VERSION} --relaxed-errors MAIN_DEPENDENCY ${SOURCE_FILE} ) @@ -214,7 +214,6 @@ list(APPEND SHADER_SOURCES ${GLSL_INCLUDES}) add_custom_target(host_shaders DEPENDS ${SHADER_HEADERS} - snapdragon_gsr SOURCES ${SHADER_SOURCES} ) From c7c1c4fad1c381f50a320a2120d4491773a812dd Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 04:11:31 +0000 Subject: [PATCH 09/37] push constant is inverse --- src/video_core/renderer_vulkan/present/sgsr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 1f334cbc92..a41e1885e2 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -116,8 +116,8 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ // highp vec4 PushConstants viewport_con{}; - viewport_con[0] = std::bit_cast(viewport_x); - viewport_con[1] = std::bit_cast(viewport_y); + viewport_con[0] = std::bit_cast(1.f / viewport_x); + viewport_con[1] = std::bit_cast(1.f / viewport_y); viewport_con[2] = std::bit_cast(viewport_width); viewport_con[3] = std::bit_cast(viewport_height); From e5fe0caa3c115fbfc75f4cd461368472cacf54d2 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 04:53:47 +0000 Subject: [PATCH 10/37] fix oob error --- src/android/app/src/main/res/values/arrays.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 81383e1bfc..0250066050 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -257,6 +257,7 @@ 10 11 12 + 13 From 1924110609dfc03d7610b1af0b7861a4dbf44f35 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 04:54:59 +0000 Subject: [PATCH 11/37] FIX FUCKING BUILD --- src/video_core/renderer_vulkan/present/sgsr.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index a41e1885e2..0e4342a443 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -95,13 +95,13 @@ void SGSR::UploadImages(Scheduler& scheduler) { VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect) { Images& images = m_dynamic_images[image_index]; auto const stage0_image = *images.images[0]; - auto const stage1_image = *images.images[1]; + //auto const stage1_image = *images.images[1]; auto const stage0_descriptor_set = images.descriptor_sets[0]; - auto const stage1_descriptor_set = images.descriptor_sets[1]; + //auto const stage1_descriptor_set = images.descriptor_sets[1]; auto const stage0_framebuffer = *images.framebuffers[0]; - auto const stage1_framebuffer = *images.framebuffers[1]; + //auto const stage1_framebuffer = *images.framebuffers[1]; auto const stage0_pipeline = *m_stage_pipeline[0]; - auto const stage1_pipeline = *m_stage_pipeline[1]; + //auto const stage1_pipeline = *m_stage_pipeline[1]; VkPipelineLayout pipeline_layout = *m_pipeline_layout; VkRenderPass renderpass = *m_renderpass; From 4a1abeded0424d539dc04d703677708538c4022a Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 05:12:37 +0000 Subject: [PATCH 12/37] fix sgsr on android hopefully --- src/video_core/renderer_vulkan/present/sgsr.cpp | 5 +++++ src/video_core/renderer_vulkan/present/sgsr.h | 6 ++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 0e4342a443..f6aeb9f19c 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -23,6 +23,11 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image : m_device{device}, m_memory_allocator{memory_allocator} , m_image_count{image_count}, m_extent{extent} { + // Not finished yet initializing at ctor time? + Initialize(); +} + +void SGSR::Initialize() { m_dynamic_images.resize(m_image_count); for (auto& images : m_dynamic_images) { images.images[0] = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); diff --git a/src/video_core/renderer_vulkan/present/sgsr.h b/src/video_core/renderer_vulkan/present/sgsr.h index 14650a4143..364500a159 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.h +++ b/src/video_core/renderer_vulkan/present/sgsr.h @@ -16,11 +16,9 @@ class SGSR { public: static constexpr size_t SGSR_STAGE_COUNT = 2; explicit SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent); - VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, - VkImageView source_image_view, VkExtent2D input_image_extent, - const Common::Rectangle& crop_rect); - + VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect); private: + void Initialize(); void UploadImages(Scheduler& scheduler); void UpdateDescriptorSets(VkImageView image_view, size_t image_index); From e94af3c0c846e1461833c77f36f59241789a6159 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 05:26:00 +0000 Subject: [PATCH 13/37] fix relaxed errors --- src/video_core/host_shaders/CMakeLists.txt | 2 +- src/video_core/renderer_vulkan/present/sgsr.cpp | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 7b0d8e03e9..dc05853326 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -150,7 +150,7 @@ foreach(SOURCE_FILE IN ITEMS ${SHADER_FILES}) OUTPUT ${SPIRV_HEADER_FILE} COMMAND - ${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -DUseUniformBlock=1 ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} --target-env ${SPIR_V_VERSION} --relaxed-errors + ${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -DUseUniformBlock=1 ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} --target-env ${SPIR_V_VERSION} MAIN_DEPENDENCY ${SOURCE_FILE} ) diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index f6aeb9f19c..0567ba3905 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -24,10 +24,6 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image , m_image_count{image_count}, m_extent{extent} { // Not finished yet initializing at ctor time? - Initialize(); -} - -void SGSR::Initialize() { m_dynamic_images.resize(m_image_count); for (auto& images : m_dynamic_images) { images.images[0] = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); From 9df6919f4d99064cfc34317eb1460b57ea0cc34c Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 05:41:58 +0000 Subject: [PATCH 14/37] push new --- .patch/snapdragon_gsr/0001-fix-glsl.patch | 28 +++++++++---------- .../renderer_vulkan/present/sgsr.cpp | 3 +- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/.patch/snapdragon_gsr/0001-fix-glsl.patch b/.patch/snapdragon_gsr/0001-fix-glsl.patch index 794eed8a21..c45180b197 100644 --- a/.patch/snapdragon_gsr/0001-fix-glsl.patch +++ b/.patch/snapdragon_gsr/0001-fix-glsl.patch @@ -1,15 +1,14 @@ diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -index 7074999..2d322fb 100644 +index 7074999..4f76e1a 100644 --- a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -@@ -1,4 +1,5 @@ +@@ -1,4 +1,4 @@ -#version 300 es -+#version 310 es -+#extension GL_EXT_spec_constant_composites:require ++#version 460 core //============================================================================================================ // -@@ -34,11 +35,10 @@ precision highp int; +@@ -34,11 +34,10 @@ precision highp int; //////////////////////// #if defined(UseUniformBlock) @@ -20,11 +19,11 @@ index 7074999..2d322fb 100644 + highp vec4 ViewportInfo[1]; }; -layout(set = 0, binding = 1) uniform mediump sampler2D ps0; -+layout(set = 0, binding = 0) uniform mediump sampler2D ps0; ++layout(set = 0, binding = 0) uniform sampler2D ps0; #else uniform highp vec4 ViewportInfo[1]; uniform mediump sampler2D ps0; -@@ -63,9 +63,9 @@ vec2 weightY(float dx, float dy,float c, float std) +@@ -63,9 +62,9 @@ vec2 weightY(float dx, float dy,float c, float std) void main() { @@ -37,7 +36,7 @@ index 7074999..2d322fb 100644 vec4 color; if(mode == 1) -@@ -93,10 +93,13 @@ void main() +@@ -93,10 +92,13 @@ void main() { coord.x += ViewportInfo[0].x; @@ -55,17 +54,16 @@ index 7074999..2d322fb 100644 float mean = (left.y+left.z+right.x+right.w)*0.25; left = left - vec4(mean); diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -index d2df646..875cdbf 100644 +index d2df646..116c572 100644 --- a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -@@ -1,4 +1,5 @@ +@@ -1,4 +1,4 @@ -#version 300 es -+#version 310 es -+#extension GL_EXT_spec_constant_composites:require ++#version 460 core //============================================================================================================ // -@@ -40,11 +41,10 @@ precision highp int; +@@ -40,11 +40,10 @@ precision highp int; //////////////////////// #if defined(UseUniformBlock) @@ -76,11 +74,11 @@ index d2df646..875cdbf 100644 + highp vec4 ViewportInfo[1]; }; -layout(set = 0, binding = 1) uniform mediump sampler2D ps0; -+layout(set = 0, binding = 0) uniform mediump sampler2D ps0; ++layout(set = 0, binding = 0) uniform sampler2D ps0; #else uniform highp vec4 ViewportInfo[1]; uniform mediump sampler2D ps0; -@@ -124,10 +124,13 @@ void main() +@@ -124,10 +123,13 @@ void main() { coord.x += ViewportInfo[0].x; diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 0567ba3905..9f6a01a962 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -17,7 +17,7 @@ namespace Vulkan { -using PushConstants = std::array; +using PushConstants = std::array; SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent) : m_device{device}, m_memory_allocator{memory_allocator} @@ -65,7 +65,6 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image .pPushConstantRanges = &range, }; m_pipeline_layout = m_device.GetLogical().CreatePipelineLayout(ci); - m_stage_pipeline[0] = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, std::tie(m_vert_shader, m_stage_shader[0])); m_stage_pipeline[1] = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, std::tie(m_vert_shader, m_stage_shader[1])); } From 3d9e5e50d99dad59b9ac63f1326903629aa474a5 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 06:02:19 +0000 Subject: [PATCH 15/37] fix 2 --- src/video_core/host_shaders/CMakeLists.txt | 1 + src/video_core/host_shaders/sgsr1_shader.vert | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index dc05853326..c6158b4a2f 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -217,3 +217,4 @@ add_custom_target(host_shaders SOURCES ${SHADER_SOURCES} ) +#add_dependencies(host_shaders snapdragon_gsr::snapdragon_gsr) diff --git a/src/video_core/host_shaders/sgsr1_shader.vert b/src/video_core/host_shaders/sgsr1_shader.vert index 6a87a7cac0..a7453114bd 100644 --- a/src/video_core/host_shaders/sgsr1_shader.vert +++ b/src/video_core/host_shaders/sgsr1_shader.vert @@ -1,13 +1,13 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later #version 450 -layout(location = 0) out vec2 texcoord; +layout(location = 0) out highp vec4 texcoord; void main() { float x = float((gl_VertexIndex & 1) << 2); float y = float((gl_VertexIndex & 2) << 1); gl_Position = vec4(x - 1.0, y - 1.0, 0.0, 1.0); - texcoord = vec2(x, y) / 2.0; + texcoord = vec4(x, y, 0.f, 0.f) / 2.0; } From 0924d8918c9b2658c4c595f9d3da9826dc573fba Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 06:07:04 +0000 Subject: [PATCH 16/37] new glsl shit --- .patch/snapdragon_gsr/0001-fix-glsl.patch | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.patch/snapdragon_gsr/0001-fix-glsl.patch b/.patch/snapdragon_gsr/0001-fix-glsl.patch index c45180b197..89922f49c2 100644 --- a/.patch/snapdragon_gsr/0001-fix-glsl.patch +++ b/.patch/snapdragon_gsr/0001-fix-glsl.patch @@ -1,5 +1,5 @@ diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -index 7074999..4f76e1a 100644 +index 7074999..cb1eea3 100644 --- a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag @@ -1,4 +1,4 @@ @@ -19,7 +19,7 @@ index 7074999..4f76e1a 100644 + highp vec4 ViewportInfo[1]; }; -layout(set = 0, binding = 1) uniform mediump sampler2D ps0; -+layout(set = 0, binding = 0) uniform sampler2D ps0; ++layout(set = 0, binding = 0) uniform mediump sampler2D ps0; #else uniform highp vec4 ViewportInfo[1]; uniform mediump sampler2D ps0; @@ -54,7 +54,7 @@ index 7074999..4f76e1a 100644 float mean = (left.y+left.z+right.x+right.w)*0.25; left = left - vec4(mean); diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -index d2df646..116c572 100644 +index d2df646..95d09cf 100644 --- a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag @@ -1,4 +1,4 @@ @@ -74,7 +74,7 @@ index d2df646..116c572 100644 + highp vec4 ViewportInfo[1]; }; -layout(set = 0, binding = 1) uniform mediump sampler2D ps0; -+layout(set = 0, binding = 0) uniform sampler2D ps0; ++layout(set = 0, binding = 0) uniform mediump sampler2D ps0; #else uniform highp vec4 ViewportInfo[1]; uniform mediump sampler2D ps0; From bc8bcb13103b959ff305a4daa7dd23a94229519c Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 08:21:20 +0000 Subject: [PATCH 17/37] fx --- src/video_core/host_shaders/sgsr1_shader.vert | 2 +- src/video_core/renderer_vulkan/present/sgsr.cpp | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/video_core/host_shaders/sgsr1_shader.vert b/src/video_core/host_shaders/sgsr1_shader.vert index a7453114bd..8fa7ddff73 100644 --- a/src/video_core/host_shaders/sgsr1_shader.vert +++ b/src/video_core/host_shaders/sgsr1_shader.vert @@ -8,6 +8,6 @@ layout(location = 0) out highp vec4 texcoord; void main() { float x = float((gl_VertexIndex & 1) << 2); float y = float((gl_VertexIndex & 2) << 1); - gl_Position = vec4(x - 1.0, y - 1.0, 0.0, 1.0); + gl_Position = vec4(x - 1.0f, y - 1.0f, 0.0, 1.0f); texcoord = vec4(x, y, 0.f, 0.f) / 2.0; } diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 9f6a01a962..702f960939 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -109,6 +109,8 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ const f32 input_image_width = f32(input_image_extent.width); const f32 input_image_height = f32(input_image_extent.height); + const f32 output_image_width = f32(extent.width); + const f32 output_image_height = f32(extent.height); const f32 viewport_x = crop_rect.left * input_image_width; const f32 viewport_y = crop_rect.top * input_image_height; const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_image_width; @@ -116,10 +118,10 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ // highp vec4 PushConstants viewport_con{}; - viewport_con[0] = std::bit_cast(1.f / viewport_x); - viewport_con[1] = std::bit_cast(1.f / viewport_y); - viewport_con[2] = std::bit_cast(viewport_width); - viewport_con[3] = std::bit_cast(viewport_height); + viewport_con[2] = std::bit_cast(0.5f * viewport_width / output_image_width - 0.5f + viewport_x); + viewport_con[3] = std::bit_cast(0.5f * viewport_height / output_image_height - 0.5f + viewport_y); + viewport_con[0] = std::bit_cast(1.f / std::bit_cast(viewport_con[2])); + viewport_con[1] = std::bit_cast(1.f / std::bit_cast(viewport_con[3])); UploadImages(scheduler); UpdateDescriptorSets(source_image_view, image_index); From bfc72fd364cc40d46e66a68dd5da315ab836a202 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Wed, 14 Jan 2026 13:43:45 -0400 Subject: [PATCH 18/37] [renderer_vulkan, sgsr] Playing a bit with viewports --- src/video_core/renderer_vulkan/present/sgsr.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 702f960939..31ba3b4eb0 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -116,12 +116,14 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_image_width; const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_image_height; - // highp vec4 + // ViewportInfo[0] = vec4(1/inputWidth, 1/inputHeight, inputWidth, inputHeight) + // .xy = pixel step size for texture sampling + // .zw = input texture dimensions for coordinate scaling PushConstants viewport_con{}; - viewport_con[2] = std::bit_cast(0.5f * viewport_width / output_image_width - 0.5f + viewport_x); - viewport_con[3] = std::bit_cast(0.5f * viewport_height / output_image_height - 0.5f + viewport_y); - viewport_con[0] = std::bit_cast(1.f / std::bit_cast(viewport_con[2])); - viewport_con[1] = std::bit_cast(1.f / std::bit_cast(viewport_con[3])); + viewport_con[0] = std::bit_cast(1.f / input_image_width); + viewport_con[1] = std::bit_cast(1.f / input_image_height); + viewport_con[2] = std::bit_cast(input_image_width); + viewport_con[3] = std::bit_cast(input_image_height); UploadImages(scheduler); UpdateDescriptorSets(source_image_view, image_index); From 8451112a2f8c849e31afa5ffbdc04ec542b3caff Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Wed, 14 Jan 2026 16:29:31 -0400 Subject: [PATCH 19/37] [renderer_vulkan, sgsr] Another try --- src/video_core/renderer_vulkan/present/sgsr.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 31ba3b4eb0..25953090c0 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -116,14 +116,11 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_image_width; const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_image_height; - // ViewportInfo[0] = vec4(1/inputWidth, 1/inputHeight, inputWidth, inputHeight) - // .xy = pixel step size for texture sampling - // .zw = input texture dimensions for coordinate scaling PushConstants viewport_con{}; - viewport_con[0] = std::bit_cast(1.f / input_image_width); - viewport_con[1] = std::bit_cast(1.f / input_image_height); - viewport_con[2] = std::bit_cast(input_image_width); - viewport_con[3] = std::bit_cast(input_image_height); + viewport_con[0] = std::bit_cast(1.f / output_image_width); + viewport_con[1] = std::bit_cast(1.f / output_image_height); + viewport_con[2] = std::bit_cast(output_image_width); + viewport_con[3] = std::bit_cast(output_image_height); UploadImages(scheduler); UpdateDescriptorSets(source_image_view, image_index); From 5460ca464a52eb7d26d677b59be73022ec593f08 Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 20 Jan 2026 20:09:50 +0000 Subject: [PATCH 20/37] fix sgsr with new variant shit --- src/video_core/renderer_vulkan/present/layer.cpp | 8 ++++---- src/video_core/renderer_vulkan/present/layer.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/video_core/renderer_vulkan/present/layer.cpp b/src/video_core/renderer_vulkan/present/layer.cpp index d6c0ca082f..198fd4f468 100644 --- a/src/video_core/renderer_vulkan/present/layer.cpp +++ b/src/video_core/renderer_vulkan/present/layer.cpp @@ -64,9 +64,9 @@ Layer::Layer(const Device& device_, MemoryAllocator& memory_allocator_, Schedule CreateDescriptorPool(); CreateDescriptorSets(layout); if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr) { - fsr.emplace(device, memory_allocator, image_count, output_size); + sr_filter.emplace(device, memory_allocator, image_count, output_size); } else if (filters.get_scaling_filter() == Settings::ScalingFilter::Sgsr) { - sgsr.emplace(device, memory_allocator, image_count, output_size); + sr_filter.emplace(device, memory_allocator, image_count, output_size); } } @@ -117,10 +117,10 @@ void Layer::ConfigureDraw(PresentPushConstants* out_push_constants, .height = scaled_height, }; - if (fsr) { + if (auto* fsr = std::get_if(&sr_filter)) { source_image_view = fsr->Draw(scheduler, image_index, source_image, source_image_view, render_extent, crop_rect); crop_rect = {0, 0, 1, 1}; - } else if (sgsr) { + } else if (auto* sgsr = std::get_if(&sr_filter)) { source_image_view = sgsr->Draw(scheduler, image_index, source_image, source_image_view, render_extent, crop_rect); crop_rect = {0, 0, 1, 1}; } diff --git a/src/video_core/renderer_vulkan/present/layer.h b/src/video_core/renderer_vulkan/present/layer.h index 6de7a66087..47a6a69218 100644 --- a/src/video_core/renderer_vulkan/present/layer.h +++ b/src/video_core/renderer_vulkan/present/layer.h @@ -13,6 +13,7 @@ #include "video_core/host1x/gpu_device_memory_manager.h" #include "video_core/vulkan_common/vulkan_wrapper.h" #include "video_core/renderer_vulkan/present/fsr.h" +#include "video_core/renderer_vulkan/present/sgsr.h" #include "video_core/renderer_vulkan/present/fxaa.h" #include "video_core/renderer_vulkan/present/smaa.h" @@ -95,8 +96,7 @@ private: Settings::AntiAliasing anti_alias_setting{}; std::variant anti_alias{}; - std::optional fsr{}; - std::unique_ptr sgsr{}; + std::variant sr_filter{}; std::vector resource_ticks{}; }; From f514ecaa81c1e1001e46a57f2ae96ddd24a964dd Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 20 Jan 2026 21:25:44 +0000 Subject: [PATCH 21/37] fix sgsr --- src/video_core/renderer_vulkan/present/layer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video_core/renderer_vulkan/present/layer.cpp b/src/video_core/renderer_vulkan/present/layer.cpp index 198fd4f468..b988e0862b 100644 --- a/src/video_core/renderer_vulkan/present/layer.cpp +++ b/src/video_core/renderer_vulkan/present/layer.cpp @@ -117,10 +117,10 @@ void Layer::ConfigureDraw(PresentPushConstants* out_push_constants, .height = scaled_height, }; - if (auto* fsr = std::get_if(&sr_filter)) { + if (auto* fsr = std::get_if(&sr_filter)) { source_image_view = fsr->Draw(scheduler, image_index, source_image, source_image_view, render_extent, crop_rect); crop_rect = {0, 0, 1, 1}; - } else if (auto* sgsr = std::get_if(&sr_filter)) { + } else if (auto* sgsr = std::get_if(&sr_filter)) { source_image_view = sgsr->Draw(scheduler, image_index, source_image, source_image_view, render_extent, crop_rect); crop_rect = {0, 0, 1, 1}; } From a6e5c38804d2f50d3c929bc2faa47c57622f1b56 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 24 Jan 2026 08:21:27 +0000 Subject: [PATCH 22/37] fixup sgsr for realsies --- .patch/sgsr/0001-fix-glsl.patch | 82 ++++++++++++++++ .patch/snapdragon_gsr/0001-fix-glsl.patch | 97 ------------------- CMakeLists.txt | 2 +- src/video_core/host_shaders/CMakeLists.txt | 6 +- .../renderer_vulkan/present/sgsr.cpp | 10 +- 5 files changed, 92 insertions(+), 105 deletions(-) create mode 100644 .patch/sgsr/0001-fix-glsl.patch delete mode 100644 .patch/snapdragon_gsr/0001-fix-glsl.patch diff --git a/.patch/sgsr/0001-fix-glsl.patch b/.patch/sgsr/0001-fix-glsl.patch new file mode 100644 index 0000000000..15a886dddd --- /dev/null +++ b/.patch/sgsr/0001-fix-glsl.patch @@ -0,0 +1,82 @@ +diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +index 7074999..b465126 100644 +--- a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag ++++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +@@ -1,4 +1,4 @@ +-#version 300 es ++#version 460 core + + //============================================================================================================ + // +@@ -34,11 +34,10 @@ precision highp int; + //////////////////////// + + #if defined(UseUniformBlock) +-layout (set=0, binding = 0) uniform UniformBlock +-{ +- highp vec4 ViewportInfo[1]; ++layout( push_constant ) uniform constants { ++ highp vec4 ViewportInfo[1]; + }; +-layout(set = 0, binding = 1) uniform mediump sampler2D ps0; ++layout(set = 0, binding = 0) uniform mediump sampler2D ps0; + #else + uniform highp vec4 ViewportInfo[1]; + uniform mediump sampler2D ps0; +@@ -63,15 +62,19 @@ vec2 weightY(float dx, float dy,float c, float std) + + void main() + { +- int mode = OperationMode; +- float edgeThreshold = EdgeThreshold; +- float edgeSharpness = EdgeSharpness; ++ const int mode = OperationMode; ++ const float edgeThreshold = EdgeThreshold; ++ const float edgeSharpness = EdgeSharpness; ++ ++ vec2 full_texsize = textureSize(ps0, 0); ++ vec2 recp_texsize = 1.0 / full_texsize; ++ vec2 resize_factor = ViewportInfo[0].zw / full_texsize; + + vec4 color; + if(mode == 1) +- color.xyz = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyz; ++ color.xyz = textureLod(ps0, in_TEXCOORD0.xy * resize_factor, 0.0).xyz; + else +- color.xyzw = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyzw; ++ color.xyzw = textureLod(ps0, in_TEXCOORD0.xy * resize_factor, 0.0).xyzw; + + highp float xCenter; + xCenter = abs(in_TEXCOORD0.x+-0.5); +@@ -82,21 +85,24 @@ void main() + //if ( mode!=4 && xCenter*xCenter+yCenter*yCenter<=0.4 * 0.4) + if ( mode!=4) + { +- highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo[0].zw)+vec2(-0.5,0.5)); ++ highp vec2 imgCoord = ((in_TEXCOORD0.xy * ViewportInfo[0].zw) + vec2(-0.5,0.5)); + highp vec2 imgCoordPixel = floor(imgCoord); +- highp vec2 coord = (imgCoordPixel*ViewportInfo[0].xy); +- vec2 pl = (imgCoord+(-imgCoordPixel)); +- vec4 left = textureGather(ps0,coord, mode); ++ highp vec2 coord = imgCoordPixel * ViewportInfo[0].xy; ++ vec2 pl = imgCoord - imgCoordPixel; ++ vec4 left = textureGather(ps0, coord * resize_factor, mode); + + float edgeVote = abs(left.z - left.y) + abs(color[mode] - left.y) + abs(color[mode] - left.z) ; + if(edgeVote > edgeThreshold) + { + coord.x += ViewportInfo[0].x; + +- vec4 right = textureGather(ps0,coord + highp vec2(ViewportInfo[0].x, 0.0), mode); ++ highp vec2 IR_highp_vec2_0 = coord + vec2(ViewportInfo[0].x, 0.0); ++ vec4 right = textureGather(ps0, IR_highp_vec2_0 * resize_factor, mode); + vec4 upDown; +- upDown.xy = textureGather(ps0,coord + highp vec2(0.0, -ViewportInfo[0].y),mode).wz; +- upDown.zw = textureGather(ps0,coord+ highp vec2(0.0, ViewportInfo[0].y), mode).yx; ++ highp vec2 IR_highp_vec2_1 = coord + vec2(0.0, -ViewportInfo[0].y); ++ upDown.xy = textureGather(ps0, IR_highp_vec2_1 * resize_factor, mode).wz; ++ highp vec2 IR_highp_vec2_2 = coord + vec2(0.0, ViewportInfo[0].y); ++ upDown.zw = textureGather(ps0, IR_highp_vec2_2 * resize_factor, mode).yx; + + float mean = (left.y+left.z+right.x+right.w)*0.25; + left = left - vec4(mean); diff --git a/.patch/snapdragon_gsr/0001-fix-glsl.patch b/.patch/snapdragon_gsr/0001-fix-glsl.patch deleted file mode 100644 index 89922f49c2..0000000000 --- a/.patch/snapdragon_gsr/0001-fix-glsl.patch +++ /dev/null @@ -1,97 +0,0 @@ -diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -index 7074999..cb1eea3 100644 ---- a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -+++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -@@ -1,4 +1,4 @@ --#version 300 es -+#version 460 core - - //============================================================================================================ - // -@@ -34,11 +34,10 @@ precision highp int; - //////////////////////// - - #if defined(UseUniformBlock) --layout (set=0, binding = 0) uniform UniformBlock --{ -- highp vec4 ViewportInfo[1]; -+layout( push_constant ) uniform constants { -+ highp vec4 ViewportInfo[1]; - }; --layout(set = 0, binding = 1) uniform mediump sampler2D ps0; -+layout(set = 0, binding = 0) uniform mediump sampler2D ps0; - #else - uniform highp vec4 ViewportInfo[1]; - uniform mediump sampler2D ps0; -@@ -63,9 +62,9 @@ vec2 weightY(float dx, float dy,float c, float std) - - void main() - { -- int mode = OperationMode; -- float edgeThreshold = EdgeThreshold; -- float edgeSharpness = EdgeSharpness; -+ const int mode = OperationMode; -+ const float edgeThreshold = EdgeThreshold; -+ const float edgeSharpness = EdgeSharpness; - - vec4 color; - if(mode == 1) -@@ -93,10 +92,13 @@ void main() - { - coord.x += ViewportInfo[0].x; - -- vec4 right = textureGather(ps0,coord + highp vec2(ViewportInfo[0].x, 0.0), mode); -+ highp vec2 IR_highp_vec2_0 = vec2(ViewportInfo[0].x, 0.0); -+ vec4 right = textureGather(ps0,coord + IR_highp_vec2_0, mode); - vec4 upDown; -- upDown.xy = textureGather(ps0,coord + highp vec2(0.0, -ViewportInfo[0].y),mode).wz; -- upDown.zw = textureGather(ps0,coord+ highp vec2(0.0, ViewportInfo[0].y), mode).yx; -+ highp vec2 IR_highp_vec2_1 = vec2(0.0, -ViewportInfo[0].y); -+ upDown.xy = textureGather(ps0,coord + IR_highp_vec2_1,mode).wz; -+ highp vec2 IR_highp_vec2_2 = vec2(0.0, ViewportInfo[0].y); -+ upDown.zw = textureGather(ps0,coord+ IR_highp_vec2_2, mode).yx; - - float mean = (left.y+left.z+right.x+right.w)*0.25; - left = left - vec4(mean); -diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -index d2df646..95d09cf 100644 ---- a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -+++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -@@ -1,4 +1,4 @@ --#version 300 es -+#version 460 core - - //============================================================================================================ - // -@@ -40,11 +40,10 @@ precision highp int; - //////////////////////// - - #if defined(UseUniformBlock) --layout (set=0, binding = 0) uniform UniformBlock --{ -- highp vec4 ViewportInfo[1]; -+layout( push_constant ) uniform constants { -+ highp vec4 ViewportInfo[1]; - }; --layout(set = 0, binding = 1) uniform mediump sampler2D ps0; -+layout(set = 0, binding = 0) uniform mediump sampler2D ps0; - #else - uniform highp vec4 ViewportInfo[1]; - uniform mediump sampler2D ps0; -@@ -124,10 +123,13 @@ void main() - { - coord.x += ViewportInfo[0].x; - -- vec4 right = textureGather(ps0,coord + highp vec2(ViewportInfo[0].x, 0.0), OperationMode); -+ highp vec2 IR_highp_vec2_0 = vec2(ViewportInfo[0].x, 0.0); -+ vec4 right = textureGather(ps0,coord + IR_highp_vec2_0, OperationMode); - vec4 upDown; -- upDown.xy = textureGather(ps0,coord + highp vec2(0.0, -ViewportInfo[0].y),OperationMode).wz; -- upDown.zw = textureGather(ps0,coord+ highp vec2(0.0, ViewportInfo[0].y), OperationMode).yx; -+ highp vec2 IR_highp_vec2_1 = vec2(0.0, -ViewportInfo[0].y); -+ upDown.xy = textureGather(ps0,coord + IR_highp_vec2_1,OperationMode).wz; -+ highp vec2 IR_highp_vec2_2 = vec2(0.0, ViewportInfo[0].y); -+ upDown.zw = textureGather(ps0,coord+ IR_highp_vec2_2, OperationMode).yx; - - float mean = (left.y+left.z+right.x+right.w)*0.25; - left = left - vec4(mean); diff --git a/CMakeLists.txt b/CMakeLists.txt index c071c6e1f5..75f02b5d09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -233,7 +233,7 @@ endif() option(YUZU_USE_BUNDLED_OPENSSL "Download bundled OpenSSL build" ${DEFAULT_YUZU_USE_BUNDLED_OPENSSL}) -AddJsonPackage(snapdragon_gsr) +AddJsonPackage(sgsr) # TODO(crueter): CPM this if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL) diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index c6158b4a2f..f2b4846db8 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -79,8 +79,8 @@ set(SHADER_FILES # Snapdragon Game Super Resolution ${CMAKE_CURRENT_SOURCE_DIR}/sgsr1_shader.vert - ${snapdragon_gsr_SOURCE_DIR}/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag - ${snapdragon_gsr_SOURCE_DIR}/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag + ${sgsr_SOURCE_DIR}/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag + ${sgsr_SOURCE_DIR}/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag ) if (PLATFORM_HAIKU) @@ -217,4 +217,4 @@ add_custom_target(host_shaders SOURCES ${SHADER_SOURCES} ) -#add_dependencies(host_shaders snapdragon_gsr::snapdragon_gsr) +#add_dependencies(host_shaders sgsr::sgsr) diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 25953090c0..804107cfda 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -116,11 +116,13 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_image_width; const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_image_height; + // p = (tex * viewport) / input = [0,n] (normalized texcoords) + // p * input = [0,1024], [0,768] PushConstants viewport_con{}; - viewport_con[0] = std::bit_cast(1.f / output_image_width); - viewport_con[1] = std::bit_cast(1.f / output_image_height); - viewport_con[2] = std::bit_cast(output_image_width); - viewport_con[3] = std::bit_cast(output_image_height); + viewport_con[0] = std::bit_cast(1.f / viewport_width); + viewport_con[1] = std::bit_cast(1.f / viewport_height); + viewport_con[2] = std::bit_cast(viewport_width); + viewport_con[3] = std::bit_cast(viewport_height); UploadImages(scheduler); UpdateDescriptorSets(source_image_view, image_index); From 0a1133901af255ed50fa869583d3a38d9e02ea4d Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 24 Jan 2026 08:21:44 +0000 Subject: [PATCH 23/37] fix license --- src/video_core/renderer_opengl/gl_blit_screen.cpp | 2 +- src/video_core/renderer_vulkan/present/sgsr.cpp | 2 +- src/video_core/renderer_vulkan/present/sgsr.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_blit_screen.cpp b/src/video_core/renderer_opengl/gl_blit_screen.cpp index b03fc3ecbd..c839d05c9a 100644 --- a/src/video_core/renderer_opengl/gl_blit_screen.cpp +++ b/src/video_core/renderer_opengl/gl_blit_screen.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 Torzu Emulator Project diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 804107cfda..457b1ddb02 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include "common/common_types.h" diff --git a/src/video_core/renderer_vulkan/present/sgsr.h b/src/video_core/renderer_vulkan/present/sgsr.h index 364500a159..ca48e4998d 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.h +++ b/src/video_core/renderer_vulkan/present/sgsr.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once From 48e718946e159281c9b4c6f610e5cd89223d1840 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 24 Jan 2026 08:46:36 +0000 Subject: [PATCH 24/37] Add SGSR edge variant --- .patch/sgsr/0001-fix-glsl.patch | 75 ++++++++++++++++++- docs/user/Graphics.md | 1 + .../app/src/main/res/values/arrays.xml | 1 + .../app/src/main/res/values/strings.xml | 3 +- src/common/settings_enums.h | 2 +- src/qt_common/config/shared_translation.cpp | 1 + src/qt_common/config/shared_translation.h | 1 + src/video_core/host_shaders/sgsr1_shader.vert | 4 +- .../renderer_opengl/gl_blit_screen.cpp | 1 + .../renderer_vulkan/present/layer.cpp | 4 +- .../renderer_vulkan/present/sgsr.cpp | 31 ++------ src/video_core/renderer_vulkan/present/sgsr.h | 5 +- .../renderer_vulkan/vk_blit_screen.cpp | 1 + 13 files changed, 97 insertions(+), 33 deletions(-) diff --git a/.patch/sgsr/0001-fix-glsl.patch b/.patch/sgsr/0001-fix-glsl.patch index 15a886dddd..37bb823572 100644 --- a/.patch/sgsr/0001-fix-glsl.patch +++ b/.patch/sgsr/0001-fix-glsl.patch @@ -1,5 +1,5 @@ diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -index 7074999..b465126 100644 +index 7074999..9e2122e 100644 --- a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag @@ -1,4 +1,4 @@ @@ -8,7 +8,7 @@ index 7074999..b465126 100644 //============================================================================================================ // -@@ -34,11 +34,10 @@ precision highp int; +@@ -34,17 +34,16 @@ precision highp int; //////////////////////// #if defined(UseUniformBlock) @@ -23,6 +23,13 @@ index 7074999..b465126 100644 #else uniform highp vec4 ViewportInfo[1]; uniform mediump sampler2D ps0; + #endif + +-layout(location=0) in highp vec4 in_TEXCOORD0; ++layout(location=0) in highp vec2 in_TEXCOORD0; + layout(location=0) out vec4 out_Target0; + + float fastLanczos2(float x) @@ -63,15 +62,19 @@ vec2 weightY(float dx, float dy,float c, float std) void main() @@ -80,3 +87,67 @@ index 7074999..b465126 100644 float mean = (left.y+left.z+right.x+right.w)*0.25; left = left - vec4(mean); +diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +index d2df646..91a8d4d 100644 +--- a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag ++++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +@@ -1,4 +1,4 @@ +-#version 300 es ++#version 460 core + + //============================================================================================================ + // +@@ -50,7 +50,7 @@ uniform highp vec4 ViewportInfo[1]; + uniform mediump sampler2D ps0; + #endif + +-layout(location=0) in highp vec4 in_TEXCOORD0; ++layout(location=0) in highp vec2 in_TEXCOORD0; + layout(location=0) out vec4 out_Target0; + + float fastLanczos2(float x) +@@ -98,11 +98,15 @@ vec2 edgeDirection(vec4 left, vec4 right) + + void main() + { ++ vec2 full_texsize = textureSize(ps0, 0); ++ vec2 recp_texsize = 1.0 / full_texsize; ++ vec2 resize_factor = ViewportInfo[0].zw / full_texsize; ++ + vec4 color; + if(OperationMode == 1) +- color.xyz = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyz; ++ color.xyz = textureLod(ps0,in_TEXCOORD0.xy * resize_factor,0.0).xyz; + else +- color.xyzw = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyzw; ++ color.xyzw = textureLod(ps0,in_TEXCOORD0.xy * resize_factor,0.0).xyzw; + + highp float xCenter; + xCenter = abs(in_TEXCOORD0.x+-0.5); +@@ -116,18 +120,21 @@ void main() + highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo[0].zw)+vec2(-0.5,0.5)); + highp vec2 imgCoordPixel = floor(imgCoord); + highp vec2 coord = (imgCoordPixel*ViewportInfo[0].xy); +- vec2 pl = (imgCoord+(-imgCoordPixel)); +- vec4 left = textureGather(ps0,coord, OperationMode); ++ vec2 pl = imgCoord - imgCoordPixel; ++ vec4 left = textureGather(ps0, coord * resize_factor, OperationMode); + + float edgeVote = abs(left.z - left.y) + abs(color[OperationMode] - left.y) + abs(color[OperationMode] - left.z) ; + if(edgeVote > EdgeThreshold) + { + coord.x += ViewportInfo[0].x; + +- vec4 right = textureGather(ps0,coord + highp vec2(ViewportInfo[0].x, 0.0), OperationMode); ++ highp vec2 IR_highp_vec2_0 = coord + vec2(ViewportInfo[0].x, 0.0); ++ vec4 right = textureGather(ps0, IR_highp_vec2_0 * resize_factor, OperationMode); + vec4 upDown; +- upDown.xy = textureGather(ps0,coord + highp vec2(0.0, -ViewportInfo[0].y),OperationMode).wz; +- upDown.zw = textureGather(ps0,coord+ highp vec2(0.0, ViewportInfo[0].y), OperationMode).yx; ++ highp vec2 IR_highp_vec2_1 = coord + vec2(0.0, -ViewportInfo[0].y); ++ upDown.xy = textureGather(ps0, IR_highp_vec2_1 * resize_factor, OperationMode).wz; ++ highp vec2 IR_highp_vec2_2 = coord + vec2(0.0, ViewportInfo[0].y); ++ upDown.zw = textureGather(ps0, IR_highp_vec2_2 * resize_factor, OperationMode).yx; + + float mean = (left.y+left.z+right.x+right.w)*0.25; + left = left - vec4(mean); diff --git a/docs/user/Graphics.md b/docs/user/Graphics.md index 49ee0e68b2..4d3b1da3c7 100644 --- a/docs/user/Graphics.md +++ b/docs/user/Graphics.md @@ -47,6 +47,7 @@ Various graphical filters exist - each of them aimed at a specific target/image - **SGSR**: Uses Snapdragon Studios Game Super Resolution to enhance image quality (similar to FSR, but for Adreno devices). - **Pros**: Optimized for Adreno devices. - **Cons**: Doesn't play nicely with non-Adreno devices. +- **SGSR Edge**: Almost the same pipeline as SGSR, but with improved edge detection. ### Anisotropy values diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 0250066050..7d00dd23ad 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -241,6 +241,7 @@ @string/scaling_filter_mitchell @string/scaling_filter_spline1 @string/scaling_filter_sgsr + @string/scaling_filter_sgsr_edge diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 3e98222f7e..0188fd4b3d 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -1074,7 +1074,8 @@ B-Spline Mitchell MMPX - Snapdragon Game Super Resolution + Snapdragon GSR + Snapdragon GSR EdgeDir None diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index 389b16608f..60a194a35d 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h @@ -143,7 +143,7 @@ ENUM(ConfirmStop, Ask_Always, Ask_Based_On_Game, Ask_Never); ENUM(FullscreenMode, Borderless, Exclusive); ENUM(NvdecEmulation, Off, Cpu, Gpu); ENUM(ResolutionSetup, Res1_4X, Res1_2X, Res3_4X, Res1X, Res5_4X, Res3_2X, Res2X, Res3X, Res4X, Res5X, Res6X, Res7X, Res8X); -ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Gaussian, Lanczos, ScaleForce, Fsr, Area, ZeroTangent, BSpline, Mitchell, Spline1, Mmpx, Sgsr, MaxEnum); +ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Gaussian, Lanczos, ScaleForce, Fsr, Area, ZeroTangent, BSpline, Mitchell, Spline1, Mmpx, Sgsr, SgsrEdge, MaxEnum); ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum); ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch); ENUM(ConsoleMode, Handheld, Docked); diff --git a/src/qt_common/config/shared_translation.cpp b/src/qt_common/config/shared_translation.cpp index f6b509c77b..ca74f8d3cc 100644 --- a/src/qt_common/config/shared_translation.cpp +++ b/src/qt_common/config/shared_translation.cpp @@ -494,6 +494,7 @@ std::unique_ptr ComboboxEnumeration(QObject* parent) { PAIR(ScalingFilter, Mitchell, tr("Mitchell")), PAIR(ScalingFilter, Spline1, tr("Spline-1")), PAIR(ScalingFilter, Sgsr, tr("Snapdragon Game Super Resolution")), + PAIR(ScalingFilter, SgsrEdge, tr("Snapdragon Game Super Resolution EdgeDir")), }}); translations->insert({Settings::EnumMetadata::Index(), { diff --git a/src/qt_common/config/shared_translation.h b/src/qt_common/config/shared_translation.h index edadf5eb9b..c34b5162c4 100644 --- a/src/qt_common/config/shared_translation.h +++ b/src/qt_common/config/shared_translation.h @@ -54,6 +54,7 @@ static const std::map scaling_filter_texts_map {Settings::ScalingFilter::Area, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Area"))}, {Settings::ScalingFilter::Mmpx, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "MMPX"))}, {Settings::ScalingFilter::Sgsr, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "SGSR"))}, + {Settings::ScalingFilter::SgsrEdge, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "SGSR EdgeDir"))}, }; static const std::map use_docked_mode_texts_map = { diff --git a/src/video_core/host_shaders/sgsr1_shader.vert b/src/video_core/host_shaders/sgsr1_shader.vert index 8fa7ddff73..00649312fb 100644 --- a/src/video_core/host_shaders/sgsr1_shader.vert +++ b/src/video_core/host_shaders/sgsr1_shader.vert @@ -3,11 +3,11 @@ #version 450 -layout(location = 0) out highp vec4 texcoord; +layout(location = 0) out highp vec2 texcoord; void main() { float x = float((gl_VertexIndex & 1) << 2); float y = float((gl_VertexIndex & 2) << 1); gl_Position = vec4(x - 1.0f, y - 1.0f, 0.0, 1.0f); - texcoord = vec4(x, y, 0.f, 0.f) / 2.0; + texcoord = vec2(x, y) / 2.0; } diff --git a/src/video_core/renderer_opengl/gl_blit_screen.cpp b/src/video_core/renderer_opengl/gl_blit_screen.cpp index c839d05c9a..23e5eb7481 100644 --- a/src/video_core/renderer_opengl/gl_blit_screen.cpp +++ b/src/video_core/renderer_opengl/gl_blit_screen.cpp @@ -116,6 +116,7 @@ void BlitScreen::CreateWindowAdapt() { break; case Settings::ScalingFilter::Fsr: case Settings::ScalingFilter::Sgsr: + case Settings::ScalingFilter::SgsrEdge: case Settings::ScalingFilter::Bilinear: default: window_adapt = MakeBilinear(device); diff --git a/src/video_core/renderer_vulkan/present/layer.cpp b/src/video_core/renderer_vulkan/present/layer.cpp index b988e0862b..e20473d2af 100644 --- a/src/video_core/renderer_vulkan/present/layer.cpp +++ b/src/video_core/renderer_vulkan/present/layer.cpp @@ -66,7 +66,9 @@ Layer::Layer(const Device& device_, MemoryAllocator& memory_allocator_, Schedule if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr) { sr_filter.emplace(device, memory_allocator, image_count, output_size); } else if (filters.get_scaling_filter() == Settings::ScalingFilter::Sgsr) { - sr_filter.emplace(device, memory_allocator, image_count, output_size); + sr_filter.emplace(device, memory_allocator, image_count, output_size, false); + } else if (filters.get_scaling_filter() == Settings::ScalingFilter::SgsrEdge) { + sr_filter.emplace(device, memory_allocator, image_count, output_size, true); } } diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 457b1ddb02..e4cb5dbb4c 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -19,29 +19,27 @@ namespace Vulkan { using PushConstants = std::array; -SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent) +SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent, bool edge_dir) : m_device{device}, m_memory_allocator{memory_allocator} , m_image_count{image_count}, m_extent{extent} + , m_edge_dir{edge_dir} { // Not finished yet initializing at ctor time? m_dynamic_images.resize(m_image_count); for (auto& images : m_dynamic_images) { images.images[0] = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); - images.images[1] = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); images.image_views[0] = CreateWrappedImageView(m_device, images.images[0], VK_FORMAT_R16G16B16A16_SFLOAT); - images.image_views[1] = CreateWrappedImageView(m_device, images.images[1], VK_FORMAT_R16G16B16A16_SFLOAT); } m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); - for (auto& images : m_dynamic_images) { + for (auto& images : m_dynamic_images) images.framebuffers[0] = CreateWrappedFramebuffer(m_device, m_renderpass, images.image_views[0], m_extent); - images.framebuffers[1] = CreateWrappedFramebuffer(m_device, m_renderpass, images.image_views[1], m_extent); - } m_sampler = CreateBilinearSampler(m_device); m_vert_shader = BuildShader(m_device, SGSR1_SHADER_VERT_SPV); - m_stage_shader[0] = BuildShader(m_device, SGSR1_SHADER_MOBILE_FRAG_SPV); - m_stage_shader[1] = BuildShader(m_device, SGSR1_SHADER_MOBILE_EDGE_DIRECTION_FRAG_SPV); + m_stage_shader[0] = m_edge_dir + ? BuildShader(m_device, SGSR1_SHADER_MOBILE_EDGE_DIRECTION_FRAG_SPV) + : BuildShader(m_device, SGSR1_SHADER_MOBILE_FRAG_SPV); // 2 descriptors, 2 descriptor sets per invocation m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 2 * m_image_count, 2 * m_image_count); m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); @@ -66,14 +64,13 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image }; m_pipeline_layout = m_device.GetLogical().CreatePipelineLayout(ci); m_stage_pipeline[0] = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, std::tie(m_vert_shader, m_stage_shader[0])); - m_stage_pipeline[1] = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, std::tie(m_vert_shader, m_stage_shader[1])); } void SGSR::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { Images& images = m_dynamic_images[image_index]; std::vector image_infos; std::vector updates; - image_infos.reserve(2); + image_infos.reserve(1); updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, images.descriptor_sets[0], 0)); updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[0], images.descriptor_sets[1], 0)); m_device.GetLogical().UpdateDescriptorSets(updates, {}); @@ -84,7 +81,6 @@ void SGSR::UploadImages(Scheduler& scheduler) { scheduler.Record([&](vk::CommandBuffer cmdbuf) { for (auto& image : m_dynamic_images) { ClearColorImage(cmdbuf, *image.images[0]); - ClearColorImage(cmdbuf, *image.images[1]); } }); scheduler.Finish(); @@ -95,13 +91,9 @@ void SGSR::UploadImages(Scheduler& scheduler) { VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect) { Images& images = m_dynamic_images[image_index]; auto const stage0_image = *images.images[0]; - //auto const stage1_image = *images.images[1]; auto const stage0_descriptor_set = images.descriptor_sets[0]; - //auto const stage1_descriptor_set = images.descriptor_sets[1]; auto const stage0_framebuffer = *images.framebuffers[0]; - //auto const stage1_framebuffer = *images.framebuffers[1]; auto const stage0_pipeline = *m_stage_pipeline[0]; - //auto const stage1_pipeline = *m_stage_pipeline[1]; VkPipelineLayout pipeline_layout = *m_pipeline_layout; VkRenderPass renderpass = *m_renderpass; @@ -138,16 +130,7 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ cmdbuf.Draw(3, 1, 0, 0); cmdbuf.EndRenderPass(); TransitionImageLayout(cmdbuf, stage0_image, VK_IMAGE_LAYOUT_GENERAL); - // TransitionImageLayout(cmdbuf, stage1_image, VK_IMAGE_LAYOUT_GENERAL); - // BeginRenderPass(cmdbuf, renderpass, stage1_framebuffer, extent); - // cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, stage1_pipeline); - // cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, stage1_descriptor_set, {}); - // cmdbuf.PushConstants(pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, viewport_con); - // cmdbuf.Draw(3, 1, 0, 0); - // cmdbuf.EndRenderPass(); - // TransitionImageLayout(cmdbuf, stage1_image, VK_IMAGE_LAYOUT_GENERAL); }); - //return *images.image_views[1]; return *images.image_views[0]; } diff --git a/src/video_core/renderer_vulkan/present/sgsr.h b/src/video_core/renderer_vulkan/present/sgsr.h index ca48e4998d..d6362c361d 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.h +++ b/src/video_core/renderer_vulkan/present/sgsr.h @@ -14,8 +14,8 @@ class Scheduler; class SGSR { public: - static constexpr size_t SGSR_STAGE_COUNT = 2; - explicit SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent); + static constexpr size_t SGSR_STAGE_COUNT = 1; + explicit SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent, bool edge_dir); VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect); private: void Initialize(); @@ -44,6 +44,7 @@ private: }; std::vector m_dynamic_images; bool m_images_ready{}; + bool m_edge_dir{}; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index f7c6bc0cd1..a742e4073c 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp @@ -74,6 +74,7 @@ void BlitScreen::SetWindowAdaptPass() { break; case Settings::ScalingFilter::Fsr: case Settings::ScalingFilter::Sgsr: + case Settings::ScalingFilter::SgsrEdge: case Settings::ScalingFilter::Bilinear: default: window_adapt = MakeBilinear(device, swapchain_view_format); From 54a45f736a13f38c227aff44449075c157ceca92 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 24 Jan 2026 09:01:32 +0000 Subject: [PATCH 25/37] edgedir fix --- .patch/sgsr/0001-fix-glsl.patch | 21 +++++++++++++++---- .../renderer_vulkan/present/sgsr.cpp | 3 +-- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.patch/sgsr/0001-fix-glsl.patch b/.patch/sgsr/0001-fix-glsl.patch index 37bb823572..3fd8c531a1 100644 --- a/.patch/sgsr/0001-fix-glsl.patch +++ b/.patch/sgsr/0001-fix-glsl.patch @@ -88,7 +88,7 @@ index 7074999..9e2122e 100644 float mean = (left.y+left.z+right.x+right.w)*0.25; left = left - vec4(mean); diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -index d2df646..91a8d4d 100644 +index d2df646..3e4f5cd 100644 --- a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag @@ -1,4 +1,4 @@ @@ -97,7 +97,20 @@ index d2df646..91a8d4d 100644 //============================================================================================================ // -@@ -50,7 +50,7 @@ uniform highp vec4 ViewportInfo[1]; +@@ -40,17 +40,16 @@ precision highp int; + //////////////////////// + + #if defined(UseUniformBlock) +-layout (set=0, binding = 0) uniform UniformBlock +-{ +- highp vec4 ViewportInfo[1]; ++layout( push_constant ) uniform constants { ++ highp vec4 ViewportInfo[1]; + }; +-layout(set = 0, binding = 1) uniform mediump sampler2D ps0; ++layout(set = 0, binding = 0) uniform mediump sampler2D ps0; + #else + uniform highp vec4 ViewportInfo[1]; uniform mediump sampler2D ps0; #endif @@ -106,7 +119,7 @@ index d2df646..91a8d4d 100644 layout(location=0) out vec4 out_Target0; float fastLanczos2(float x) -@@ -98,11 +98,15 @@ vec2 edgeDirection(vec4 left, vec4 right) +@@ -98,11 +97,15 @@ vec2 edgeDirection(vec4 left, vec4 right) void main() { @@ -124,7 +137,7 @@ index d2df646..91a8d4d 100644 highp float xCenter; xCenter = abs(in_TEXCOORD0.x+-0.5); -@@ -116,18 +120,21 @@ void main() +@@ -116,18 +119,21 @@ void main() highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo[0].zw)+vec2(-0.5,0.5)); highp vec2 imgCoordPixel = floor(imgCoord); highp vec2 coord = (imgCoordPixel*ViewportInfo[0].xy); diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index e4cb5dbb4c..3dda457b7f 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -41,7 +41,7 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image ? BuildShader(m_device, SGSR1_SHADER_MOBILE_EDGE_DIRECTION_FRAG_SPV) : BuildShader(m_device, SGSR1_SHADER_MOBILE_FRAG_SPV); // 2 descriptors, 2 descriptor sets per invocation - m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 2 * m_image_count, 2 * m_image_count); + m_descriptor_pool = CreateWrappedDescriptorPool(m_device, SGSR_STAGE_COUNT * m_image_count, SGSR_STAGE_COUNT * m_image_count); m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); std::vector layouts(SGSR_STAGE_COUNT, *m_descriptor_set_layout); @@ -72,7 +72,6 @@ void SGSR::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { std::vector updates; image_infos.reserve(1); updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, images.descriptor_sets[0], 0)); - updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[0], images.descriptor_sets[1], 0)); m_device.GetLogical().UpdateDescriptorSets(updates, {}); } From dabd8a65a2495652908922ee78383ee543c24507 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 24 Jan 2026 10:44:17 +0000 Subject: [PATCH 26/37] fuckyou --- src/video_core/renderer_vulkan/present/sgsr.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 3dda457b7f..07e9df4b97 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -100,10 +100,10 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ const f32 input_image_width = f32(input_image_extent.width); const f32 input_image_height = f32(input_image_extent.height); - const f32 output_image_width = f32(extent.width); - const f32 output_image_height = f32(extent.height); - const f32 viewport_x = crop_rect.left * input_image_width; - const f32 viewport_y = crop_rect.top * input_image_height; + //const f32 output_image_width = f32(extent.width); + //const f32 output_image_height = f32(extent.height); + //const f32 viewport_x = crop_rect.left * input_image_width; + //const f32 viewport_y = crop_rect.top * input_image_height; const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_image_width; const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_image_height; From caa949e7e2040421dc2fc26fbcdb75a09fa4d2d3 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 24 Jan 2026 10:53:02 +0000 Subject: [PATCH 27/37] STOP CRASHING ANDROID --- src/android/app/src/main/res/values/arrays.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 7d00dd23ad..f3a2a069e7 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -259,6 +259,7 @@ 11 12 13 + 14 From f8c972569d51f61ab2ce399f3376310d656a2d5a Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 24 Jan 2026 11:02:16 +0000 Subject: [PATCH 28/37] force ci --- src/video_core/renderer_vulkan/present/sgsr.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 07e9df4b97..1991684920 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -100,10 +100,6 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ const f32 input_image_width = f32(input_image_extent.width); const f32 input_image_height = f32(input_image_extent.height); - //const f32 output_image_width = f32(extent.width); - //const f32 output_image_height = f32(extent.height); - //const f32 viewport_x = crop_rect.left * input_image_width; - //const f32 viewport_y = crop_rect.top * input_image_height; const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_image_width; const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_image_height; From e5aeb03d981d2b182d19bd0d1d2e727fd7336315 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 24 Jan 2026 11:35:51 +0000 Subject: [PATCH 29/37] dont multiply shit randomly, just premult the texcoord to scale :) --- .patch/sgsr/0001-fix-glsl.patch | 58 ++++++------------- src/video_core/host_shaders/sgsr1_shader.vert | 6 +- .../renderer_vulkan/present/sgsr.cpp | 4 +- 3 files changed, 27 insertions(+), 41 deletions(-) diff --git a/.patch/sgsr/0001-fix-glsl.patch b/.patch/sgsr/0001-fix-glsl.patch index 3fd8c531a1..7f50bc210b 100644 --- a/.patch/sgsr/0001-fix-glsl.patch +++ b/.patch/sgsr/0001-fix-glsl.patch @@ -1,5 +1,5 @@ diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -index 7074999..9e2122e 100644 +index 7074999..c23aae4 100644 --- a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag @@ -1,4 +1,4 @@ @@ -8,7 +8,7 @@ index 7074999..9e2122e 100644 //============================================================================================================ // -@@ -34,17 +34,16 @@ precision highp int; +@@ -34,17 +34,17 @@ precision highp int; //////////////////////// #if defined(UseUniformBlock) @@ -17,6 +17,7 @@ index 7074999..9e2122e 100644 - highp vec4 ViewportInfo[1]; +layout( push_constant ) uniform constants { + highp vec4 ViewportInfo[1]; ++ highp vec2 ResizeFactor; }; -layout(set = 0, binding = 1) uniform mediump sampler2D ps0; +layout(set = 0, binding = 0) uniform mediump sampler2D ps0; @@ -30,7 +31,7 @@ index 7074999..9e2122e 100644 layout(location=0) out vec4 out_Target0; float fastLanczos2(float x) -@@ -63,15 +62,19 @@ vec2 weightY(float dx, float dy,float c, float std) +@@ -63,15 +63,15 @@ vec2 weightY(float dx, float dy,float c, float std) void main() { @@ -40,22 +41,18 @@ index 7074999..9e2122e 100644 + const int mode = OperationMode; + const float edgeThreshold = EdgeThreshold; + const float edgeSharpness = EdgeSharpness; -+ -+ vec2 full_texsize = textureSize(ps0, 0); -+ vec2 recp_texsize = 1.0 / full_texsize; -+ vec2 resize_factor = ViewportInfo[0].zw / full_texsize; vec4 color; if(mode == 1) - color.xyz = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyz; -+ color.xyz = textureLod(ps0, in_TEXCOORD0.xy * resize_factor, 0.0).xyz; ++ color.xyz = textureLod(ps0, in_TEXCOORD0.xy, 0.0).xyz; else - color.xyzw = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyzw; -+ color.xyzw = textureLod(ps0, in_TEXCOORD0.xy * resize_factor, 0.0).xyzw; ++ color.xyzw = textureLod(ps0, in_TEXCOORD0.xy, 0.0).xyzw; highp float xCenter; xCenter = abs(in_TEXCOORD0.x+-0.5); -@@ -82,21 +85,24 @@ void main() +@@ -82,21 +82,24 @@ void main() //if ( mode!=4 && xCenter*xCenter+yCenter*yCenter<=0.4 * 0.4) if ( mode!=4) { @@ -67,7 +64,7 @@ index 7074999..9e2122e 100644 - vec4 left = textureGather(ps0,coord, mode); + highp vec2 coord = imgCoordPixel * ViewportInfo[0].xy; + vec2 pl = imgCoord - imgCoordPixel; -+ vec4 left = textureGather(ps0, coord * resize_factor, mode); ++ vec4 left = textureGather(ps0, coord, mode); float edgeVote = abs(left.z - left.y) + abs(color[mode] - left.y) + abs(color[mode] - left.z) ; if(edgeVote > edgeThreshold) @@ -76,19 +73,19 @@ index 7074999..9e2122e 100644 - vec4 right = textureGather(ps0,coord + highp vec2(ViewportInfo[0].x, 0.0), mode); + highp vec2 IR_highp_vec2_0 = coord + vec2(ViewportInfo[0].x, 0.0); -+ vec4 right = textureGather(ps0, IR_highp_vec2_0 * resize_factor, mode); ++ vec4 right = textureGather(ps0, IR_highp_vec2_0, mode); vec4 upDown; - upDown.xy = textureGather(ps0,coord + highp vec2(0.0, -ViewportInfo[0].y),mode).wz; - upDown.zw = textureGather(ps0,coord+ highp vec2(0.0, ViewportInfo[0].y), mode).yx; + highp vec2 IR_highp_vec2_1 = coord + vec2(0.0, -ViewportInfo[0].y); -+ upDown.xy = textureGather(ps0, IR_highp_vec2_1 * resize_factor, mode).wz; ++ upDown.xy = textureGather(ps0, IR_highp_vec2_1, mode).wz; + highp vec2 IR_highp_vec2_2 = coord + vec2(0.0, ViewportInfo[0].y); -+ upDown.zw = textureGather(ps0, IR_highp_vec2_2 * resize_factor, mode).yx; ++ upDown.zw = textureGather(ps0, IR_highp_vec2_2, mode).yx; float mean = (left.y+left.z+right.x+right.w)*0.25; left = left - vec4(mean); diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -index d2df646..3e4f5cd 100644 +index d2df646..8b64497 100644 --- a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag @@ -1,4 +1,4 @@ @@ -97,7 +94,7 @@ index d2df646..3e4f5cd 100644 //============================================================================================================ // -@@ -40,17 +40,16 @@ precision highp int; +@@ -40,17 +40,17 @@ precision highp int; //////////////////////// #if defined(UseUniformBlock) @@ -106,6 +103,7 @@ index d2df646..3e4f5cd 100644 - highp vec4 ViewportInfo[1]; +layout( push_constant ) uniform constants { + highp vec4 ViewportInfo[1]; ++ highp vec2 ResizeFactor; }; -layout(set = 0, binding = 1) uniform mediump sampler2D ps0; +layout(set = 0, binding = 0) uniform mediump sampler2D ps0; @@ -119,32 +117,14 @@ index d2df646..3e4f5cd 100644 layout(location=0) out vec4 out_Target0; float fastLanczos2(float x) -@@ -98,11 +97,15 @@ vec2 edgeDirection(vec4 left, vec4 right) - - void main() - { -+ vec2 full_texsize = textureSize(ps0, 0); -+ vec2 recp_texsize = 1.0 / full_texsize; -+ vec2 resize_factor = ViewportInfo[0].zw / full_texsize; -+ - vec4 color; - if(OperationMode == 1) -- color.xyz = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyz; -+ color.xyz = textureLod(ps0,in_TEXCOORD0.xy * resize_factor,0.0).xyz; - else -- color.xyzw = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyzw; -+ color.xyzw = textureLod(ps0,in_TEXCOORD0.xy * resize_factor,0.0).xyzw; - - highp float xCenter; - xCenter = abs(in_TEXCOORD0.x+-0.5); -@@ -116,18 +119,21 @@ void main() +@@ -116,18 +116,21 @@ void main() highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo[0].zw)+vec2(-0.5,0.5)); highp vec2 imgCoordPixel = floor(imgCoord); highp vec2 coord = (imgCoordPixel*ViewportInfo[0].xy); - vec2 pl = (imgCoord+(-imgCoordPixel)); - vec4 left = textureGather(ps0,coord, OperationMode); + vec2 pl = imgCoord - imgCoordPixel; -+ vec4 left = textureGather(ps0, coord * resize_factor, OperationMode); ++ vec4 left = textureGather(ps0, coord, OperationMode); float edgeVote = abs(left.z - left.y) + abs(color[OperationMode] - left.y) + abs(color[OperationMode] - left.z) ; if(edgeVote > EdgeThreshold) @@ -153,14 +133,14 @@ index d2df646..3e4f5cd 100644 - vec4 right = textureGather(ps0,coord + highp vec2(ViewportInfo[0].x, 0.0), OperationMode); + highp vec2 IR_highp_vec2_0 = coord + vec2(ViewportInfo[0].x, 0.0); -+ vec4 right = textureGather(ps0, IR_highp_vec2_0 * resize_factor, OperationMode); ++ vec4 right = textureGather(ps0, IR_highp_vec2_0, OperationMode); vec4 upDown; - upDown.xy = textureGather(ps0,coord + highp vec2(0.0, -ViewportInfo[0].y),OperationMode).wz; - upDown.zw = textureGather(ps0,coord+ highp vec2(0.0, ViewportInfo[0].y), OperationMode).yx; + highp vec2 IR_highp_vec2_1 = coord + vec2(0.0, -ViewportInfo[0].y); -+ upDown.xy = textureGather(ps0, IR_highp_vec2_1 * resize_factor, OperationMode).wz; ++ upDown.xy = textureGather(ps0, IR_highp_vec2_1, OperationMode).wz; + highp vec2 IR_highp_vec2_2 = coord + vec2(0.0, ViewportInfo[0].y); -+ upDown.zw = textureGather(ps0, IR_highp_vec2_2 * resize_factor, OperationMode).yx; ++ upDown.zw = textureGather(ps0, IR_highp_vec2_2, OperationMode).yx; float mean = (left.y+left.z+right.x+right.w)*0.25; left = left - vec4(mean); diff --git a/src/video_core/host_shaders/sgsr1_shader.vert b/src/video_core/host_shaders/sgsr1_shader.vert index 00649312fb..1a07242fd6 100644 --- a/src/video_core/host_shaders/sgsr1_shader.vert +++ b/src/video_core/host_shaders/sgsr1_shader.vert @@ -3,11 +3,15 @@ #version 450 +layout( push_constant ) uniform constants { + highp vec4 ViewportInfo[1]; + highp vec2 ResizeFactor; +}; layout(location = 0) out highp vec2 texcoord; void main() { float x = float((gl_VertexIndex & 1) << 2); float y = float((gl_VertexIndex & 2) << 1); gl_Position = vec4(x - 1.0f, y - 1.0f, 0.0, 1.0f); - texcoord = vec2(x, y) / 2.0; + texcoord = vec2(x, y) * ResizeFactor * 0.5; } diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 1991684920..9442d81630 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -17,7 +17,7 @@ namespace Vulkan { -using PushConstants = std::array; +using PushConstants = std::array; SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent, bool edge_dir) : m_device{device}, m_memory_allocator{memory_allocator} @@ -110,6 +110,8 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ viewport_con[1] = std::bit_cast(1.f / viewport_height); viewport_con[2] = std::bit_cast(viewport_width); viewport_con[3] = std::bit_cast(viewport_height); + viewport_con[4] = std::bit_cast(viewport_width / input_image_width); + viewport_con[5] = std::bit_cast(viewport_height / input_image_height); UploadImages(scheduler); UpdateDescriptorSets(source_image_view, image_index); From ce09cfb0c6129d665d44c83b305fdc22f1016665 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 24 Jan 2026 18:11:55 +0000 Subject: [PATCH 30/37] allow control sharpness from [0,2.0] --- .patch/sgsr/0001-fix-glsl.patch | 86 ++++++++++++++----- .../app/src/main/res/values/strings.xml | 4 +- src/qt_common/config/shared_translation.cpp | 2 +- src/video_core/host_shaders/sgsr1_shader.vert | 1 + .../renderer_vulkan/present/sgsr.cpp | 10 ++- src/yuzu/configuration/configure_graphics.cpp | 2 +- 6 files changed, 80 insertions(+), 25 deletions(-) diff --git a/.patch/sgsr/0001-fix-glsl.patch b/.patch/sgsr/0001-fix-glsl.patch index 7f50bc210b..48f5a123f2 100644 --- a/.patch/sgsr/0001-fix-glsl.patch +++ b/.patch/sgsr/0001-fix-glsl.patch @@ -1,5 +1,5 @@ diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -index 7074999..c23aae4 100644 +index 7074999..2db04b3 100644 --- a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag @@ -1,4 +1,4 @@ @@ -8,7 +8,16 @@ index 7074999..c23aae4 100644 //============================================================================================================ // -@@ -34,17 +34,17 @@ precision highp int; +@@ -25,7 +25,7 @@ precision highp int; + + #define EdgeThreshold 8.0/255.0 + +-#define EdgeSharpness 2.0 ++// #define EdgeSharpness 2.0 + + // #define UseUniformBlock + +@@ -34,17 +34,18 @@ precision highp int; //////////////////////// #if defined(UseUniformBlock) @@ -18,6 +27,7 @@ index 7074999..c23aae4 100644 +layout( push_constant ) uniform constants { + highp vec4 ViewportInfo[1]; + highp vec2 ResizeFactor; ++ highp float EdgeSharpness; }; -layout(set = 0, binding = 1) uniform mediump sampler2D ps0; +layout(set = 0, binding = 0) uniform mediump sampler2D ps0; @@ -31,20 +41,18 @@ index 7074999..c23aae4 100644 layout(location=0) out vec4 out_Target0; float fastLanczos2(float x) -@@ -63,15 +63,15 @@ vec2 weightY(float dx, float dy,float c, float std) +@@ -63,15 +64,11 @@ vec2 weightY(float dx, float dy,float c, float std) void main() { - int mode = OperationMode; - float edgeThreshold = EdgeThreshold; - float edgeSharpness = EdgeSharpness; -+ const int mode = OperationMode; -+ const float edgeThreshold = EdgeThreshold; -+ const float edgeSharpness = EdgeSharpness; - +- vec4 color; - if(mode == 1) +- if(mode == 1) - color.xyz = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyz; ++ if(OperationMode == 1) + color.xyz = textureLod(ps0, in_TEXCOORD0.xy, 0.0).xyz; else - color.xyzw = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyzw; @@ -52,9 +60,14 @@ index 7074999..c23aae4 100644 highp float xCenter; xCenter = abs(in_TEXCOORD0.x+-0.5); -@@ -82,21 +82,24 @@ void main() - //if ( mode!=4 && xCenter*xCenter+yCenter*yCenter<=0.4 * 0.4) - if ( mode!=4) +@@ -79,30 +76,33 @@ void main() + yCenter = abs(in_TEXCOORD0.y+-0.5); + + //todo: config the SR region based on needs +- //if ( mode!=4 && xCenter*xCenter+yCenter*yCenter<=0.4 * 0.4) +- if ( mode!=4) ++ //if ( OperationMode!=4 && xCenter*xCenter+yCenter*yCenter<=0.4 * 0.4) ++ if ( OperationMode!=4) { - highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo[0].zw)+vec2(-0.5,0.5)); + highp vec2 imgCoord = ((in_TEXCOORD0.xy * ViewportInfo[0].zw) + vec2(-0.5,0.5)); @@ -64,28 +77,46 @@ index 7074999..c23aae4 100644 - vec4 left = textureGather(ps0,coord, mode); + highp vec2 coord = imgCoordPixel * ViewportInfo[0].xy; + vec2 pl = imgCoord - imgCoordPixel; -+ vec4 left = textureGather(ps0, coord, mode); ++ vec4 left = textureGather(ps0, coord, OperationMode); - float edgeVote = abs(left.z - left.y) + abs(color[mode] - left.y) + abs(color[mode] - left.z) ; - if(edgeVote > edgeThreshold) +- float edgeVote = abs(left.z - left.y) + abs(color[mode] - left.y) + abs(color[mode] - left.z) ; +- if(edgeVote > edgeThreshold) ++ float edgeVote = abs(left.z - left.y) + abs(color[OperationMode] - left.y) + abs(color[OperationMode] - left.z) ; ++ if(edgeVote > EdgeThreshold) { coord.x += ViewportInfo[0].x; - vec4 right = textureGather(ps0,coord + highp vec2(ViewportInfo[0].x, 0.0), mode); + highp vec2 IR_highp_vec2_0 = coord + vec2(ViewportInfo[0].x, 0.0); -+ vec4 right = textureGather(ps0, IR_highp_vec2_0, mode); ++ vec4 right = textureGather(ps0, IR_highp_vec2_0, OperationMode); vec4 upDown; - upDown.xy = textureGather(ps0,coord + highp vec2(0.0, -ViewportInfo[0].y),mode).wz; - upDown.zw = textureGather(ps0,coord+ highp vec2(0.0, ViewportInfo[0].y), mode).yx; + highp vec2 IR_highp_vec2_1 = coord + vec2(0.0, -ViewportInfo[0].y); -+ upDown.xy = textureGather(ps0, IR_highp_vec2_1, mode).wz; ++ upDown.xy = textureGather(ps0, IR_highp_vec2_1, OperationMode).wz; + highp vec2 IR_highp_vec2_2 = coord + vec2(0.0, ViewportInfo[0].y); -+ upDown.zw = textureGather(ps0, IR_highp_vec2_2, mode).yx; ++ upDown.zw = textureGather(ps0, IR_highp_vec2_2, OperationMode).yx; float mean = (left.y+left.z+right.x+right.w)*0.25; left = left - vec4(mean); + right = right - vec4(mean); + upDown = upDown - vec4(mean); +- color.w =color[mode] - mean; ++ color.w =color[OperationMode] - mean; + + float sum = (((((abs(left.x)+abs(left.y))+abs(left.z))+abs(left.w))+(((abs(right.x)+abs(right.y))+abs(right.z))+abs(right.w)))+(((abs(upDown.x)+abs(upDown.y))+abs(upDown.z))+abs(upDown.w))); + float std = 2.181818/sum; +@@ -124,7 +124,7 @@ void main() + + float maxY = max(max(left.y,left.z),max(right.x,right.w)); + float minY = min(min(left.y,left.z),min(right.x,right.w)); +- finalY = clamp(edgeSharpness*finalY, minY, maxY); ++ finalY = clamp(EdgeSharpness*finalY, minY, maxY); + + float deltaY = finalY -color.w; + diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -index d2df646..8b64497 100644 +index d2df646..5a38589 100644 --- a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag @@ -1,4 +1,4 @@ @@ -94,7 +125,21 @@ index d2df646..8b64497 100644 //============================================================================================================ // -@@ -40,17 +40,17 @@ precision highp int; +@@ -27,11 +27,11 @@ precision highp int; + * If set, will use edge direction to improve visual quality + * Expect a minimal cost increase + */ +-// #define UseEdgeDirection ++#define UseEdgeDirection 1 + + #define EdgeThreshold 8.0/255.0 + +-#define EdgeSharpness 2.0 ++// #define EdgeSharpness 2.0 + + // #define UseUniformBlock + +@@ -40,17 +40,18 @@ precision highp int; //////////////////////// #if defined(UseUniformBlock) @@ -104,6 +149,7 @@ index d2df646..8b64497 100644 +layout( push_constant ) uniform constants { + highp vec4 ViewportInfo[1]; + highp vec2 ResizeFactor; ++ highp float EdgeSharpness; }; -layout(set = 0, binding = 1) uniform mediump sampler2D ps0; +layout(set = 0, binding = 0) uniform mediump sampler2D ps0; @@ -117,7 +163,7 @@ index d2df646..8b64497 100644 layout(location=0) out vec4 out_Target0; float fastLanczos2(float x) -@@ -116,18 +116,21 @@ void main() +@@ -116,18 +117,21 @@ void main() highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo[0].zw)+vec2(-0.5,0.5)); highp vec2 imgCoordPixel = floor(imgCoord); highp vec2 coord = (imgCoordPixel*ViewportInfo[0].xy); diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 0188fd4b3d..42cdf91380 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -466,8 +466,8 @@ Resolution (Handheld/Docked) VSync mode Window adapting filter - FSR sharpness - Determines how sharpened the image will look while using FSR\'s dynamic contrast + FSR/SGSR sharpness + Determines how sharpened the image will look while using FSR or SGSR filters Anti-aliasing method Optimize SPIRV output Optimizes compiled shaders to improve GPU efficiency, but may introduce longer loading times and initial slowdowns. diff --git a/src/qt_common/config/shared_translation.cpp b/src/qt_common/config/shared_translation.cpp index ca74f8d3cc..ed998aee41 100644 --- a/src/qt_common/config/shared_translation.cpp +++ b/src/qt_common/config/shared_translation.cpp @@ -149,7 +149,7 @@ std::unique_ptr InitializeTranslations(QObject* parent) { "Options lower than 1X can cause artifacts.")); INSERT(Settings, scaling_filter, tr("Window Adapting Filter:"), QString()); INSERT(Settings, fsr_sharpening_slider, tr("FSR Sharpness:"), - tr("Determines how sharpened the image will look using FSR's dynamic contrast.")); + tr("Determines how sharpened the image will look using FSR's or SGSR's dynamic contrast.")); INSERT(Settings, anti_aliasing, tr("Anti-Aliasing Method:"), tr("The anti-aliasing method to use.\nSMAA offers the best quality.\nFXAA " "can produce a more stable picture in lower resolutions.")); diff --git a/src/video_core/host_shaders/sgsr1_shader.vert b/src/video_core/host_shaders/sgsr1_shader.vert index 1a07242fd6..820beb26de 100644 --- a/src/video_core/host_shaders/sgsr1_shader.vert +++ b/src/video_core/host_shaders/sgsr1_shader.vert @@ -6,6 +6,7 @@ layout( push_constant ) uniform constants { highp vec4 ViewportInfo[1]; highp vec2 ResizeFactor; + highp float EdgeSharpness; }; layout(location = 0) out highp vec2 texcoord; diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 9442d81630..72d28f5e5c 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -17,7 +17,7 @@ namespace Vulkan { -using PushConstants = std::array; +using PushConstants = std::array; SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent, bool edge_dir) : m_device{device}, m_memory_allocator{memory_allocator} @@ -102,9 +102,16 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ const f32 input_image_height = f32(input_image_extent.height); const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_image_width; const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_image_height; + // expected [0, 2] + const f32 sharpening = f32(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f; // p = (tex * viewport) / input = [0,n] (normalized texcoords) // p * input = [0,1024], [0,768] + // layout( push_constant ) uniform constants { + // highp vec4 ViewportInfo[1]; + // highp vec2 ResizeFactor; + // highp float EdgeSharpness; + // }; PushConstants viewport_con{}; viewport_con[0] = std::bit_cast(1.f / viewport_width); viewport_con[1] = std::bit_cast(1.f / viewport_height); @@ -112,6 +119,7 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ viewport_con[3] = std::bit_cast(viewport_height); viewport_con[4] = std::bit_cast(viewport_width / input_image_width); viewport_con[5] = std::bit_cast(viewport_height / input_image_height); + viewport_con[6] = std::bit_cast(sharpening); UploadImages(scheduler); UpdateDescriptorSets(source_image_view, image_index); diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 54835aea5a..6ae71d2368 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -265,7 +265,7 @@ void ConfigureGraphics::Setup(const ConfigurationShared::Builder& builder) { // FSR needs a reversed slider and a 0.5 multiplier return builder.BuildWidget( setting, apply_funcs, ConfigurationShared::RequestType::ReverseSlider, true, - 0.5f, nullptr, tr("%", "FSR sharpening percentage (e.g. 50%)")); + 0.5f, nullptr, tr("%", "FSR/SGSR sharpening percentage (e.g. 50%)")); } else { return builder.BuildWidget(setting, apply_funcs); } From ee534cb9fb6be814ca43eb7f7e6e965fb26f4ad4 Mon Sep 17 00:00:00 2001 From: lizzie Date: Fri, 6 Feb 2026 01:58:59 +0000 Subject: [PATCH 31/37] fix cmake 2 --- cpmfile.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cpmfile.json b/cpmfile.json index b9a1110106..4af85428ea 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -102,13 +102,12 @@ "artifact": "android-binaries-%VERSION%.zip", "hash": "8812ae84cbe49e6a3418ade9c458d3be6d74a3dffd319d4502007b564d580998056e8190414368ec11b27bc83993c7a0dad713c31bcc3d9553b51243efee3753" }, - "snapdragon_gsr": { + "sgsr": { "repo": "SnapdragonStudios/snapdragon-gsr", - "package": "snapdragon_gsr", - "hash": "dsfsdfsd", + "hash": "3940df715189813ffeffa540f48673e999754d53a1dcadc16aab846ef03d57e395e2c8d8e89772bc162835e1686ff6bdb8cae108c1f84404e9e66d993107b76e", "sha": "d926f074bcb9d714e179f1ce0fcb9ee2eeb5074e", "patches": [ - "0001-glslang-fix.patch" + "0001-fix-glsl.patch" ] }, "quazip": { From d20b9a9acc4856d87556a4895b8b9f77c0f5d7f8 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sun, 8 Feb 2026 23:56:46 -0400 Subject: [PATCH 32/37] [vulkan, sgsr] Added missing stage bit --- src/video_core/renderer_vulkan/present/sgsr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 72d28f5e5c..080b5247fa 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -49,7 +49,7 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layouts); const VkPushConstantRange range{ - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, .offset = 0, .size = sizeof(PushConstants), }; From cd02b9f37511169429efda490e58cebddb4d01e8 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Mon, 9 Feb 2026 00:25:29 -0400 Subject: [PATCH 33/37] [vulkan, sgsr] Adjusting vkCmdPushConstant to receive vertex and fragment stages --- src/video_core/renderer_vulkan/present/sgsr.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 080b5247fa..3589083f00 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -131,7 +131,9 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ BeginRenderPass(cmdbuf, renderpass, stage0_framebuffer, extent); cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, stage0_pipeline); cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, stage0_descriptor_set, {}); - cmdbuf.PushConstants(pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, viewport_con); + cmdbuf.PushConstants(pipeline_layout, + VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, + viewport_con); cmdbuf.Draw(3, 1, 0, 0); cmdbuf.EndRenderPass(); TransitionImageLayout(cmdbuf, stage0_image, VK_IMAGE_LAYOUT_GENERAL); From be689d15793c75f4e1a0d1aacfadd9eadba73f85 Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 9 Feb 2026 05:26:50 +0000 Subject: [PATCH 34/37] fx --- src/video_core/host_shaders/CMakeLists.txt | 33 +--------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index f2b4846db8..88dce53b10 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -150,42 +150,11 @@ foreach(SOURCE_FILE IN ITEMS ${SHADER_FILES}) OUTPUT ${SPIRV_HEADER_FILE} COMMAND - ${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -DUseUniformBlock=1 ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} --target-env ${SPIR_V_VERSION} + ${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -I"${FIDELITYFX_INCLUDE_DIR}" ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} --target-env ${SPIR_V_VERSION} MAIN_DEPENDENCY ${SOURCE_FILE} ) set(SHADER_HEADERS ${SHADER_HEADERS} ${SPIRV_HEADER_FILE}) - else() - # Skip generating source headers on Vulkan exclusive files - if (NOT ${FILENAME} MATCHES "vulkan.*" AND NOT ${FILENAME} MATCHES "sgsr1.*") - set(SOURCE_HEADER_FILE ${SHADER_DIR}/${SHADER_NAME}.h) - add_custom_command( - OUTPUT - ${SOURCE_HEADER_FILE} - COMMAND - ${CMAKE_COMMAND} -P ${HEADER_GENERATOR} ${SOURCE_FILE} ${SOURCE_HEADER_FILE} ${INPUT_FILE} - MAIN_DEPENDENCY - ${SOURCE_FILE} - DEPENDS - ${INPUT_FILE} - # HEADER_GENERATOR should be included here but msbuild seems to assume it's always modified - ) - set(SHADER_HEADERS ${SHADER_HEADERS} ${SOURCE_HEADER_FILE}) - endif() - # Skip compiling to SPIR-V OpenGL exclusive files - if (NOT ${FILENAME} MATCHES "opengl.*") - string(TOUPPER ${SHADER_NAME}_SPV SPIRV_VARIABLE_NAME) - set(SPIRV_HEADER_FILE ${SHADER_DIR}/${SHADER_NAME}_spv.h) - add_custom_command( - OUTPUT - ${SPIRV_HEADER_FILE} - COMMAND - ${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -I"${FIDELITYFX_INCLUDE_DIR}" ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} --target-env ${SPIR_V_VERSION} - MAIN_DEPENDENCY - ${SOURCE_FILE} - ) - set(SHADER_HEADERS ${SHADER_HEADERS} ${SPIRV_HEADER_FILE}) - endif() endif() endforeach() From 443c64d7cb78e814f87e919ed4ae3d2acf16c952 Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 9 Feb 2026 05:31:01 +0000 Subject: [PATCH 35/37] fx2 --- src/video_core/host_shaders/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 88dce53b10..310baf118d 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -95,7 +95,7 @@ if ("${GLSLANGVALIDATOR}" STREQUAL "GLSLANGVALIDATOR-NOTFOUND") message(FATAL_ERROR "Required program `glslangValidator` not found.") endif() -set(GLSL_FLAGS "") +set(GLSL_FLAGS "-DUseUniformBlock=1") set(SPIR_V_VERSION "spirv1.3") set(QUIET_FLAG "--quiet") From 0a5395b61c4d47f9d995479a6102a63e795f3efa Mon Sep 17 00:00:00 2001 From: lizzie Date: Thu, 5 Mar 2026 06:52:08 +0000 Subject: [PATCH 36/37] remove highp --- .patch/sgsr/0002-remove-highp.patch | 34 +++++++++++++++++++++++++++++ cpmfile.json | 3 ++- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 .patch/sgsr/0002-remove-highp.patch diff --git a/.patch/sgsr/0002-remove-highp.patch b/.patch/sgsr/0002-remove-highp.patch new file mode 100644 index 0000000000..9d6b65b6be --- /dev/null +++ b/.patch/sgsr/0002-remove-highp.patch @@ -0,0 +1,34 @@ +diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +index 2db04b3..056d177 100644 +--- a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag ++++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag +@@ -8,8 +8,10 @@ + // + //============================================================================================================ + +-precision mediump float; +-precision highp int; ++//precision mediump float; ++//precision highp int; ++#define highp ++#define mediump + + //////////////////////// + // USER CONFIGURATION // +diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +index 5a38589..5ed5f5e 100644 +--- a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag ++++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag +@@ -8,8 +8,10 @@ + // + //============================================================================================================ + +-precision mediump float; +-precision highp int; ++//precision mediump float; ++//precision highp int; ++#define highp ++#define mediump + + //////////////////////// + // USER CONFIGURATION // diff --git a/cpmfile.json b/cpmfile.json index 4af85428ea..babcf765ec 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -107,7 +107,8 @@ "hash": "3940df715189813ffeffa540f48673e999754d53a1dcadc16aab846ef03d57e395e2c8d8e89772bc162835e1686ff6bdb8cae108c1f84404e9e66d993107b76e", "sha": "d926f074bcb9d714e179f1ce0fcb9ee2eeb5074e", "patches": [ - "0001-fix-glsl.patch" + "0001-fix-glsl.patch", + "0002-remove-highp.patch" ] }, "quazip": { From d619b851f7ed10fcbb7e4b76d7ca809b75ca72a2 Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 30 Mar 2026 07:39:00 +0000 Subject: [PATCH 37/37] move in tree, remove sgsr dep --- .patch/sgsr/0001-fix-glsl.patch | 192 ------------------ .patch/sgsr/0002-remove-highp.patch | 34 ---- CMakeLists.txt | 2 - cpmfile.json | 9 - src/video_core/host_shaders/CMakeLists.txt | 5 +- .../host_shaders/sgsr1_shader_mobile.frag | 116 +++++++++++ .../sgsr1_shader_mobile_edge_direction.frag | 149 ++++++++++++++ 7 files changed, 267 insertions(+), 240 deletions(-) delete mode 100644 .patch/sgsr/0001-fix-glsl.patch delete mode 100644 .patch/sgsr/0002-remove-highp.patch create mode 100644 src/video_core/host_shaders/sgsr1_shader_mobile.frag create mode 100644 src/video_core/host_shaders/sgsr1_shader_mobile_edge_direction.frag diff --git a/.patch/sgsr/0001-fix-glsl.patch b/.patch/sgsr/0001-fix-glsl.patch deleted file mode 100644 index 48f5a123f2..0000000000 --- a/.patch/sgsr/0001-fix-glsl.patch +++ /dev/null @@ -1,192 +0,0 @@ -diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -index 7074999..2db04b3 100644 ---- a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -+++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -@@ -1,4 +1,4 @@ --#version 300 es -+#version 460 core - - //============================================================================================================ - // -@@ -25,7 +25,7 @@ precision highp int; - - #define EdgeThreshold 8.0/255.0 - --#define EdgeSharpness 2.0 -+// #define EdgeSharpness 2.0 - - // #define UseUniformBlock - -@@ -34,17 +34,18 @@ precision highp int; - //////////////////////// - - #if defined(UseUniformBlock) --layout (set=0, binding = 0) uniform UniformBlock --{ -- highp vec4 ViewportInfo[1]; -+layout( push_constant ) uniform constants { -+ highp vec4 ViewportInfo[1]; -+ highp vec2 ResizeFactor; -+ highp float EdgeSharpness; - }; --layout(set = 0, binding = 1) uniform mediump sampler2D ps0; -+layout(set = 0, binding = 0) uniform mediump sampler2D ps0; - #else - uniform highp vec4 ViewportInfo[1]; - uniform mediump sampler2D ps0; - #endif - --layout(location=0) in highp vec4 in_TEXCOORD0; -+layout(location=0) in highp vec2 in_TEXCOORD0; - layout(location=0) out vec4 out_Target0; - - float fastLanczos2(float x) -@@ -63,15 +64,11 @@ vec2 weightY(float dx, float dy,float c, float std) - - void main() - { -- int mode = OperationMode; -- float edgeThreshold = EdgeThreshold; -- float edgeSharpness = EdgeSharpness; -- - vec4 color; -- if(mode == 1) -- color.xyz = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyz; -+ if(OperationMode == 1) -+ color.xyz = textureLod(ps0, in_TEXCOORD0.xy, 0.0).xyz; - else -- color.xyzw = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyzw; -+ color.xyzw = textureLod(ps0, in_TEXCOORD0.xy, 0.0).xyzw; - - highp float xCenter; - xCenter = abs(in_TEXCOORD0.x+-0.5); -@@ -79,30 +76,33 @@ void main() - yCenter = abs(in_TEXCOORD0.y+-0.5); - - //todo: config the SR region based on needs -- //if ( mode!=4 && xCenter*xCenter+yCenter*yCenter<=0.4 * 0.4) -- if ( mode!=4) -+ //if ( OperationMode!=4 && xCenter*xCenter+yCenter*yCenter<=0.4 * 0.4) -+ if ( OperationMode!=4) - { -- highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo[0].zw)+vec2(-0.5,0.5)); -+ highp vec2 imgCoord = ((in_TEXCOORD0.xy * ViewportInfo[0].zw) + vec2(-0.5,0.5)); - highp vec2 imgCoordPixel = floor(imgCoord); -- highp vec2 coord = (imgCoordPixel*ViewportInfo[0].xy); -- vec2 pl = (imgCoord+(-imgCoordPixel)); -- vec4 left = textureGather(ps0,coord, mode); -+ highp vec2 coord = imgCoordPixel * ViewportInfo[0].xy; -+ vec2 pl = imgCoord - imgCoordPixel; -+ vec4 left = textureGather(ps0, coord, OperationMode); - -- float edgeVote = abs(left.z - left.y) + abs(color[mode] - left.y) + abs(color[mode] - left.z) ; -- if(edgeVote > edgeThreshold) -+ float edgeVote = abs(left.z - left.y) + abs(color[OperationMode] - left.y) + abs(color[OperationMode] - left.z) ; -+ if(edgeVote > EdgeThreshold) - { - coord.x += ViewportInfo[0].x; - -- vec4 right = textureGather(ps0,coord + highp vec2(ViewportInfo[0].x, 0.0), mode); -+ highp vec2 IR_highp_vec2_0 = coord + vec2(ViewportInfo[0].x, 0.0); -+ vec4 right = textureGather(ps0, IR_highp_vec2_0, OperationMode); - vec4 upDown; -- upDown.xy = textureGather(ps0,coord + highp vec2(0.0, -ViewportInfo[0].y),mode).wz; -- upDown.zw = textureGather(ps0,coord+ highp vec2(0.0, ViewportInfo[0].y), mode).yx; -+ highp vec2 IR_highp_vec2_1 = coord + vec2(0.0, -ViewportInfo[0].y); -+ upDown.xy = textureGather(ps0, IR_highp_vec2_1, OperationMode).wz; -+ highp vec2 IR_highp_vec2_2 = coord + vec2(0.0, ViewportInfo[0].y); -+ upDown.zw = textureGather(ps0, IR_highp_vec2_2, OperationMode).yx; - - float mean = (left.y+left.z+right.x+right.w)*0.25; - left = left - vec4(mean); - right = right - vec4(mean); - upDown = upDown - vec4(mean); -- color.w =color[mode] - mean; -+ color.w =color[OperationMode] - mean; - - float sum = (((((abs(left.x)+abs(left.y))+abs(left.z))+abs(left.w))+(((abs(right.x)+abs(right.y))+abs(right.z))+abs(right.w)))+(((abs(upDown.x)+abs(upDown.y))+abs(upDown.z))+abs(upDown.w))); - float std = 2.181818/sum; -@@ -124,7 +124,7 @@ void main() - - float maxY = max(max(left.y,left.z),max(right.x,right.w)); - float minY = min(min(left.y,left.z),min(right.x,right.w)); -- finalY = clamp(edgeSharpness*finalY, minY, maxY); -+ finalY = clamp(EdgeSharpness*finalY, minY, maxY); - - float deltaY = finalY -color.w; - -diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -index d2df646..5a38589 100644 ---- a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -+++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -@@ -1,4 +1,4 @@ --#version 300 es -+#version 460 core - - //============================================================================================================ - // -@@ -27,11 +27,11 @@ precision highp int; - * If set, will use edge direction to improve visual quality - * Expect a minimal cost increase - */ --// #define UseEdgeDirection -+#define UseEdgeDirection 1 - - #define EdgeThreshold 8.0/255.0 - --#define EdgeSharpness 2.0 -+// #define EdgeSharpness 2.0 - - // #define UseUniformBlock - -@@ -40,17 +40,18 @@ precision highp int; - //////////////////////// - - #if defined(UseUniformBlock) --layout (set=0, binding = 0) uniform UniformBlock --{ -- highp vec4 ViewportInfo[1]; -+layout( push_constant ) uniform constants { -+ highp vec4 ViewportInfo[1]; -+ highp vec2 ResizeFactor; -+ highp float EdgeSharpness; - }; --layout(set = 0, binding = 1) uniform mediump sampler2D ps0; -+layout(set = 0, binding = 0) uniform mediump sampler2D ps0; - #else - uniform highp vec4 ViewportInfo[1]; - uniform mediump sampler2D ps0; - #endif - --layout(location=0) in highp vec4 in_TEXCOORD0; -+layout(location=0) in highp vec2 in_TEXCOORD0; - layout(location=0) out vec4 out_Target0; - - float fastLanczos2(float x) -@@ -116,18 +117,21 @@ void main() - highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo[0].zw)+vec2(-0.5,0.5)); - highp vec2 imgCoordPixel = floor(imgCoord); - highp vec2 coord = (imgCoordPixel*ViewportInfo[0].xy); -- vec2 pl = (imgCoord+(-imgCoordPixel)); -- vec4 left = textureGather(ps0,coord, OperationMode); -+ vec2 pl = imgCoord - imgCoordPixel; -+ vec4 left = textureGather(ps0, coord, OperationMode); - - float edgeVote = abs(left.z - left.y) + abs(color[OperationMode] - left.y) + abs(color[OperationMode] - left.z) ; - if(edgeVote > EdgeThreshold) - { - coord.x += ViewportInfo[0].x; - -- vec4 right = textureGather(ps0,coord + highp vec2(ViewportInfo[0].x, 0.0), OperationMode); -+ highp vec2 IR_highp_vec2_0 = coord + vec2(ViewportInfo[0].x, 0.0); -+ vec4 right = textureGather(ps0, IR_highp_vec2_0, OperationMode); - vec4 upDown; -- upDown.xy = textureGather(ps0,coord + highp vec2(0.0, -ViewportInfo[0].y),OperationMode).wz; -- upDown.zw = textureGather(ps0,coord+ highp vec2(0.0, ViewportInfo[0].y), OperationMode).yx; -+ highp vec2 IR_highp_vec2_1 = coord + vec2(0.0, -ViewportInfo[0].y); -+ upDown.xy = textureGather(ps0, IR_highp_vec2_1, OperationMode).wz; -+ highp vec2 IR_highp_vec2_2 = coord + vec2(0.0, ViewportInfo[0].y); -+ upDown.zw = textureGather(ps0, IR_highp_vec2_2, OperationMode).yx; - - float mean = (left.y+left.z+right.x+right.w)*0.25; - left = left - vec4(mean); diff --git a/.patch/sgsr/0002-remove-highp.patch b/.patch/sgsr/0002-remove-highp.patch deleted file mode 100644 index 9d6b65b6be..0000000000 --- a/.patch/sgsr/0002-remove-highp.patch +++ /dev/null @@ -1,34 +0,0 @@ -diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -index 2db04b3..056d177 100644 ---- a/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -+++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag -@@ -8,8 +8,10 @@ - // - //============================================================================================================ - --precision mediump float; --precision highp int; -+//precision mediump float; -+//precision highp int; -+#define highp -+#define mediump - - //////////////////////// - // USER CONFIGURATION // -diff --git a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -index 5a38589..5ed5f5e 100644 ---- a/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -+++ b/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag -@@ -8,8 +8,10 @@ - // - //============================================================================================================ - --precision mediump float; --precision highp int; -+//precision mediump float; -+//precision highp int; -+#define highp -+#define mediump - - //////////////////////// - // USER CONFIGURATION // diff --git a/CMakeLists.txt b/CMakeLists.txt index 75f02b5d09..6cdb79be4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -233,8 +233,6 @@ endif() option(YUZU_USE_BUNDLED_OPENSSL "Download bundled OpenSSL build" ${DEFAULT_YUZU_USE_BUNDLED_OPENSSL}) -AddJsonPackage(sgsr) - # TODO(crueter): CPM this if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL) AddJsonPackage(vulkan-validation-layers) diff --git a/cpmfile.json b/cpmfile.json index babcf765ec..1bb29afae4 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -102,15 +102,6 @@ "artifact": "android-binaries-%VERSION%.zip", "hash": "8812ae84cbe49e6a3418ade9c458d3be6d74a3dffd319d4502007b564d580998056e8190414368ec11b27bc83993c7a0dad713c31bcc3d9553b51243efee3753" }, - "sgsr": { - "repo": "SnapdragonStudios/snapdragon-gsr", - "hash": "3940df715189813ffeffa540f48673e999754d53a1dcadc16aab846ef03d57e395e2c8d8e89772bc162835e1686ff6bdb8cae108c1f84404e9e66d993107b76e", - "sha": "d926f074bcb9d714e179f1ce0fcb9ee2eeb5074e", - "patches": [ - "0001-fix-glsl.patch", - "0002-remove-highp.patch" - ] - }, "quazip": { "package": "QuaZip-Qt6", "repo": "stachenov/quazip", diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 310baf118d..9e8d76b104 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -79,8 +79,8 @@ set(SHADER_FILES # Snapdragon Game Super Resolution ${CMAKE_CURRENT_SOURCE_DIR}/sgsr1_shader.vert - ${sgsr_SOURCE_DIR}/sgsr/v1/include/glsl/sgsr1_shader_mobile.frag - ${sgsr_SOURCE_DIR}/sgsr/v1/include/glsl/sgsr1_shader_mobile_edge_direction.frag + ${CMAKE_CURRENT_SOURCE_DIR}/sgsr1_shader_mobile.frag + ${CMAKE_CURRENT_SOURCE_DIR}/sgsr1_shader_mobile_edge_direction.frag ) if (PLATFORM_HAIKU) @@ -186,4 +186,3 @@ add_custom_target(host_shaders SOURCES ${SHADER_SOURCES} ) -#add_dependencies(host_shaders sgsr::sgsr) diff --git a/src/video_core/host_shaders/sgsr1_shader_mobile.frag b/src/video_core/host_shaders/sgsr1_shader_mobile.frag new file mode 100644 index 0000000000..a03144f606 --- /dev/null +++ b/src/video_core/host_shaders/sgsr1_shader_mobile.frag @@ -0,0 +1,116 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause + +#version 460 core + +//precision mediump float; +//precision highp int; +#define highp +#define mediump + +// Operation modes: RGBA -> 1, RGBY -> 3, LERP -> 4 +#define OperationMode 1 +#define EdgeThreshold 8.0/255.0 +// #define EdgeSharpness 2.0 +// #define UseUniformBlock + +#if defined(UseUniformBlock) +layout( push_constant ) uniform constants { + highp vec4 ViewportInfo[1]; + highp vec2 ResizeFactor; + highp float EdgeSharpness; +}; +layout(set = 0, binding = 0) uniform mediump sampler2D ps0; +#else +uniform highp vec4 ViewportInfo[1]; +uniform mediump sampler2D ps0; +#endif + +layout(location=0) in highp vec2 in_TEXCOORD0; +layout(location=0) out vec4 out_Target0; + +float fastLanczos2(float x) { + float wA = x-4.0; + float wB = x*wA-wA; + wA *= wA; + return wB*wA; +} + +vec2 weightY(float dx, float dy,float c, float std) { + float x = ((dx*dx)+(dy* dy))* 0.55 + clamp(abs(c)*std, 0.0, 1.0); + float w = fastLanczos2(x); + return vec2(w, w * c); +} + +void main() { + vec4 color; + if(OperationMode == 1) + color.xyz = textureLod(ps0, in_TEXCOORD0.xy, 0.0).xyz; + else + color.xyzw = textureLod(ps0, in_TEXCOORD0.xy, 0.0).xyzw; + + highp float xCenter = abs(in_TEXCOORD0.x + -0.5); + highp float yCenter = abs(in_TEXCOORD0.y + -0.5); + + //todo: config the SR region based on needs + //if ( OperationMode!=4 && xCenter*xCenter+yCenter*yCenter<=0.4 * 0.4) + if ( OperationMode!=4) { + highp vec2 imgCoord = ((in_TEXCOORD0.xy * ViewportInfo[0].zw) + vec2(-0.5, 0.5)); + highp vec2 imgCoordPixel = floor(imgCoord); + highp vec2 coord = imgCoordPixel * ViewportInfo[0].xy; + vec2 pl = imgCoord - imgCoordPixel; + vec4 left = textureGather(ps0, coord, OperationMode); + float edgeVote = abs(left.z - left.y) + abs(color[OperationMode] - left.y) + abs(color[OperationMode] - left.z) ; + if(edgeVote > EdgeThreshold) { + coord.x += ViewportInfo[0].x; + + highp vec2 IR_highp_vec2_0 = coord + vec2(ViewportInfo[0].x, 0.0); + vec4 right = textureGather(ps0, IR_highp_vec2_0, OperationMode); + vec4 upDown; + highp vec2 IR_highp_vec2_1 = coord + vec2(0.0, -ViewportInfo[0].y); + upDown.xy = textureGather(ps0, IR_highp_vec2_1, OperationMode).wz; + highp vec2 IR_highp_vec2_2 = coord + vec2(0.0, ViewportInfo[0].y); + upDown.zw = textureGather(ps0, IR_highp_vec2_2, OperationMode).yx; + + float mean = (left.y+left.z+right.x+right.w)*0.25; + left = left - vec4(mean); + right = right - vec4(mean); + upDown = upDown - vec4(mean); + color.w =color[OperationMode] - mean; + + float sum = (((((abs(left.x)+abs(left.y))+abs(left.z))+abs(left.w))+(((abs(right.x)+abs(right.y))+abs(right.z))+abs(right.w)))+(((abs(upDown.x)+abs(upDown.y))+abs(upDown.z))+abs(upDown.w))); + float std = 2.181818/sum; + + vec2 aWY = weightY(pl.x, pl.y+1.0, upDown.x,std); + aWY += weightY(pl.x-1.0, pl.y+1.0, upDown.y,std); + aWY += weightY(pl.x-1.0, pl.y-2.0, upDown.z,std); + aWY += weightY(pl.x, pl.y-2.0, upDown.w,std); + aWY += weightY(pl.x+1.0, pl.y-1.0, left.x,std); + aWY += weightY(pl.x, pl.y-1.0, left.y,std); + aWY += weightY(pl.x, pl.y, left.z,std); + aWY += weightY(pl.x+1.0, pl.y, left.w,std); + aWY += weightY(pl.x-1.0, pl.y-1.0, right.x,std); + aWY += weightY(pl.x-2.0, pl.y-1.0, right.y,std); + aWY += weightY(pl.x-2.0, pl.y, right.z,std); + aWY += weightY(pl.x-1.0, pl.y, right.w,std); + + float finalY = aWY.y/aWY.x; + + float maxY = max(max(left.y,left.z),max(right.x,right.w)); + float minY = min(min(left.y,left.z),min(right.x,right.w)); + finalY = clamp(EdgeSharpness*finalY, minY, maxY); + + float deltaY = finalY -color.w; + + //smooth high contrast input + deltaY = clamp(deltaY, -23.0 / 255.0, 23.0 / 255.0); + + color.x = clamp((color.x+deltaY),0.0,1.0); + color.y = clamp((color.y+deltaY),0.0,1.0); + color.z = clamp((color.z+deltaY),0.0,1.0); + } + } + + color.w = 1.0; //assume alpha channel is not used + out_Target0.xyzw = color; +} \ No newline at end of file diff --git a/src/video_core/host_shaders/sgsr1_shader_mobile_edge_direction.frag b/src/video_core/host_shaders/sgsr1_shader_mobile_edge_direction.frag new file mode 100644 index 0000000000..686e39a6d0 --- /dev/null +++ b/src/video_core/host_shaders/sgsr1_shader_mobile_edge_direction.frag @@ -0,0 +1,149 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause + +#version 460 core + +//precision mediump float; +//precision highp int; +#define highp +#define mediump + +// Operation modes: RGBA -> 1, RGBY -> 3, LERP -> 4 +#define OperationMode 1 +// If set, will use edge direction to improve visual quality +// Expect a minimal cost increase +#define UseEdgeDirection 1 +#define EdgeThreshold 8.0/255.0 +// #define EdgeSharpness 2.0 +// #define UseUniformBlock + +#if defined(UseUniformBlock) +layout( push_constant ) uniform constants { + highp vec4 ViewportInfo[1]; + highp vec2 ResizeFactor; + highp float EdgeSharpness; +}; +layout(set = 0, binding = 0) uniform mediump sampler2D ps0; +#else +uniform highp vec4 ViewportInfo[1]; +uniform mediump sampler2D ps0; +#endif + +layout(location=0) in highp vec2 in_TEXCOORD0; +layout(location=0) out vec4 out_Target0; + +float fastLanczos2(float x) { + float wA = x-4.0; + float wB = x*wA-wA; + wA *= wA; + return wB*wA; +} + +#if defined(UseEdgeDirection) +vec2 weightY(float dx, float dy, float c, vec3 data) +#else +vec2 weightY(float dx, float dy, float c, float data) +#endif +{ +#if defined(UseEdgeDirection) + float std = data.x; + vec2 dir = data.yz; + + float edgeDis = ((dx*dir.y)+(dy*dir.x)); + float x = (((dx*dx)+(dy*dy))+((edgeDis*edgeDis)*((clamp(((c*c)*std),0.0,1.0)*0.7)+-1.0))); +#else + float std = data; + float x = ((dx*dx)+(dy* dy))* 0.55 + clamp(abs(c)*std, 0.0, 1.0); +#endif + + float w = fastLanczos2(x); + return vec2(w, w * c); +} + +vec2 edgeDirection(vec4 left, vec4 right) { + vec2 dir; + float RxLz = (right.x + (-left.z)); + float RwLy = (right.w + (-left.y)); + vec2 delta; + delta.x = (RxLz + RwLy); + delta.y = (RxLz + (-RwLy)); + float lengthInv = inversesqrt((delta.x * delta.x+ 3.075740e-05) + (delta.y * delta.y)); + dir.x = (delta.x * lengthInv); + dir.y = (delta.y * lengthInv); + return dir; +} + +void main() { + vec4 color; + if(OperationMode == 1) + color.xyz = textureLod(ps0, in_TEXCOORD0.xy, 0.0).xyz; + else + color.xyzw = textureLod(ps0, in_TEXCOORD0.xy, 0.0).xyzw; + + highp float xCenter = abs(in_TEXCOORD0.x + -0.5); + highp float yCenter = abs(in_TEXCOORD0.y + -0.5); + + //todo: config the SR region based on needs + //if ( OperationMode!=4 && xCenter*xCenter+yCenter*yCenter<=0.4 * 0.4) + if ( OperationMode!=4) { + highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo[0].zw)+vec2(-0.5,0.5)); + highp vec2 imgCoordPixel = floor(imgCoord); + highp vec2 coord = (imgCoordPixel*ViewportInfo[0].xy); + vec2 pl = imgCoord - imgCoordPixel; + vec4 left = textureGather(ps0, coord, OperationMode); + float edgeVote = abs(left.z - left.y) + abs(color[OperationMode] - left.y) + abs(color[OperationMode] - left.z) ; + if(edgeVote > EdgeThreshold) { + coord.x += ViewportInfo[0].x; + + highp vec2 IR_highp_vec2_0 = coord + vec2(ViewportInfo[0].x, 0.0); + vec4 right = textureGather(ps0, IR_highp_vec2_0, OperationMode); + vec4 upDown; + highp vec2 IR_highp_vec2_1 = coord + vec2(0.0, -ViewportInfo[0].y); + upDown.xy = textureGather(ps0, IR_highp_vec2_1, OperationMode).wz; + highp vec2 IR_highp_vec2_2 = coord + vec2(0.0, ViewportInfo[0].y); + upDown.zw = textureGather(ps0, IR_highp_vec2_2, OperationMode).yx; + + float mean = (left.y+left.z+right.x+right.w)*0.25; + left = left - vec4(mean); + right = right - vec4(mean); + upDown = upDown - vec4(mean); + color.w =color[OperationMode] - mean; + + float sum = (((((abs(left.x)+abs(left.y))+abs(left.z))+abs(left.w))+(((abs(right.x)+abs(right.y))+abs(right.z))+abs(right.w)))+(((abs(upDown.x)+abs(upDown.y))+abs(upDown.z))+abs(upDown.w))); + float sumMean = 1.014185e+01/sum; + float std = (sumMean*sumMean); + +#if defined(UseEdgeDirection) + vec3 data = vec3(std, edgeDirection(left, right)); +#else + float data = std; +#endif + vec2 aWY = weightY(pl.x, pl.y+1.0, upDown.x,data); + aWY += weightY(pl.x-1.0, pl.y+1.0, upDown.y,data); + aWY += weightY(pl.x-1.0, pl.y-2.0, upDown.z,data); + aWY += weightY(pl.x, pl.y-2.0, upDown.w,data); + aWY += weightY(pl.x+1.0, pl.y-1.0, left.x,data); + aWY += weightY(pl.x, pl.y-1.0, left.y,data); + aWY += weightY(pl.x, pl.y, left.z,data); + aWY += weightY(pl.x+1.0, pl.y, left.w,data); + aWY += weightY(pl.x-1.0, pl.y-1.0, right.x,data); + aWY += weightY(pl.x-2.0, pl.y-1.0, right.y,data); + aWY += weightY(pl.x-2.0, pl.y, right.z,data); + aWY += weightY(pl.x-1.0, pl.y, right.w,data); + + float finalY = aWY.y/aWY.x; + float maxY = max(max(left.y,left.z),max(right.x,right.w)); + float minY = min(min(left.y,left.z),min(right.x,right.w)); + float deltaY = clamp(EdgeSharpness*finalY, minY, maxY) -color.w; + + //smooth high contrast input + deltaY = clamp(deltaY, -23.0 / 255.0, 23.0 / 255.0); + + color.x = clamp((color.x+deltaY),0.0,1.0); + color.y = clamp((color.y+deltaY),0.0,1.0); + color.z = clamp((color.z+deltaY),0.0,1.0); + } + } + color.w = 1.0; //assume alpha channel is not used + out_Target0.xyzw = color; +} \ No newline at end of file