Skip to content

Commit 0cebdb9

Browse files
committed
Enhaced the VRS implementation to support foveated rendering
- The shader was extended with an option to select between the default algorithm based on luminance and motion vectors, foveated rendering, or a combination. - The `FfxVrsDispatchDescription` parameters were extended accordingly - The sample now has the option to select between the different vrs image generation algorithms. Signed-off-by: Kenneth Funes <[email protected]>
1 parent 54fbaaf commit 0cebdb9

File tree

12 files changed

+209
-4
lines changed

12 files changed

+209
-4
lines changed
Loading
Loading

docs/samples/variable-shading.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ The sample contains various UI elements to help you explore the techniques it de
2424
| **PerDraw VRS** | `1x1, 1x2, 2x1, 2x2` | Shading rate value. Additional shading rates are 2x4, 4x2, 4x4. |
2525
| **ShadingRateImage Enabled** | `Checked/Unchecked` | Enable/Disable Tier 2 VRS control image. |
2626
| **ShadingRateImage Combiner** | `Checked/Unchecked` | The options for each combiner are: passthrough the previous state (i.e. disable the current stage), override (ignore previous stages), min, max and sum. |
27+
| **VRS Algorithm** | `Luminance and Motion Vectors, Foveated Rendering, Combined (Max)` | The technique used to generate the shading rate image. |
2728
| **VRS variance Threshold** | `0.0 - 1.0` | Defines a value against which luminance variance gets compared in the compute shader generating the VRS image. |
2829
| **VRS Motion Factor** | `0.0 - 1.0` | Sets a factor by which the motion of the pixel since the last frame gets scaled to modify the shading rate. |
2930
| **ShadingRateImage Overlay** | `Checked/Unchecked` | Enable/Disable ShadingRateImage overlay, a debug image over the rendered scene. |
3031

3132
<h2>Setting up Variable Shading</h2>
3233

33-
The Variable Shading compute shader takes as input the linear color buffer produced by the geometry rendering passes, and motion vectors buffer produced before geometry rendering passes. Final VRS control image is written to output buffer passed from setup.
34+
The Variable Shading compute shader takes as input the linear color buffer produced by the geometry rendering passes, and motion vectors buffer produced before geometry rendering passes. It also takes as input the center and radii for the foveated rendering regions. Final VRS control image is written to output buffer passed from setup.
3435

3536
Include the interface for the backend of the VRS API.
3637

docs/techniques/variable-shading.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ FidelityFX Variable Shading (VRS) provides a similar way to reduce the number of
1212

1313
One way to think about how VRS works is to think of MSAA: if a 4K frame is rendered with 2x2 VRS for everything, the required computational power and the final quality of the image would be comparable to rendering a 1080p image with 4x MSAA enabled. However, VRS provides additional features to enable more fine-grained control over which parts of the frame should get rendered with lower resolution.
1414

15+
FidelityFX Variable Shading (VRS) also gives the option to implement Foveated Rendering by significanly reducing the number of pixel shading executions at the outer periphery of where the user is looking, taking advantage of the user not noticing the loss of visual quality in such regions. This can thus be paired with an eye tracker, whether built in a VR headset, a dedicated hardware or a webcam based software.
16+
1517
<h2>Implementing Variable Shading</h2>
1618

1719
<h3>Cases allowing VRS</h3>
@@ -24,8 +26,9 @@ image:
2426
- Some objects may get distorted or blurred by being behind haze or semi-transparent objects like water or frosted glass.
2527
- Some objects might be known to have little detail variance (such as rendering for toon shaded games) or due to being in very dark parts of the scene (e.g. the unlit or shadowed parts of objects in scenes with little ambient light).
2628
- In fast moving scenes, high framerate and low input lag are important, but small details are less likely to get noticed by the player, so aggressively using VRS can help to achieve the performance goals.
29+
- When using an eye tracking device, one can establish where the user is looking, and can decrease the visual quality away from that area without being noticeable.
2730

28-
In addition to the cases mentioned above, some pixels might be known to be of little interest to the player, either through eye-tracking (foveated rendering) or other systems, or because the game design aims to steer the focus of the player to certain parts of the screen. As an example, the game might choose to reduce the shading rate on the background geometry but make sure all enemies are rendered at highest quality.
31+
In addition to the cases mentioned above, some pixels might be known to be of little interest to the player, either through eye-tracking or other systems, or because the game design aims to steer the focus of the player to certain parts of the screen. As an example, the game might choose to reduce the shading rate on the background geometry but make sure all enemies are rendered at highest quality.
2932

3033
Due to saving computational power by focusing usage of GPU resources where it matters most, VRS can be used to make sure target frame times are achieved (similar to dynamic resolution scaling but with more fine-grained control over where detail needs to be preserved), as well as for power saving on portable devices without noticeably sacrificing image quality.
3134

samples/vrs/vrsrendermodule.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,21 @@ void VRSRenderModule::BuildUI()
299299
}
300300
);
301301

302+
const char* algorithmOptions[] = {"Luminance and Motion Vectors", "Foveated Rendering", "Combined (Max)"};
303+
comboOptions.clear();
304+
for (int32_t i = 0; i < _countof(algorithmOptions); ++i)
305+
{
306+
comboOptions.push_back(algorithmOptions[i]);
307+
}
308+
309+
uiSection->RegisterUIElement<UICombo>(
310+
"VRS Algorithm",
311+
(int32_t&)m_ShadingRateImageAlgorithmIndex,
312+
std::move(comboOptions),
313+
m_ShadingRateImageEnabled,
314+
[this](int32_t cur, int32_t old) {}
315+
);
316+
302317
uiSection->RegisterUIElement<UISlider<float>>("VRS variance Threshold", m_VRSThreshold, 0.f, 0.1f, m_ShadingRateImageEnabled);
303318
uiSection->RegisterUIElement<UISlider<float>>("VRS Motion Factor", m_VRSMotionFactor, 0.f, 0.1f, m_ShadingRateImageEnabled);
304319

@@ -691,8 +706,17 @@ void VRSRenderModule::ExecuteVRSImageGen(double deltaTime, cauldron::CommandList
691706
uint32_t width = GetFramework()->GetResolutionInfo().RenderWidth;
692707
uint32_t height = GetFramework()->GetResolutionInfo().RenderHeight;
693708

709+
uint32_t vrsAlgorithm;
710+
if (m_ShadingRateImageAlgorithmIndex == 0)
711+
vrsAlgorithm = FFX_VARIABLESHADING_IMAGE_ALGORITHM_LUMINANCE_AND_MOTION_VECTORS;
712+
else if (m_ShadingRateImageAlgorithmIndex == 1)
713+
vrsAlgorithm = FFX_VARIABLESHADING_IMAGE_ALGORITHM_FOVEATED;
714+
else
715+
vrsAlgorithm = FFX_VARIABLESHADING_IMAGE_ALGORITHM_LUMINANCE_AND_MOTION_VECTORS | FFX_VARIABLESHADING_IMAGE_ALGORITHM_FOVEATED;
716+
694717
FfxVrsDispatchDescription dispatchParameters = {};
695718
dispatchParameters.commandList = SDKWrapper::ffxGetCommandList(pCmdList);
719+
dispatchParameters.vrsAlgorithm = vrsAlgorithm;
696720
dispatchParameters.output = SDKWrapper::ffxGetResource(m_pVRSTexture->GetResource(), L"VRSImage", FFX_RESOURCE_STATE_UNORDERED_ACCESS);
697721
dispatchParameters.historyColor = SDKWrapper::ffxGetResource(m_pHistoryColorBuffer->GetResource(), L"HistoryColorBuffer", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
698722
dispatchParameters.motionVectors = SDKWrapper::ffxGetResource(m_pMotionVectors->GetResource(), L"VRSMotionVectorsTarget", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ);
@@ -702,6 +726,12 @@ void VRSRenderModule::ExecuteVRSImageGen(double deltaTime, cauldron::CommandList
702726
dispatchParameters.renderSize = {width, height};
703727
dispatchParameters.motionVectorScale.x = -1.f;
704728
dispatchParameters.motionVectorScale.y = -1.f;
729+
dispatchParameters.foveationCenter.x = m_VRSFoveationCenter.x * width;
730+
dispatchParameters.foveationCenter.y = m_VRSFoveationCenter.y * height;
731+
dispatchParameters.foveationRadiiSquared.radius1x1 = (m_VRSFovRadii.radius1x1 * width) * (m_VRSFovRadii.radius1x1 * width);
732+
dispatchParameters.foveationRadiiSquared.radius1x2 = (m_VRSFovRadii.radius1x2 * width) * (m_VRSFovRadii.radius1x2 * width);
733+
dispatchParameters.foveationRadiiSquared.radius2x2 = (m_VRSFovRadii.radius2x2 * width) * (m_VRSFovRadii.radius2x2 * width);
734+
dispatchParameters.foveationRadiiSquared.radius2x4 = (m_VRSFovRadii.radius2x4 * width) * (m_VRSFovRadii.radius2x4 * width);
705735

706736
// Disabled until remaining things are fixes
707737
FfxErrorCode errorCode = ffxVrsContextDispatch(&m_VRSContext, &dispatchParameters);

samples/vrs/vrsrendermodule.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,13 @@ class VRSRenderModule : public cauldron::RenderModule, public cauldron::ContentL
140140
uint32_t m_ShadingRateIndex = 0;
141141
uint32_t m_ShadingRateCombinerIndex = 0;
142142
bool m_EnableShadingRateImage = false;
143+
uint32_t m_ShadingRateImageAlgorithmIndex = 0;
143144
bool m_AllowAdditionalShadingRates = false;
144145
uint32_t m_VRSTierSupported = 0;
145146
float m_VRSThreshold = 0.015f;
146147
float m_VRSMotionFactor = 0.01f;
148+
FfxFloatCoords2D m_VRSFoveationCenter{0.5f, 0.5f};
149+
FfxVrsFovRadii m_VRSFovRadii{0.2f, 0.3f, 0.4f, 0.5f};
147150

148151
bool m_VariableShadingEnabled = false;
149152
bool m_ShadingRateImageEnabled = false;

sdk/include/FidelityFX/gpu/vrs/ffx_variable_shading.h

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
#define FFX_CPU
3030
#include <FidelityFX/gpu/ffx_core.h>
3131

32+
FFX_STATIC const FfxUInt32 FFX_VARIABLESHADING_IMAGE_ALGORITHM_LUMINANCE_AND_MOTION_VECTORS = 0x1;
33+
FFX_STATIC const FfxUInt32 FFX_VARIABLESHADING_IMAGE_ALGORITHM_FOVEATED = 0x2;
34+
3235
FFX_STATIC void ffxVariableShadingGetDispatchInfo(
3336
const FfxDimensions2D resolution, const FfxUInt32 tileSize, const bool useAditionalShadingRates, FfxUInt32& numThreadGroupsX, FfxUInt32& numThreadGroupsY)
3437
{
@@ -61,6 +64,9 @@ FFX_STATIC void ffxVariableShadingGetDispatchInfo(
6164
}
6265
#elif defined(FFX_GPU)
6366

67+
FFX_STATIC const FfxUInt32 FFX_VARIABLESHADING_IMAGE_ALGORITHM_LUMINANCE_AND_MOTION_VECTORS = 0x1;
68+
FFX_STATIC const FfxUInt32 FFX_VARIABLESHADING_IMAGE_ALGORITHM_FOVEATED = 0x2;
69+
6470
// Forward declaration of functions that need to be implemented by shader code using this technique
6571
FfxFloat32 ReadLuminance(FfxInt32x2 pos);
6672
FfxFloat32x2 ReadMotionVec2D(FfxInt32x2 pos);
@@ -70,6 +76,8 @@ FFX_STATIC const FfxUInt32 FFX_VARIABLESHADING_RATE1D_1X = 0x0;
7076
FFX_STATIC const FfxUInt32 FFX_VARIABLESHADING_RATE1D_2X = 0x1;
7177
FFX_STATIC const FfxUInt32 FFX_VARIABLESHADING_RATE1D_4X = 0x2;
7278
#define FFX_VARIABLESHADING_MAKE_SHADING_RATE(x,y) ((x << 2) | (y))
79+
#define FFX_VARIABLESHADING_SHADING_RATE_2D_MAX(xy, wz) \
80+
FFX_VARIABLESHADING_MAKE_SHADING_RATE(max(xy >> 2, wz >> 2), max(xy & 0x3,wz & 0x3))
7381

7482
FFX_STATIC const FfxUInt32 FFX_VARIABLESHADING_RATE_1X1 = FFX_VARIABLESHADING_MAKE_SHADING_RATE(FFX_VARIABLESHADING_RATE1D_1X, FFX_VARIABLESHADING_RATE1D_1X); // 0;
7583
FFX_STATIC const FfxUInt32 FFX_VARIABLESHADING_RATE_1X2 = FFX_VARIABLESHADING_MAKE_SHADING_RATE(FFX_VARIABLESHADING_RATE1D_1X, FFX_VARIABLESHADING_RATE1D_2X); // 0x1;
@@ -91,6 +99,7 @@ FFX_STATIC const FfxUInt32 FFX_VariableShading_ThreadCount1D = 16;
9199
FFX_STATIC const FfxUInt32 FFX_VariableShading_NumBlocks1D = 1;
92100
#endif
93101
FFX_STATIC const FfxUInt32 FFX_VariableShading_SampleCount1D = FFX_VariableShading_ThreadCount1D + 2;
102+
FFX_STATIC const FfxUInt32 FFX_VariableShading_TileCenterOffset1D = FFX_VARIABLESHADING_TILESIZE >> 1 - 1;
94103

95104
FFX_GROUPSHARED FfxUInt32 FFX_VariableShading_LdsGroupReduce;
96105

@@ -107,6 +116,7 @@ FFX_STATIC const FfxUInt32 FFX_VariableShading_ThreadCount1D = 8;
107116
FFX_STATIC const FfxUInt32 FFX_VariableShading_NumBlocks1D = 32 / FFX_VARIABLESHADING_TILESIZE;
108117
FFX_STATIC const FfxUInt32 FFX_VariableShading_TilesPerGroup = FFX_VariableShading_NumBlocks1D * FFX_VariableShading_NumBlocks1D;
109118
FFX_STATIC const FfxUInt32 FFX_VariableShading_SampleCount1D = FFX_VariableShading_ThreadCount1D + 2;
119+
FFX_STATIC const FfxUInt32 FFX_VariableShading_TileCenterOffset1D = FFX_VARIABLESHADING_TILESIZE >> 1 - 1;
110120

111121
FFX_GROUPSHARED FfxUInt32 FFX_VariableShading_LdsGroupReduce[FFX_VariableShading_TilesPerGroup];
112122

@@ -118,6 +128,46 @@ FFX_STATIC const FfxUInt32 FFX_VariableShading_NumBlocks = FFX_VariableShading_N
118128
FFX_GROUPSHARED FfxUInt32 FFX_VariableShading_LdsShadingRate[FFX_VariableShading_SampleCount];
119129
#endif
120130

131+
FfxUInt32 VrsComputeFoveatedShadingRate(FfxUInt32x3 Gid, FfxUInt32x3 Gtid, FfxUInt32 Gidx)
132+
{
133+
FfxFloat32x2 tileVRSImageCoords = FfxFloat32x2(Gid.xy * FFX_VariableShading_NumBlocks1D + FfxUInt32x2(Gidx / FFX_VariableShading_NumBlocks1D, Gidx % FFX_VariableShading_NumBlocks1D));
134+
FfxFloat32x2 tileRenderingTargetCoords = FfxFloat32x2(tileVRSImageCoords.x * FFX_VARIABLESHADING_TILESIZE, tileVRSImageCoords.y * FFX_VARIABLESHADING_TILESIZE) + FfxFloat32x2(FFX_VariableShading_TileCenterOffset1D, FFX_VariableShading_TileCenterOffset1D);
135+
FfxFloat32x2 dxy = tileRenderingTargetCoords - FoveationCenter();
136+
FfxFloat32 distSquared = dot(dxy, dxy);
137+
138+
FfxUInt32 shadingRate;
139+
if (distSquared < FoveationRadiiSquared().x) // 1X1
140+
{
141+
shadingRate = FFX_VARIABLESHADING_MAKE_SHADING_RATE(FFX_VARIABLESHADING_RATE1D_1X, FFX_VARIABLESHADING_RATE1D_1X);
142+
}
143+
else if (distSquared < FoveationRadiiSquared().y) // 1X2 or 2X1
144+
{
145+
bool horizontal = abs(dxy.x) > abs(dxy.y);
146+
shadingRate = FFX_VARIABLESHADING_MAKE_SHADING_RATE(horizontal ? FFX_VARIABLESHADING_RATE1D_1X : FFX_VARIABLESHADING_RATE1D_2X, horizontal ? FFX_VARIABLESHADING_RATE1D_2X : FFX_VARIABLESHADING_RATE1D_1X);
147+
}
148+
#if !defined FFX_VARIABLESHADING_ADDITIONALSHADINGRATES
149+
else // 2X2
150+
{
151+
shadingRate = FFX_VARIABLESHADING_MAKE_SHADING_RATE(FFX_VARIABLESHADING_RATE1D_2X, FFX_VARIABLESHADING_RATE1D_2X);
152+
}
153+
#else // if defined FFX_VARIABLESHADING_ADDITIONALSHADINGRATES
154+
else if (distSquared < FoveationRadiiSquared().z) // 2X2
155+
{
156+
shadingRate = FFX_VARIABLESHADING_MAKE_SHADING_RATE(FFX_VARIABLESHADING_RATE1D_2X, FFX_VARIABLESHADING_RATE1D_2X);
157+
}
158+
else if (distSquared < FoveationRadiiSquared().w) // 2X4 or 4X2
159+
{
160+
bool horizontal = abs(dxy.x) > abs(dxy.y);
161+
shadingRate = FFX_VARIABLESHADING_MAKE_SHADING_RATE(horizontal ? FFX_VARIABLESHADING_RATE1D_2X : FFX_VARIABLESHADING_RATE1D_4X, horizontal ? FFX_VARIABLESHADING_RATE1D_4X : FFX_VARIABLESHADING_RATE1D_2X);
162+
}
163+
else // 4X4
164+
{
165+
shadingRate = FFX_VARIABLESHADING_MAKE_SHADING_RATE(FFX_VARIABLESHADING_RATE1D_4X, FFX_VARIABLESHADING_RATE1D_4X);
166+
}
167+
#endif
168+
return shadingRate;
169+
}
170+
121171
// Read luminance value from previous frame's color buffer.
122172
FfxFloat32 VrsGetLuminance(FfxInt32x2 pos)
123173
{
@@ -152,6 +202,24 @@ FfxInt32 VrsFlattenLdsOffset(FfxInt32x2 coord)
152202
/// @ingroup FfxGPUVrs
153203
void VrsGenerateVrsImage(FfxUInt32x3 Gid, FfxUInt32x3 Gtid, FfxUInt32 Gidx)
154204
{
205+
FfxUInt32 foveatedShadingRate = FFX_VARIABLESHADING_MAKE_SHADING_RATE(FFX_VARIABLESHADING_RATE1D_1X, FFX_VARIABLESHADING_RATE1D_1X);
206+
if ((VrsAlgorithm() & FFX_VARIABLESHADING_IMAGE_ALGORITHM_FOVEATED) != 0)
207+
{
208+
foveatedShadingRate = VrsComputeFoveatedShadingRate(Gid, Gtid, Gidx);
209+
}
210+
211+
// if motion based algorithm is disabled, or if foveation is returning coarsest rate already, early exit
212+
if (((VrsAlgorithm() & FFX_VARIABLESHADING_IMAGE_ALGORITHM_LUMINANCE_AND_MOTION_VECTORS) == 0) ||
213+
(foveatedShadingRate == FFX_VARIABLESHADING_MAKE_SHADING_RATE(FFX_VARIABLESHADING_RATE1D_2X, FFX_VARIABLESHADING_RATE1D_2X)))
214+
{
215+
if (Gidx < FFX_VariableShading_NumBlocks)
216+
{
217+
WriteVrsImage(
218+
FfxInt32x2(Gid.xy * FFX_VariableShading_NumBlocks1D + FfxUInt32x2(Gidx / FFX_VariableShading_NumBlocks1D, Gidx % FFX_VariableShading_NumBlocks1D)), foveatedShadingRate);
219+
}
220+
return;
221+
}
222+
155223
FfxInt32x2 tileOffset = FfxInt32x2(Gid.xy * FFX_VariableShading_ThreadCount1D * 2);
156224
FfxInt32x2 baseOffset = tileOffset + FfxInt32x2(-2, -2);
157225
FfxUInt32 index = Gidx;
@@ -315,6 +383,9 @@ void VrsGenerateVrsImage(FfxUInt32x3 Gid, FfxUInt32x3 Gtid, FfxUInt32 Gidx)
315383
shadingRate = FFX_VARIABLESHADING_MAKE_SHADING_RATE((varH > VarianceCutoff()) ? FFX_VARIABLESHADING_RATE1D_1X : FFX_VARIABLESHADING_RATE1D_2X, FFX_VARIABLESHADING_RATE1D_1X);
316384
}
317385
}
386+
387+
shadingRate = FFX_VARIABLESHADING_SHADING_RATE_2D_MAX(shadingRate, foveatedShadingRate);
388+
318389
// Store
319390
WriteVrsImage(
320391
FfxInt32x2(Gid.xy * FFX_VariableShading_NumBlocks1D + FfxUInt32x2(Gidx / FFX_VariableShading_NumBlocks1D, Gidx % FFX_VariableShading_NumBlocks1D)), shadingRate);
@@ -333,6 +404,24 @@ void VrsGenerateVrsImage(FfxUInt32x3 Gid, FfxUInt32x3 Gtid, FfxUInt32 Gidx)
333404
/// @ingroup FfxGPUVrs
334405
void VrsGenerateVrsImage(FfxUInt32x3 Gid, FfxUInt32x3 Gtid, FfxUInt32 Gidx)
335406
{
407+
FfxUInt32 foveatedShadingRate = FFX_VARIABLESHADING_MAKE_SHADING_RATE(FFX_VARIABLESHADING_RATE1D_1X, FFX_VARIABLESHADING_RATE1D_1X);
408+
if ((VrsAlgorithm() & FFX_VARIABLESHADING_IMAGE_ALGORITHM_FOVEATED) != 0)
409+
{
410+
foveatedShadingRate = VrsComputeFoveatedShadingRate(Gid, Gtid, Gidx);
411+
}
412+
413+
// if motion based algorithm is disabled, or if foveation is returning coarsest rate already, early exit
414+
if (((VrsAlgorithm() & FFX_VARIABLESHADING_IMAGE_ALGORITHM_LUMINANCE_AND_MOTION_VECTORS) == 0) ||
415+
(foveatedShadingRate == FFX_VARIABLESHADING_MAKE_SHADING_RATE(FFX_VARIABLESHADING_RATE1D_4X, FFX_VARIABLESHADING_RATE1D_4X)))
416+
{
417+
if (Gidx < FFX_VariableShading_TilesPerGroup)
418+
{
419+
WriteVrsImage(
420+
FfxInt32x2(Gid.xy * FFX_VariableShading_NumBlocks1D + FfxUInt32x2(Gidx / FFX_VariableShading_NumBlocks1D, Gidx % FFX_VariableShading_NumBlocks1D)), foveatedShadingRate);
421+
}
422+
return;
423+
}
424+
336425
FfxInt32x2 tileOffset = FfxInt32x2(Gid.xy * FFX_VariableShading_ThreadCount1D * 4);
337426
FfxInt32x2 baseOffset = tileOffset;
338427
FfxUInt32 index = Gidx;
@@ -469,6 +558,8 @@ void VrsGenerateVrsImage(FfxUInt32x3 Gid, FfxUInt32x3 Gtid, FfxUInt32 Gidx)
469558
// write out final rates
470559
if (Gidx < FFX_VariableShading_TilesPerGroup)
471560
{
561+
FFX_VariableShading_LdsGroupReduce[Gidx] = FFX_VARIABLESHADING_SHADING_RATE_2D_MAX(FFX_VariableShading_LdsGroupReduce[Gidx], foveatedShadingRate);
562+
472563
WriteVrsImage(
473564
FfxInt32x2(Gid.xy * FFX_VariableShading_NumBlocks1D + FfxUInt32x2(Gidx / FFX_VariableShading_NumBlocks1D, Gidx % FFX_VariableShading_NumBlocks1D)),
474565
FFX_VariableShading_LdsGroupReduce[Gidx]);
@@ -477,6 +568,8 @@ void VrsGenerateVrsImage(FfxUInt32x3 Gid, FfxUInt32x3 Gtid, FfxUInt32 Gidx)
477568
// write out final rates
478569
if (Gidx < FFX_VariableShading_TilesPerGroup)
479570
{
571+
shadingRate[Gidx] = FFX_VARIABLESHADING_SHADING_RATE_2D_MAX(shadingRate[Gidx], foveatedShadingRate);
572+
480573
WriteVrsImage(
481574
FfxInt32x2(Gid.xy * FFX_VariableShading_NumBlocks1D + FfxUInt32x2(Gidx / FFX_VariableShading_NumBlocks1D, Gidx % FFX_VariableShading_NumBlocks1D)),
482575
shadingRate[Gidx]);

sdk/include/FidelityFX/gpu/vrs/ffx_vrs_callbacks_glsl.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,13 @@
3333
layout(set = 0, binding = VRS_BIND_CB_VRS, std140) uniform cbVRS_t
3434
{
3535
FfxFloat32x2 motionVectorScale;
36+
FfxFloat32x2 foveationCenter;
37+
FfxFloat32x4 foveationRadiiSquared;
3638
FfxFloat32 varianceCutoff;
3739
FfxFloat32 motionFactor;
3840
FfxInt32x2 resolution;
3941
FfxUInt32 tileSize;
42+
FfxUInt32 vrsAlgorithm;
4043
} cbVRS;
4144

4245
#endif
@@ -86,6 +89,33 @@ FfxFloat32x2 MotionVectorScale()
8689
#endif
8790
}
8891

92+
FfxFloat32x2 FoveationCenter()
93+
{
94+
#if defined(VRS_BIND_CB_VRS)
95+
return cbVRS.foveationCenter;
96+
#else
97+
return FfxFloat32x2(0.0f);
98+
#endif
99+
}
100+
101+
FfxFloat32x4 FoveationRadiiSquared()
102+
{
103+
#if defined(VRS_BIND_CB_VRS)
104+
return cbVRS.foveationRadiiSquared;
105+
#else
106+
return FfxFloat32x4(0.0f);
107+
#endif
108+
}
109+
110+
FfxUInt32 VrsAlgorithm()
111+
{
112+
#if defined(VRS_BIND_CB_VRS)
113+
return cbVRS.vrsAlgorithm;
114+
#else
115+
return 0;
116+
#endif
117+
}
118+
89119
// SRVs
90120
#if defined VRS_BIND_SRV_INPUT_COLOR
91121
layout (set = 0, binding = VRS_BIND_SRV_INPUT_COLOR) uniform texture2D r_input_color;

0 commit comments

Comments
 (0)