Skip to content

Commit

Permalink
Add support for SGSR 1.0
Browse files Browse the repository at this point in the history
SGSR stands for Snapdragon Game Super Resolution. It is an efficient
upscaler for mobile.

Split the upscaling passes into multiple methods in PostProcessManager.
Also, add a way to preserve the alpha channel in the FXAA pass.
  • Loading branch information
pixelflinger committed Jan 29, 2025
1 parent 5b3343f commit 48a2c64
Show file tree
Hide file tree
Showing 10 changed files with 458 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1420,10 +1420,10 @@ public static class DynamicResolutionOptions {
/**
* Upscaling quality
* LOW: bilinear filtered blit. Fastest, poor quality
* MEDIUM: AMD FidelityFX FSR1 w/ mobile optimizations
* MEDIUM: Qualcomm Snapdragon Game Super Resolution (SGSR) 1.0
* HIGH: AMD FidelityFX FSR1 w/ mobile optimizations
* ULTRA: AMD FidelityFX FSR1
* FSR1 require a well anti-aliased (MSAA or TAA), noise free scene.
* FSR1 and SGSR require a well anti-aliased (MSAA or TAA), noise free scene. Avoid FXAA and dithering.
*
* The default upscaling quality is set to LOW.
*/
Expand Down
7 changes: 7 additions & 0 deletions filament/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ set(MATERIAL_SRCS
src/materials/fsr/fsr_easu_mobile.mat
src/materials/fsr/fsr_easu_mobileF.mat
src/materials/fsr/fsr_rcas.mat
src/materials/sgsr/sgsr1.mat
src/materials/resolveDepth.mat
src/materials/separableGaussianBlur.mat
src/materials/skybox.mat
Expand Down Expand Up @@ -504,6 +505,12 @@ add_custom_command(
APPEND
)

add_custom_command(
OUTPUT "${MATERIAL_DIR}/sgsr1.filamat"
DEPENDS src/materials/sgsr/sgsr1_shader_mobile.fs
APPEND
)

add_custom_command(
OUTPUT "${MATERIAL_DIR}/separableGaussianBlur.filamat"
DEPENDS src/materials/separableGaussianBlur.vs
Expand Down
4 changes: 2 additions & 2 deletions filament/include/filament/Options.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ struct DynamicResolutionOptions {
/**
* Upscaling quality
* LOW: bilinear filtered blit. Fastest, poor quality
* MEDIUM: AMD FidelityFX FSR1 w/ mobile optimizations
* MEDIUM: Qualcomm Snapdragon Game Super Resolution (SGSR) 1.0
* HIGH: AMD FidelityFX FSR1 w/ mobile optimizations
* ULTRA: AMD FidelityFX FSR1
* FSR1 require a well anti-aliased (MSAA or TAA), noise free scene.
* FSR1 and SGSR require a well anti-aliased (MSAA or TAA), noise free scene. Avoid FXAA and dithering.
*
* The default upscaling quality is set to LOW.
*/
Expand Down
222 changes: 174 additions & 48 deletions filament/src/PostProcessManager.cpp

Large diffs are not rendered by default.

19 changes: 16 additions & 3 deletions filament/src/PostProcessManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class PostProcessManager {
bool asSubpass{};
bool customResolve{};
bool translucent{};
bool fxaa{};
bool outputLuminance{}; // Whether to output luminance in the alpha channel. Ignored by the TRANSLUCENT variant.
bool dithering{};
backend::TextureFormat ldrFormat{};
};
Expand Down Expand Up @@ -227,7 +227,7 @@ class PostProcessManager {
// Anti-aliasing
FrameGraphId<FrameGraphTexture> fxaa(FrameGraph& fg,
FrameGraphId<FrameGraphTexture> input, Viewport const& vp,
backend::TextureFormat outFormat, bool translucent) noexcept;
backend::TextureFormat outFormat, bool preserveAlphaChannel) noexcept;

// Temporal Anti-aliasing
void TaaJitterCamera(
Expand All @@ -251,12 +251,25 @@ class PostProcessManager {

// high quality upscaler
// - when translucent, reverts to LINEAR
// - doens't handle sub-resouces
// - doesn't handle sub-resouces
FrameGraphId<FrameGraphTexture> upscale(FrameGraph& fg, bool translucent,
bool sourceHasLuminance, DynamicResolutionOptions dsrOptions,
FrameGraphId<FrameGraphTexture> input, Viewport const& vp,
FrameGraphTexture::Descriptor const& outDesc, backend::SamplerMagFilter filter) noexcept;

FrameGraphId<FrameGraphTexture> upscaleBilinear(FrameGraph& fg, bool translucent,
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> input,
Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc,
backend::SamplerMagFilter filter) noexcept;

FrameGraphId<FrameGraphTexture> upscaleFSR1(FrameGraph& fg,
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> input,
filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc) noexcept;

FrameGraphId<FrameGraphTexture> upscaleSGSR1(FrameGraph& fg, bool sourceHasLuminance,
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> input,
filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc) noexcept;

FrameGraphId<FrameGraphTexture> rcas(
FrameGraph& fg,
float sharpness,
Expand Down
23 changes: 13 additions & 10 deletions filament/src/details/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,9 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
hasColorGrading &&
!bloomOptions.enabled && !dofOptions.enabled && !taaOptions.enabled;

// whether we're scaled at all
bool scaled = any(notEqual(scale, float2(1.0f)));

// asSubpass is disabled with TAA (although it's supported) because performance was degraded
// on qualcomm hardware -- we might need a backend dependent toggle at some point
const PostProcessManager::ColorGradingConfig colorGradingConfig{
Expand All @@ -695,18 +698,15 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
hasColorGrading &&
!engine.debug.renderer.disable_subpasses,
.translucent = needsAlphaChannel,
.fxaa = hasFXAA,
.outputLuminance = hasFXAA || scaled, // ignored by translucent variants (false)
.dithering = hasDithering,
.ldrFormat = (hasColorGrading && hasFXAA) ?
.ldrFormat = (hasColorGrading && (hasFXAA || scaled)) ?
TextureFormat::RGBA8 : getLdrFormat(needsAlphaChannel)
};

// by construction (msaaSampleCount) both asSubpass and customResolve can't be true
assert_invariant(colorGradingConfig.asSubpass + colorGradingConfig.customResolve < 2);

// whether we're scaled at all
bool scaled = any(notEqual(scale, float2(1.0f)));

// vp is the user defined viewport within the View
filament::Viewport const& vp = view.getViewport();

Expand Down Expand Up @@ -1351,18 +1351,21 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
}

if (hasFXAA) {
input = ppm.fxaa(fg, input, xvp, colorGradingConfig.ldrFormat,
!hasColorGrading || needsAlphaChannel);
bool const preserveAlphaChannel = needsAlphaChannel ||
(hasColorGrading && colorGradingConfig.outputLuminance);
input = ppm.fxaa(fg, input, xvp, colorGradingConfig.ldrFormat, preserveAlphaChannel);
// the padded buffer is resolved now
xvp.left = xvp.bottom = 0;
svp = xvp;
}
if (scaled) {
mightNeedFinalBlit = false;
auto viewport = DEBUG_DYNAMIC_SCALING ? xvp : vp;
input = ppm.upscale(fg, needsAlphaChannel, dsrOptions, input, xvp, {
.width = viewport.width, .height = viewport.height,
.format = colorGradingConfig.ldrFormat }, SamplerMagFilter::LINEAR);
bool const sourceHasLuminance = !needsAlphaChannel &&
(hasColorGrading && colorGradingConfig.outputLuminance);
input = ppm.upscale(fg, needsAlphaChannel, sourceHasLuminance, dsrOptions, input, xvp, {
.width = viewport.width, .height = viewport.height,
.format = colorGradingConfig.ldrFormat }, SamplerMagFilter::LINEAR);
xvp.left = xvp.bottom = 0;
svp = xvp;
}
Expand Down
6 changes: 3 additions & 3 deletions filament/src/materials/colorGrading/colorGrading.mat
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ material {
},
{
type : int,
name : fxaa
name : outputLuminance
},
{
type : float,
Expand Down Expand Up @@ -166,10 +166,10 @@ void postProcess(inout PostProcessInputs postProcess) {
color = dither(color, materialParams.temporalNoise);
}

// kill alpha computations when opaque / fxaa luminance
// kill alpha computations when opaque / luminance
#if POST_PROCESS_OPAQUE
color.a = 1.0;
if (materialParams.fxaa > 0) {
if (materialParams.outputLuminance > 0) {
color.a = luminance(color.rgb);
}
#endif
Expand Down
29 changes: 29 additions & 0 deletions filament/src/materials/sgsr/LICENSE.txt
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
80 changes: 80 additions & 0 deletions filament/src/materials/sgsr/sgsr1.mat
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
material {
name : sgsr1,
parameters : [
{
type : sampler2d,
name : color,
precision: medium
},
{
type : float4,
name : viewport,
precision: high
}
],
variables : [
vertex
],
depthWrite : false,
depthCulling : false,
domain: postprocess
}

vertex {
void postProcessVertex(inout PostProcessVertexInputs postProcess) {
postProcess.normalizedUV = uvToRenderTargetUV(postProcess.normalizedUV);
postProcess.vertex.xy = postProcess.normalizedUV;
}
}

fragment {

void dummy(){}

precision mediump float;
precision highp int;

#if defined(FILAMENT_HAS_FEATURE_TEXTURE_GATHER)
#define gather textureGather
#else
vec4 gather(const mediump sampler2D color, highp vec2 p, const int comp) {
highp ivec2 i = ivec2(p * materialParams.viewport.zw - 0.5);
vec4 d;
d[0] = texelFetchOffset(color, i, 0, ivec2(0, 1))[comp];
d[1] = texelFetchOffset(color, i, 0, ivec2(1, 1))[comp];
d[2] = texelFetchOffset(color, i, 0, ivec2(1, 0))[comp];
d[3] = texelFetchOffset(color, i, 0, ivec2(0, 0))[comp];
return d;
}
#endif

/*
* Operation modes:
* RGBA -> 1
* RGBY -> 3
* LERP -> 4
*/

// SGSR cannot support translucency;
// So we hijack the POST_PROCESS variant to select whether a luminance channel is present
#if POST_PROCESS_OPAQUE
# define OperationMode 1
#else
# define OperationMode 3
#endif

/*
* If set, will use edge direction to improve visual quality
* Expect a minimal cost increase
*/
#define UseEdgeDirection
#define EdgeThreshold 8.0 / 255.0
#define EdgeSharpness 2.0

#include "sgsr1_shader_mobile.fs"

void postProcess(inout PostProcessInputs postProcess) {
highp vec4 vp[1] = vec4[1]( materialParams.viewport );
postProcess.color = sgsr(materialParams_color, variable_vertex.xy, vp);
}
}
Loading

1 comment on commit 48a2c64

@emezeske
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #8401, I think this change is related to the new crash.

Please sign in to comment.