diff --git a/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/sgsr.meta b/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/sgsr.meta
new file mode 100644
index 00000000000..0378869041f
--- /dev/null
+++ b/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/sgsr.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d9b19982aed923e418ed37258a6a7729
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/sgsr/LICENSE b/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/sgsr/LICENSE
new file mode 100644
index 00000000000..d9d513c7585
--- /dev/null
+++ b/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/sgsr/LICENSE
@@ -0,0 +1,29 @@
+Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+SPDX-License-Identifier: BSD-3-Clause
\ No newline at end of file
diff --git a/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/sgsr/LICENSE.meta b/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/sgsr/LICENSE.meta
new file mode 100644
index 00000000000..cd5a974ad49
--- /dev/null
+++ b/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/sgsr/LICENSE.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 0784c039be2675c41a8c0f8460805ef3
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/sgsr/sgsr_mobile.hlsl b/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/sgsr/sgsr_mobile.hlsl
new file mode 100644
index 00000000000..bbc9cfe9118
--- /dev/null
+++ b/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/sgsr/sgsr_mobile.hlsl
@@ -0,0 +1,130 @@
+//============================================================================================================
+//
+//
+// Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
+// SPDX-License-Identifier: BSD-3-Clause
+//
+//============================================================================================================
+
+////////////////////////
+// USER CONFIGURATION //
+////////////////////////
+
+/*
+* Operation modes:
+* RGBA -> 1
+* RGBY -> 3
+* LERP -> 4
+*/
+#define OperationMode 1
+
+#define EdgeThreshold 8.0/255.0
+
+#define EdgeSharpness 2.0
+
+////////////////////////
+////////////////////////
+////////////////////////
+
+// ///////SGSR_GL_Mobile.frag/////////////////////////////////////////
+#if defined(SGSR_MOBILE)
+half fastLanczos2(half x)
+{
+ half wA = x- half(4.0);
+ half wB = x*wA-wA;
+ wA *= wA;
+ return wB*wA;
+}
+half2 weightY(half dx, half dy, half c, half std)
+{
+ half x = ((dx*dx)+(dy* dy))* half(0.5) + clamp(abs(c)*std, 0.0, 1.0);
+ half w = fastLanczos2(x);
+ return half2(w, w * c);
+}
+
+void SgsrYuvH(
+ out half4 pix,
+ float2 uv,
+ float4 con1)
+{
+ const int mode = OperationMode;
+ half edgeThreshold = EdgeThreshold;
+ half edgeSharpness = EdgeSharpness;
+
+ // Sample the low res texture using current texture coordinates (in UV space).
+ if(mode == 1)
+ pix.xyz = SGSRRGBH(uv).xyz;
+ else
+ pix.xyzw = SGSRRGBH(uv).xyzw;
+ float xCenter;
+ xCenter = abs(uv.x+-0.5);
+ float yCenter;
+ yCenter = abs(uv.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)
+ {
+ // Compute the coordinate for the center of the texel in image space.
+ float2 imgCoord = ((uv.xy*con1.zw)+ float2(-0.5,0.5));
+ float2 imgCoordPixel = floor(imgCoord);
+ // Remap the coordinate for the center of the texel in image space to UV space.
+ float2 coord = (imgCoordPixel*con1.xy);
+ half2 pl = (imgCoord+(-imgCoordPixel));
+ // Gather the `[mode]` components (ex: `.y` if mode is 1) of the 4 texels located around `coord`.
+ half4 left = SGSRH(coord, mode);
+
+ half edgeVote = abs(left.z - left.y) + abs(pix[mode] - left.y) + abs(pix[mode] - left.z) ;
+ if(edgeVote > edgeThreshold)
+ {
+ // Shift coord to the right by 1 texel. `coord` will be pointing to the same texel originally sampled
+ // l.84 or 86 (The texel at UV in_TEXCOORD0 in the low res texture).
+ coord.x += con1.x;
+
+ // Gather components for the texels located to the right of coord (the original sampled texel).
+ half4 right = SGSRH(coord + float2(con1.x, 0.0), mode);
+ // Gather components for the texels located to up and down of coord (the original sampled texel).
+ half4 upDown;
+ upDown.xy = SGSRH(coord + float2(0.0, -con1.y), mode).wz;
+ upDown.zw = SGSRH(coord + float2(0.0, con1.y), mode).yx;
+
+ half mean = (left.y+left.z+right.x+right.w)* half(0.25);
+ left = left - half4(mean,mean,mean,mean);
+ right = right - half4(mean, mean, mean, mean);
+ upDown = upDown - half4(mean, mean, mean, mean);
+ pix.w =pix[mode] - mean;
+
+ half 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)));
+ half std = half(2.181818)/sum;
+
+ half2 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);
+
+ half finalY = aWY.y/aWY.x;
+
+ half max4 = max(max(left.y,left.z),max(right.x,right.w));
+ half min4 = min(min(left.y,left.z),min(right.x,right.w));
+ finalY = clamp(edgeSharpness*finalY, min4, max4);
+
+ half deltaY = finalY -pix.w;
+
+ pix.x = saturate((pix.x+deltaY));
+ pix.y = saturate((pix.y+deltaY));
+ pix.z = saturate((pix.z+deltaY));
+ }
+ }
+ pix.w = 1.0; //assume alpha channel is not used
+
+}
+#endif
+////////////////////////////////////////////////////////////////////////
diff --git a/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/sgsr/sgsr_mobile.hlsl.meta b/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/sgsr/sgsr_mobile.hlsl.meta
new file mode 100644
index 00000000000..c9fa5182513
--- /dev/null
+++ b/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/sgsr/sgsr_mobile.hlsl.meta
@@ -0,0 +1,27 @@
+fileFormatVersion: 2
+guid: 107bc422565fc5443a1df1419ea7ba81
+PluginImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ iconMap: {}
+ executionOrder: {}
+ defineConstraints: []
+ isPreloaded: 0
+ isOverridable: 1
+ isExplicitlyReferenced: 0
+ validateReferences: 1
+ platformData:
+ - first:
+ Any:
+ second:
+ enabled: 1
+ settings: {}
+ - first:
+ Editor: Editor
+ second:
+ enabled: 0
+ settings:
+ DefaultValueInitialized: true
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/Data/UniversalRenderPipelineAsset.cs b/Packages/com.unity.render-pipelines.universal/Runtime/Data/UniversalRenderPipelineAsset.cs
index b4d4e849c71..f08b19ea4b6 100644
--- a/Packages/com.unity.render-pipelines.universal/Runtime/Data/UniversalRenderPipelineAsset.cs
+++ b/Packages/com.unity.render-pipelines.universal/Runtime/Data/UniversalRenderPipelineAsset.cs
@@ -374,6 +374,12 @@ public enum UpscalingFilterSelection
[InspectorName("FidelityFX Super Resolution 1.0"), Tooltip("If the target device does not support Unity shader model 4.5, Unity falls back to the Automatic option.")]
FSR,
+ ///
+ /// Unity uses the Snapdragon Game Super Resolution technique to perform upscaling.
+ ///
+ [InspectorName("Snapdragon Game Super Resolution")]
+ SGSR,
+
///
/// Unity uses the Spatial-Temporal Post-Processing technique to perform upscaling.
///
diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/Passes/PostProcessPass.cs b/Packages/com.unity.render-pipelines.universal/Runtime/Passes/PostProcessPass.cs
index dbac1d62450..de3d03b838a 100644
--- a/Packages/com.unity.render-pipelines.universal/Runtime/Passes/PostProcessPass.cs
+++ b/Packages/com.unity.render-pipelines.universal/Runtime/Passes/PostProcessPass.cs
@@ -1689,6 +1689,7 @@ void RenderFinalPass(CommandBuffer cmd, ref RenderingData renderingData)
// FSR is only considered "enabled" when we're performing upscaling. (downscaling uses a linear filter unconditionally)
bool isFsrEnabled = ((cameraData.imageScalingMode == ImageScalingMode.Upscaling) && (cameraData.upscalingFilter == ImageUpscalingFilter.FSR));
+ bool isSgsrEnabled = ((cameraData.imageScalingMode == ImageScalingMode.Upscaling) && (cameraData.upscalingFilter == ImageUpscalingFilter.SGSR));
// Reuse RCAS pass as an optional standalone post sharpening pass for TAA.
// This avoids the cost of EASU and is available for other upscaling options.
@@ -1704,7 +1705,7 @@ void RenderFinalPass(CommandBuffer cmd, ref RenderingData renderingData)
// NOTE: An ideal implementation could inline this color conversion logic into the UberPost pass, but the current code structure would make
// this process very complex. Specifically, we'd need to guarantee that the uber post output is always written to a UNORM format render
// target in order to preserve the precision of specially encoded color data.
- bool isSetupRequired = (isFxaaEnabled || isFsrEnabled);
+ bool isSetupRequired = (isFxaaEnabled || isFsrEnabled || isSgsrEnabled);
// Make sure to remove any MSAA and attached depth buffers from the temporary render targets
var tempRtDesc = cameraData.cameraTargetDescriptor;
@@ -1799,6 +1800,12 @@ void RenderFinalPass(CommandBuffer cmd, ref RenderingData renderingData)
break;
}
+
+ case ImageUpscalingFilter.SGSR:
+ {
+ material.EnableKeyword(ShaderKeywordStrings.Sgsr);
+ break;
+ }
}
break;
diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipeline.cs b/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipeline.cs
index a3ce26eb4f2..12391c49bfe 100644
--- a/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipeline.cs
+++ b/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipeline.cs
@@ -2084,6 +2084,13 @@ static ImageUpscalingFilter ResolveUpscalingFilterSelection(Vector2 imageSize, f
break;
}
+ case UpscalingFilterSelection.SGSR:
+ {
+ filter = ImageUpscalingFilter.SGSR;
+
+ break;
+ }
+
case UpscalingFilterSelection.STP:
{
filter = ImageUpscalingFilter.STP;
diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipelineCore.cs b/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipelineCore.cs
index 9a3e14b0fa2..6ff4851d616 100644
--- a/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipelineCore.cs
+++ b/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipelineCore.cs
@@ -75,6 +75,9 @@ internal enum ImageUpscalingFilter
/// FidelityFX Super Resolution
FSR,
+ /// Snapdragon Game Super Resolution
+ SGSR,
+
/// Spatial-Temporal Post-Processing
STP
}
@@ -1301,6 +1304,9 @@ public static class ShaderKeywordStrings
/// Keyword used for Robust Contrast-Adaptive Sharpening (RCAS) when doing upsampling, after EASU has ran and with HDR Dsiplay output.
public const string EasuRcasAndHDRInput = "_EASU_RCAS_AND_HDR_INPUT";
+ /// Keyword used for Snapdragon Game Super Resolution.
+ public const string Sgsr = "_SGSR";
+
/// Keyword used for Gamma 2.0.
public const string Gamma20 = "_GAMMA_20";
diff --git a/Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/FinalPost.shader b/Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/FinalPost.shader
index c7f4b7a22df..64f77656925 100644
--- a/Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/FinalPost.shader
+++ b/Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/FinalPost.shader
@@ -1,7 +1,7 @@
Shader "Hidden/Universal Render Pipeline/FinalPost"
{
HLSLINCLUDE
- #pragma multi_compile_local_fragment _ _POINT_SAMPLING _RCAS _EASU_RCAS_AND_HDR_INPUT
+ #pragma multi_compile_local_fragment _ _POINT_SAMPLING _RCAS _EASU_RCAS_AND_HDR_INPUT _SGSR
#pragma multi_compile_local_fragment _ _FXAA
#pragma multi_compile_local_fragment _ _FILM_GRAIN
#pragma multi_compile_local_fragment _ _DITHERING
@@ -55,6 +55,49 @@ Shader "Hidden/Universal Render Pipeline/FinalPost"
#include "Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/FSRCommon.hlsl"
#endif
+ #if defined(_SGSR)
+ #define SGSR_MOBILE
+
+ half4 SGSRRH(float2 p)
+ {
+ half4 res = _BlitTexture.GatherRed(sampler_LinearClamp, p);
+ return res;
+ }
+ half4 SGSRGH(float2 p)
+ {
+ half4 res = _BlitTexture.GatherGreen(sampler_LinearClamp, p);
+ return res;
+ }
+ half4 SGSRBH(float2 p)
+ {
+ half4 res = _BlitTexture.GatherBlue(sampler_LinearClamp, p);
+ return res;
+ }
+ half4 SGSRAH(float2 p)
+ {
+ half4 res = _BlitTexture.GatherAlpha(sampler_LinearClamp, p);
+ return res;
+ }
+ half4 SGSRRGBH(float2 p)
+ {
+ half4 res = _BlitTexture.SampleLevel(sampler_LinearClamp, p, 0);
+ return res;
+ }
+
+ half4 SGSRH(float2 p, uint channel)
+ {
+ if (channel == 0)
+ return SGSRRH(p);
+ if (channel == 1)
+ return SGSRGH(p);
+ if (channel == 2)
+ return SGSRBH(p);
+ return SGSRAH(p);
+ }
+
+ #include "Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/sgsr/sgsr_mobile.hlsl"
+ #endif
+
half4 FragFinalPost(Varyings input) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
@@ -80,6 +123,13 @@ Shader "Hidden/Universal Render Pipeline/FinalPost"
#if _ENABLE_ALPHA_OUTPUT
color.a = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv).a;
#endif
+ #elif _SGSR
+ half4 color = half4(0, 0, 0, 1);
+ // ViewportInfo should be a float4 containing {1.0/low_res_tex_width, 1.0/low_res_tex_height, low_res_tex_width, low_res_tex_height}.
+ // The `xy` components will be used to shift UVs to read adjacent texels.
+ // The `zw` components will be used to map from UV space [0, 1][0, 1] to image space [0, w][0, h].
+ // _SourceSize contains the same data as ViewportInfo except xy are swapped with zw
+ SgsrYuvH(color, uv, _SourceSize.zwxy);
#else
half4 color = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv);
#endif