@@ -44,9 +44,6 @@ uniform vec2 shadowAtlasParams;
4444// it's sorted to have all vectors aligned to 4 floats to limit padding
4545struct ClusterLightData {
4646
47- // 32bit of flags
48- uint flags;
49-
5047 // area light sizes / orientation
5148 vec3 halfWidth;
5249
@@ -88,16 +85,10 @@ struct ClusterLightData {
8885 // compressed biases, two haf-floats stored in a float
8986 float biasesData;
9087
91- // blue color component and angle flags (as uint for efficient bit operations)
92- uint colorBFlagsData;
93-
9488 // shadow bias values
9589 float shadowBias;
9690 float shadowNormalBias;
9791
98- // compressed angles, two haf-floats stored in a float
99- float anglesData;
100-
10192 // spot light inner and outer angle cosine
10293 float innerConeAngleCos;
10394 float outerConeAngleCos;
@@ -118,6 +109,12 @@ struct ClusterLightData {
118109// shadow (spot light only) / cookie projection matrix
119110mat4 lightProjectionMatrix;
120111
112+ // NOTE: On some Samsung devices, these values can suffer precision / corruption issues when stored
113+ // as members of ClusterLightData. Keep them as module-scope temporaries instead. See issue #7800.
114+ uint clusterLightData_flags; // 32bit of flags
115+ float clusterLightData_anglesData; // compressed angles, two haf-floats stored in a float
116+ uint clusterLightData_colorBFlagsData; // blue color component and angle flags (as uint for efficient bit operations)
117+
121118vec4 sampleLightTextureF(const ClusterLightData clusterLightData, int index) {
122119 return texelFetch(lightsTexture, ivec2(index, clusterLightData.lightIndex), 0);
123120}
@@ -131,13 +128,13 @@ void decodeClusterLightCore(inout ClusterLightData clusterLightData, int lightIn
131128 vec4 halfData = sampleLightTextureF(clusterLightData, {CLUSTER_TEXTURE_COLOR_ANGLES_BIAS});
132129
133130 // store floats we decode later as needed
134- clusterLightData.anglesData = halfData.z;
131+ clusterLightData_anglesData = halfData.z;
135132 clusterLightData.biasesData = halfData.w;
136- clusterLightData.colorBFlagsData = floatBitsToUint(halfData.y);
133+ clusterLightData_colorBFlagsData = floatBitsToUint(halfData.y);
137134
138135 // decompress color half-floats
139136 vec2 colorRG = unpackHalf2x16(floatBitsToUint(halfData.x));
140- vec2 colorB_flags = unpackHalf2x16(clusterLightData.colorBFlagsData );
137+ vec2 colorB_flags = unpackHalf2x16(clusterLightData_colorBFlagsData );
141138 clusterLightData.color = vec3(colorRG, colorB_flags.x) * {LIGHT_COLOR_DIVIDER};
142139
143140 // position and range, full floats
@@ -152,21 +149,21 @@ void decodeClusterLightCore(inout ClusterLightData clusterLightData, int lightIn
152149 clusterLightData.direction = lightDir_Flags.xyz;
153150
154151 // 32bit flags
155- clusterLightData.flags = floatBitsToUint(lightDir_Flags.w);
156- clusterLightData.isSpot = (clusterLightData.flags & (1u << 30u)) != 0u;
157- clusterLightData.shape = (clusterLightData.flags >> 28u) & 0x3u;
158- clusterLightData.falloffModeLinear = (clusterLightData.flags & (1u << 27u)) == 0u;
159- clusterLightData.shadowIntensity = float((clusterLightData.flags >> 0u) & 0xFFu) / 255.0;
160- clusterLightData.cookieIntensity = float((clusterLightData.flags >> 8u) & 0xFFu) / 255.0;
161- clusterLightData.isDynamic = (clusterLightData.flags & (1u << 22u)) != 0u;
162- clusterLightData.isLightmapped = (clusterLightData.flags & (1u << 21u)) != 0u;
152+ clusterLightData_flags = floatBitsToUint(lightDir_Flags.w);
153+ clusterLightData.isSpot = (clusterLightData_flags & (1u << 30u)) != 0u;
154+ clusterLightData.shape = (clusterLightData_flags >> 28u) & 0x3u;
155+ clusterLightData.falloffModeLinear = (clusterLightData_flags & (1u << 27u)) == 0u;
156+ clusterLightData.shadowIntensity = float((clusterLightData_flags >> 0u) & 0xFFu) / 255.0;
157+ clusterLightData.cookieIntensity = float((clusterLightData_flags >> 8u) & 0xFFu) / 255.0;
158+ clusterLightData.isDynamic = (clusterLightData_flags & (1u << 22u)) != 0u;
159+ clusterLightData.isLightmapped = (clusterLightData_flags & (1u << 21u)) != 0u;
163160}
164161
165162void decodeClusterLightSpot(inout ClusterLightData clusterLightData) {
166163 // decompress spot light angles
167- uint angleFlags = (clusterLightData.colorBFlagsData >> 16u) & 0xFFFFu; // Extract upper 16 bits as integer
164+ uint angleFlags = (clusterLightData_colorBFlagsData >> 16u) & 0xFFFFu; // Extract upper 16 bits as integer
168165
169- vec2 angleValues = unpackHalf2x16(floatBitsToUint(clusterLightData.anglesData ));
166+ vec2 angleValues = unpackHalf2x16(floatBitsToUint(clusterLightData_anglesData ));
170167 float innerVal = angleValues.x;
171168 float outerVal = angleValues.y;
172169
@@ -207,7 +204,7 @@ void decodeClusterLightShadowData(inout ClusterLightData clusterLightData) {
207204void decodeClusterLightCookieData(inout ClusterLightData clusterLightData) {
208205
209206 // extract channel mask from flags
210- uint cookieFlags = (clusterLightData.flags >> 23u) & 0x0Fu; // 4bits, each bit enables a channel
207+ uint cookieFlags = (clusterLightData_flags >> 23u) & 0x0Fu; // 4bits, each bit enables a channel
211208 clusterLightData.cookieChannelMask = vec4(uvec4(cookieFlags) & uvec4(1u, 2u, 4u, 8u));
212209 clusterLightData.cookieChannelMask = step(1.0, clusterLightData.cookieChannelMask); // Normalize to 0.0 or 1.0
213210}
0 commit comments