浏览代码

Fix flickering issues on PS4 for the single pass loop (+ initial fixes for FPTL)

Flickering is caused by the delay between values in the constant buffer (globals) and values in structured buffers becoming visible in the Deferred shader. It appears that the update latency (the number of frames between setting the value in C# and being able to access it in a shader) varies depending on the type of buffer. Therefore, moving globals into a structured buffer provides a workaround for the single pass loop.

Doing the same for FPTL does not appear to be sufficient. Could be that the additional compute pass introduces extra frame(s) of latency, or that globals from ShaderVariables.hlsl need to be moved as well.

Globals from Clustered appear to be set once for multiple shaders, which makes implementing a similar workarond even more complicated.
/fptl_cleanup
Evgenii Golubev 7 年前
当前提交
5a2aa8b3
共有 5 个文件被更改,包括 95 次插入42 次删除
  1. 7
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  2. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Resources/Deferred.shader
  3. 58
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs
  4. 49
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.hlsl
  5. 21
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl

7
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


cmd.SetGlobalMatrix("_InvProjMatrix", hdCamera.invProjectionMatrix);
cmd.SetGlobalVector("_InvProjParam", hdCamera.invProjectionParam);
// TODO: cmd.SetGlobalInt() does not exist, so we are forced to use Shader.SetGlobalInt() instead.
// TODO: setting the Sky Settings to 'None' appears to do nothing (so no invalidation happens).
Shader.EnableKeyword("SKY_LIGHTING");
Shader.SetGlobalInt("_EnvLightSkyEnabled", 1);
Shader.SetGlobalInt("_EnvLightSkyEnabled", 0);
Shader.DisableKeyword("SKY_LIGHTING");
}
// Broadcast SSS parameters to all shaders.

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Resources/Deferred.shader


#pragma shader_feature _ SSS_PRE_SCATTER_TEXTURING SSS_POST_SCATTER_TEXTURING
// #endif
#pragma shader_feature SKY_LIGHTING
#pragma multi_compile _ LIGHTING_DEBUG
//-------------------------------------------------------------------------------------

58
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs


public const int k_MaxCascadeCount = 4; //Should be not less than m_Settings.directionalLightCascadeCount;
// Static keyword is required here else we get a "DestroyBuffer can only be call in main thread"
static ComputeBuffer s_LightingSettings = null; // We use a structured buffer instead of a constant buffer due to the delay between setting values via constant and other buffer types on PS4
static ComputeBuffer s_DirectionalLightDatas = null;
static ComputeBuffer s_LightDatas = null;
static ComputeBuffer s_EnvLightDatas = null;

int m_areaLightCount = 0;
int m_lightCount = 0;
// See LightingSettings in TilePass.hlsl.
public struct LightingSettings
{
public uint directionalLightCount;
public uint punctualLightCount;
public uint areaLightCount;
public uint envLightCount;
public uint numTileFtplX;
public uint numTileFtplY;
// public uint numTileClusteredX;
// public uint numTileClusteredY;
// public uint isLogBaseBufferEnabled;
// public uint log2NumClusters;
// public float clusterScale;
// public float clusterBase;
// public float nearPlane;
// public float farPlane;
public Vector4 dirShadowSplitSpheres0;
public Vector4 dirShadowSplitSpheres1;
public Vector4 dirShadowSplitSpheres2;
public Vector4 dirShadowSplitSpheres3;
};
LightingSettings[] m_LightingSettings = new LightingSettings[1];
private ComputeShader buildScreenAABBShader { get { return m_PassResources.buildScreenAABBShader; } }
private ComputeShader buildPerTileLightListShader { get { return m_PassResources.buildPerTileLightListShader; } }
private ComputeShader buildPerBigTileLightListShader { get { return m_PassResources.buildPerBigTileLightListShader; } }

m_lightList = new LightList();
m_lightList.Allocate();
s_LightingSettings = new ComputeBuffer(1, System.Runtime.InteropServices.Marshal.SizeOf(typeof(LightingSettings)));
s_DirectionalLightDatas = new ComputeBuffer(k_MaxDirectionalLightsOnScreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(DirectionalLightData)));
s_LightDatas = new ComputeBuffer(k_MaxPunctualLightsOnScreen + k_MaxAreaLightsOnSCreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(LightData)));
s_EnvLightDatas = new ComputeBuffer(k_MaxEnvLightsOnScreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(EnvLightData)));

UnityEditor.SceneView.onSceneGUIDelegate -= OnSceneGUI;
#endif
Utilities.SafeRelease(s_LightingSettings);
Utilities.SafeRelease(s_DirectionalLightDatas);
Utilities.SafeRelease(s_LightDatas);
Utilities.SafeRelease(s_EnvLightDatas);

SetGlobalTexture("_CookieCubeTextures", m_CubeCookieTexArray.GetTexCache());
SetGlobalTexture("_EnvTextures", m_CubeReflTexArray.GetTexCache());
SetGlobalBuffer("_LightingSettings", s_LightingSettings);
SetGlobalInt("_DirectionalLightCount", m_lightList.directionalLights.Count);
SetGlobalInt("_PunctualLightCount", m_punctualLightCount);
SetGlobalInt("_AreaLightCount", m_areaLightCount);
SetGlobalInt("_EnvLightCount", m_lightList.envLights.Count);
SetGlobalVectorArray("_DirShadowSplitSpheres", m_lightList.directionalShadowSplitSphereSqr);
SetGlobalInt("_NumTileFtplX", GetNumTileFtplX(camera));
SetGlobalInt("_NumTileFtplY", GetNumTileFtplY(camera));
SetGlobalInt("_NumTileClusteredX", GetNumTileClusteredX(camera));
SetGlobalInt("_NumTileClusteredY", GetNumTileClusteredY(camera));

{
var cmd = new CommandBuffer { name = "Push Global Parameters" };
m_LightingSettings[0].directionalLightCount = (uint)m_lightList.directionalLights.Count;
m_LightingSettings[0].punctualLightCount = (uint)m_punctualLightCount;
m_LightingSettings[0].areaLightCount = (uint)m_areaLightCount;
m_LightingSettings[0].envLightCount = (uint)m_lightList.envLights.Count;
m_LightingSettings[0].numTileFtplX = (uint)GetNumTileFtplX(camera);
m_LightingSettings[0].numTileFtplY = (uint)GetNumTileFtplY(camera);
// m_LightingSettings[0].numTileClusteredX = (uint)GetNumTileClusteredX(camera);
// m_LightingSettings[0].numTileClusteredY = (uint)GetNumTileClusteredY(camera);
// m_LightingSettings[0].isLogBaseBufferEnabled = (uint)(k_UseDepthBuffer ? 1 : 0);
// m_LightingSettings[0].log2NumClusters = k_Log2NumClusters;
// m_LightingSettings[0].clusterBase = k_ClustLogBase;
// m_LightingSettings[0].clusterScale = m_ClustScale;
// m_LightingSettings[0].nearPlane = camera.nearClipPlane;
// m_LightingSettings[0].farPlane = camera.farClipPlane;
m_LightingSettings[0].dirShadowSplitSpheres0 = m_lightList.directionalShadowSplitSphereSqr[0];
m_LightingSettings[0].dirShadowSplitSpheres1 = m_lightList.directionalShadowSplitSphereSqr[1];
m_LightingSettings[0].dirShadowSplitSpheres2 = m_lightList.directionalShadowSplitSphereSqr[2];
m_LightingSettings[0].dirShadowSplitSpheres3 = m_lightList.directionalShadowSplitSphereSqr[3];
s_LightingSettings.SetData(m_LightingSettings);
s_DirectionalLightDatas.SetData(m_lightList.directionalLights.ToArray());
s_LightDatas.SetData(m_lightList.lights.ToArray());
s_EnvLightDatas.SetData(m_lightList.envLights.ToArray());

Utilities.SetMatrixCS(cmd, shadeOpaqueShader, "_InvViewProjMatrix", invViewProjection);
Utilities.SetMatrixCS(cmd, shadeOpaqueShader, "_ViewProjMatrix", viewProjection);
Utilities.SetMatrixCS(cmd, shadeOpaqueShader, "g_mInvScrProjection", Shader.GetGlobalMatrix("g_mInvScrProjection"));
cmd.SetComputeVectorParam(shadeOpaqueShader, "_ScreenSize", Shader.GetGlobalVector("_ScreenSize"));
cmd.SetComputeIntParam(shadeOpaqueShader, "_UseTileLightList", Shader.GetGlobalInt("_UseTileLightList"));

cmd.SetComputeVectorParam(shadeOpaqueShader, "_ScreenParams", Shader.GetGlobalVector("_ScreenParams"));
cmd.SetComputeVectorParam(shadeOpaqueShader, "_ZBufferParams", Shader.GetGlobalVector("_ZBufferParams"));
cmd.SetComputeVectorParam(shadeOpaqueShader, "unity_OrthoParams", Shader.GetGlobalVector("unity_OrthoParams"));
cmd.SetComputeIntParam(shadeOpaqueShader, "_EnvLightSkyEnabled", Shader.GetGlobalInt("_EnvLightSkyEnabled"));
Texture skyTexture = Shader.GetGlobalTexture("_SkyTexture");
Texture IESArrayTexture = Shader.GetGlobalTexture("_IESArray");

49
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.hlsl


#include "TilePass.cs.hlsl"
// For FPTL
uint _NumTileFtplX;
uint _NumTileFtplY;
StructuredBuffer<uint> g_vLightListGlobal; // don't support Buffer yet in unity
#ifdef USE_FPTL_LIGHTLIST

// these uniforms are only needed for when OPAQUES_ONLY is NOT defined
// but there's a problem with our front-end compilation of compute shaders with multiple kernels causing it to error
//#ifdef USE_CLUSTERED_LIGHTLIST
float4x4 g_mInvScrProjection;
float g_fClustScale;
float g_fClustBase;
float g_fNearPlane;

StructuredBuffer<float> g_logBaseBuffer; // don't support Buffer yet in unity
//#endif
StructuredBuffer<DirectionalLightData> _DirectionalLightDatas;
StructuredBuffer<LightData> _LightDatas;
StructuredBuffer<EnvLightData> _EnvLightDatas;
StructuredBuffer<ShadowData> _ShadowDatas;
struct LightingSettings
{
uint directionalLightCount;
uint punctualLightCount;
uint areaLightCount;
uint envLightCount;
uint numTileFtplX;
uint numTileFtplY;
// uint numTileClusteredX;
// uint numTileClusteredY;
// uint isLogBaseBufferEnabled;
// uint log2NumClusters;
// float clusterScale;
// float clusterBase;
// float nearPlane;
// float farPlane;
float4 dirShadowSplitSpheres[4]; // TODO: share this max between C# and hlsl
};
// We use a structured buffer instead of a constant buffer due to the delay between setting values via constant and other buffer types on PS4
StructuredBuffer<LightingSettings> _LightingSettings; // 1 element
StructuredBuffer<DirectionalLightData> _DirectionalLightDatas;
StructuredBuffer<LightData> _LightDatas;
StructuredBuffer<EnvLightData> _EnvLightDatas;
StructuredBuffer<ShadowData> _ShadowDatas;
// Use texture atlas for shadow map
//TEXTURE2D(_ShadowAtlas);

TEXTURECUBE(_SkyTexture);
SAMPLERCUBE(sampler_SkyTexture); // NOTE: Sampler could be share here with _EnvTextures. Don't know if the shader compiler will complain...
/*
uint _DirectionalLightCount;
uint _PunctualLightCount;
uint _AreaLightCount;
uint _EnvLightCount;
float4 _DirShadowSplitSpheres[4]; // TODO: share this max between C# and hlsl
int _EnvLightSkyEnabled; // TODO: make it a bool
// See _LightingSettings
*/
struct LightLoopContext
{

float GetDirectionalShadowAttenuation(LightLoopContext lightLoopContext, float3 positionWS, int index, float3 L, float2 unPositionSS)
{
// Note Index is 0 for now, but else we need to provide the correct index in _DirShadowSplitSpheres and _ShadowDatas
int shadowSplitIndex = GetSplitSphereIndexForDirshadows(positionWS, _DirShadowSplitSpheres);
// Note Index is 0 for now, but else we need to provide the correct index in _LightingSettings[0].dirShadowSplitSpheres and _ShadowDatas
int shadowSplitIndex = GetSplitSphereIndexForDirshadows(positionWS, _LightingSettings[0].dirShadowSplitSpheres);
if (shadowSplitIndex == -1)
return 1.0;

21
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl


float shadow = GetDirectionalShadowAttenuation(lightLoopContext, positionWS, 0, float3(0.0, 0.0, 0.0), float2(0.0, 0.0));
#endif
int shadowSplitIndex = GetSplitSphereIndexForDirshadows(positionWS, _DirShadowSplitSpheres);
int shadowSplitIndex = GetSplitSphereIndexForDirshadows(positionWS, _LightingSettings[0].dirShadowSplitSpheres);
if (shadowSplitIndex == -1)
diffuseLighting = float3(0.0, 0.0, 0.0);
else

int GetTileOffset(PositionInputs posInput, uint lightCategory)
{
uint2 tileIndex = posInput.unPositionSS / TILE_SIZE_FPTL;
return (tileIndex.y + lightCategory * _NumTileFtplY) * _NumTileFtplX + tileIndex.x;
return (tileIndex.y + lightCategory * _LightingSettings[0].numTileFtplY) * _LightingSettings[0].numTileFtplX + tileIndex.x;
}
void GetCountAndStartTile(PositionInputs posInput, uint lightCategory, out uint start, out uint lightCount)

uint i = 0; // Declare once to avoid the D3D11 compiler warning.
#ifdef PROCESS_DIRECTIONAL_LIGHT
for (i = 0; i < _DirectionalLightCount; ++i)
for (i = 0; i < _LightingSettings[0].directionalLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;

float3 iblSpecularLighting = float3(0.0, 0.0, 0.0);
// Only apply sky IBL if the sky texture is available.
if (_EnvLightSkyEnabled)
#ifdef SKY_LIGHTING
{
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;

iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
}
#endif
uint envLightStart;
uint envLightCount;

uint i = 0; // Declare once to avoid the D3D11 compiler warning.
for (i = 0; i < _DirectionalLightCount; ++i)
for (i = 0; i < _LightingSettings[0].directionalLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;

specularLighting += localSpecularLighting;
}
for (i = 0; i < _PunctualLightCount; ++i)
for (i = 0; i < _LightingSettings[0].punctualLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;

}
// Area are store with punctual, just offset the index
for (i = _PunctualLightCount; i < _AreaLightCount + _PunctualLightCount; ++i)
for (i = _LightingSettings[0].punctualLightCount; i < _LightingSettings[0].punctualLightCount + _LightingSettings[0].areaLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;

float3 iblSpecularLighting = float3(0.0, 0.0, 0.0);
// Only apply sky IBL if the sky texture is available.
if (_EnvLightSkyEnabled)
#ifdef SKY_LIGHTING
{
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;

iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
}
#endif
for (i = 0; i < _EnvLightCount; ++i)
for (i = 0; i < _LightingSettings[0].envLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;

正在加载...
取消
保存