Skip to content

Commit f76abc1

Browse files
Paulm-UnityEvergreen
authored andcommitted
Shader optimizations/light indexing 16bitpacked
1 parent fd32284 commit f76abc1

5 files changed

Lines changed: 22 additions & 39 deletions

File tree

Packages/com.unity.render-pipelines.universal/ShaderLibrary/RealtimeLights.hlsl

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -195,39 +195,28 @@ uint GetPerObjectLightIndexOffset()
195195
// This abstract the underlying data implementation for storing lights/light indices
196196
int GetPerObjectLightIndex(uint index)
197197
{
198+
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
198199
/////////////////////////////////////////////////////////////////////////////////////////////
199200
// Structured Buffer Path /
200201
// /
201202
// Lights and light indices are stored in StructuredBuffer. We can just index them. /
202203
// Currently all non-mobile platforms take this path :( /
203204
// There are limitation in mobile GPUs to use SSBO (performance / no vertex shader support) /
204205
/////////////////////////////////////////////////////////////////////////////////////////////
205-
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
206206
uint offset = uint(unity_LightData.x);
207207
return _AdditionalLightsIndices[offset + index];
208-
208+
#else
209209
/////////////////////////////////////////////////////////////////////////////////////////////
210210
// UBO path /
211211
// /
212-
// We store 8 light indices in half4 unity_LightIndices[2]; /
213-
// Due to memory alignment unity doesn't support int[] or float[] /
214-
// Even trying to reinterpret cast the unity_LightIndices to float[] won't work /
215-
// it will cast to float4[] and create extra register pressure. :( /
212+
// We pack 8 x 16bit uint light indices into float4 unity_PackedLightIndices; /
213+
// light index 0 is packed into lower 16 bits of unity_PackedLightIndices.x, /
214+
// light index 1 is packed into high 16 bits of unity_PackedLightIndices.x and so on /
216215
/////////////////////////////////////////////////////////////////////////////////////////////
217-
#else
218-
// since index is uint shader compiler will implement
219-
// div & mod as bitfield ops (shift and mask).
220-
221-
// TODO: Can we index a float4? Currently compiler is
222-
// replacing unity_LightIndicesX[i] with a dp4 with identity matrix.
223-
// u_xlat16_40 = dot(unity_LightIndices[int(u_xlatu13)], ImmCB_0_0_0[u_xlati1]);
224-
// This increases both arithmetic and register pressure.
225-
//
226-
// NOTE: min16float4 bug workaround.
227-
// Take the "vec4" part into float4 tmp variable in order to force float4 math.
228-
// It appears indexing half4 as min16float4 on DX11 can fail. (dp4 {min16f})
229-
float4 tmp = unity_LightIndices[index / 4];
230-
return int(tmp[index % 4]);
216+
uint4 packed4 = asuint(unity_PackedLightIndices);
217+
uint2 pair = index >= 4 ? packed4.zw : packed4.xy;
218+
uint word = (index & 2) ? pair.y : pair.x;
219+
return (word >> ((index & 1) << 4)) & 0xFFFF;
231220
#endif
232221
}
233222

Packages/com.unity.render-pipelines.universal/ShaderLibrary/UnityInput.hlsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ float4 unity_RenderingLayer;
120120

121121
// Light Indices block feature
122122
// These are set internally by the engine upon request by RendererConfiguration.
123+
float4 unity_PackedLightIndices;
123124
half4 unity_LightData;
124-
half4 unity_LightIndices[2];
125125

126126
float4 unity_ProbesOcclusion;
127127

Packages/com.unity.render-pipelines.universal/ShaderLibrary/UniversalDOTSInstancing.hlsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ UNITY_DOTS_INSTANCING_END(BuiltinPropertyMetadata)
4848

4949
// Not supported by BatchRendererGroup. Just define them as constants.
5050
// ------------------------------------------------------------------------------
51-
static const float2x4 unity_LightIndices = float2x4(0,0,0,0, 0,0,0,0);
51+
static const float4 unity_PackedLightIndices = float4(0,0,0,0);
5252

5353
static const float4 unity_SpecCube0_BoxMax = float4(1,1,1,1);
5454
static const float4 unity_SpecCube0_BoxMin = float4(0,0,0,0);

Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/Lighting.hlsl

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -202,34 +202,28 @@ int GetPerObjectLightIndex(uint index)
202202
{
203203

204204
#ifndef BUILTIN_TARGET_API
205+
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
205206
/////////////////////////////////////////////////////////////////////////////////////////////
206207
// Structured Buffer Path /
207208
// /
208209
// Lights and light indices are stored in StructuredBuffer. We can just index them. /
209210
// Currently all non-mobile platforms take this path :( /
210211
// There are limitation in mobile GPUs to use SSBO (performance / no vertex shader support) /
211212
/////////////////////////////////////////////////////////////////////////////////////////////
212-
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
213-
uint offset = unity_LightData.x;
213+
uint offset = uint(unity_LightData.x);
214214
return _AdditionalLightsIndices[offset + index];
215-
215+
#else
216216
/////////////////////////////////////////////////////////////////////////////////////////////
217217
// UBO path /
218218
// /
219-
// We store 8 light indices in float4 unity_LightIndices[2]; /
220-
// Due to memory alignment unity doesn't support int[] or float[] /
221-
// Even trying to reinterpret cast the unity_LightIndices to float[] won't work /
222-
// it will cast to float4[] and create extra register pressure. :( /
219+
// We pack 8 x 16bit uint light indices into float4 unity_packedLightIndices; /
220+
// light index 0 is packed into lower 16 bits of unity_packedLightIndices.x, /
221+
// light index 1 is packed into high 16 bits of unity_packedLightIndices.x and so on /
223222
/////////////////////////////////////////////////////////////////////////////////////////////
224-
#else
225-
// since index is uint shader compiler will implement
226-
// div & mod as bitfield ops (shift and mask).
227-
228-
// TODO: Can we index a float4? Currently compiler is
229-
// replacing unity_LightIndicesX[i] with a dp4 with identity matrix.
230-
// u_xlat16_40 = dot(unity_LightIndices[int(u_xlatu13)], ImmCB_0_0_0[u_xlati1]);
231-
// This increases both arithmetic and register pressure.
232-
return unity_LightIndices[index / 4][index % 4];
223+
uint4 packed4 = asuint(unity_PackedLightIndices);
224+
uint2 pair = index >= 4 ? packed4.zw : packed4.xy;
225+
uint word = (index & 2) ? pair.y : pair.x;
226+
return (word >> ((index & 1) << 4)) & 0xFFFF;
233227
#endif
234228
#else
235229
return 0;

Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/UnityInput.hlsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ real4 unity_WorldTransformParams; // w is usually 1.0, or -1.0 for odd-negative
107107

108108
// Light Indices block feature
109109
// These are set internally by the engine upon request by RendererConfiguration.
110+
float4 unity_PackedLightIndices;
110111
real4 unity_LightData;
111-
real4 unity_LightIndices[2];
112112

113113
float4 unity_ProbesOcclusion;
114114

0 commit comments

Comments
 (0)