Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Snapdragon Game Super Resolution #8072

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -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

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -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
////////////////////////////////////////////////////////////////////////

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -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,

/// <summary>
/// Unity uses the Snapdragon Game Super Resolution technique to perform upscaling.
/// </summary>
[InspectorName("Snapdragon Game Super Resolution")]
SGSR,

/// <summary>
/// Unity uses the Spatial-Temporal Post-Processing technique to perform upscaling.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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;
Expand Down Expand Up @@ -1799,6 +1800,12 @@ void RenderFinalPass(CommandBuffer cmd, ref RenderingData renderingData)

break;
}

case ImageUpscalingFilter.SGSR:
{
material.EnableKeyword(ShaderKeywordStrings.Sgsr);
break;
}
}

break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2084,6 +2084,13 @@ static ImageUpscalingFilter ResolveUpscalingFilterSelection(Vector2 imageSize, f
break;
}

case UpscalingFilterSelection.SGSR:
{
filter = ImageUpscalingFilter.SGSR;

break;
}

case UpscalingFilterSelection.STP:
{
filter = ImageUpscalingFilter.STP;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ internal enum ImageUpscalingFilter
/// FidelityFX Super Resolution
FSR,

/// Snapdragon Game Super Resolution
SGSR,

/// Spatial-Temporal Post-Processing
STP
}
Expand Down Expand Up @@ -1301,6 +1304,9 @@ public static class ShaderKeywordStrings
/// <summary> Keyword used for Robust Contrast-Adaptive Sharpening (RCAS) when doing upsampling, after EASU has ran and with HDR Dsiplay output. </summary>
public const string EasuRcasAndHDRInput = "_EASU_RCAS_AND_HDR_INPUT";

/// <summary> Keyword used for Snapdragon Game Super Resolution. </summary>
public const string Sgsr = "_SGSR";

/// <summary> Keyword used for Gamma 2.0. </summary>
public const string Gamma20 = "_GAMMA_20";

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down