Workaround for a bug in Adreno's shader compiler

At least some adreno compilers don't like returning an element of a
UBO array that is a structure in the vertex shader.
To work this around we have to copy the each of the structure fields.

Fixes #6355
This commit is contained in:
Mathias Agopian
2022-12-14 15:39:18 -08:00
committed by Mathias Agopian
parent aa5504aad3
commit ee6612ecfa
13 changed files with 69 additions and 53 deletions
+1
View File
@@ -13,6 +13,7 @@ A new header is inserted each time a *tag* is created.
- web: added TypeScript definition for `Engine.destroy`
- materials: `getNormalizedViewportCoord()` now returns the logical (i.e. user) viewport
normalized position and keeps z reversed [⚠️ **Recompile Materials**]
- backend: workaround Adreno shader compiler bug (#6355) [⚠️ **Recompile Materials**]
## v1.30.0
@@ -662,9 +662,11 @@ io::sstream& CodeGenerator::generateCommon(io::sstream& out, ShaderStage stage)
switch (stage) {
case ShaderStage::VERTEX:
out << SHADERS_COMMON_INSTANCING_GLSL_DATA;
out << SHADERS_COMMON_SHADOWING_GLSL_DATA;
break;
case ShaderStage::FRAGMENT:
out << SHADERS_COMMON_INSTANCING_GLSL_DATA;
out << SHADERS_COMMON_SHADOWING_GLSL_DATA;
out << SHADERS_COMMON_SHADING_FS_DATA;
out << SHADERS_COMMON_GRAPHICS_FS_DATA;
+1 -1
View File
@@ -104,7 +104,7 @@ fragment {
material.metallic = materialParams.metallicFactor;
material.transmission = materialParams.transmissionFactor;
material.absorption = materialParams.volumeAbsorption;
material.thickness = materialParams.volumeThicknessFactor * getObjectUniforms().userData;
material.thickness = materialParams.volumeThicknessFactor * getObjectUserData();
material.ior = materialParams.ior;
material.emissive = vec4(materialParams.emissiveStrength *
+1
View File
@@ -16,6 +16,7 @@ set(SHADERS
src/brdf.fs
src/common_defines.glsl
src/common_getters.glsl
src/common_instancing.glsl
src/common_graphics.fs
src/common_lighting.fs
src/common_material.fs
+35
View File
@@ -0,0 +1,35 @@
//------------------------------------------------------------------------------
// Instancing
// ------------------------------------------------------------------------------------------------
PerRenderableData object_uniforms;
void initObjectUniforms(out PerRenderableData p) {
#if defined(MATERIAL_HAS_INSTANCES)
// the material manages instancing, all instances share the same uniform block.
p = objectUniforms.data[0];
#else
// automatic instancing was used, each instance has its own uniform block.
// We're copying each field separately to workaround an issue in some Adreno drivers
// that fail on non-const array access in a UBO. Accessing the fields works however.
// e.g.: this fails `p = objectUniforms.data[instance_index];`
p.worldFromModelMatrix = objectUniforms.data[instance_index].worldFromModelMatrix;
p.worldFromModelNormalMatrix = objectUniforms.data[instance_index].worldFromModelNormalMatrix;
p.morphTargetCount = objectUniforms.data[instance_index].morphTargetCount;
p.flagsChannels = objectUniforms.data[instance_index].flagsChannels;
p.objectId = objectUniforms.data[instance_index].objectId;
p.userData = objectUniforms.data[instance_index].userData;
#endif
}
//------------------------------------------------------------------------------
// Instance access
//------------------------------------------------------------------------------
#if defined(MATERIAL_HAS_INSTANCES)
/** @public-api */
int getInstanceIndex() {
return instance_index;
}
#endif
+1 -1
View File
@@ -47,7 +47,7 @@ void main() {
fragColor.xy = computeDepthMomentsVSM(depth);
fragColor.zw = computeDepthMomentsVSM(-1.0 / depth); // requires at least RGBA16F
#elif defined(VARIANT_HAS_PICKING)
outPicking.x = getObjectUniforms().objectId;
outPicking.x = object_uniforms.objectId;
outPicking.y = floatBitsToUint(vertex_position.z / vertex_position.w);
#else
// that's it
+4 -15
View File
@@ -1,13 +1,11 @@
//------------------------------------------------------------------------------
// Instance access
// Uniforms access
//------------------------------------------------------------------------------
#if defined(MATERIAL_HAS_INSTANCES)
/** @public-api */
int getInstanceIndex() {
return instance_index;
/** sort-of public */
float getObjectUserData() {
return object_uniforms.userData;
}
#endif
//------------------------------------------------------------------------------
// Attributes access
@@ -142,12 +140,3 @@ highp vec4 getCascadeLightSpacePosition(uint cascade) {
#endif
PerRenderableData getObjectUniforms() {
#if defined(MATERIAL_HAS_INSTANCES)
// the material manages instancing, all instances share the same uniform block.
return objectUniforms.data[0];
#else
// automatic instancing was used, each instance has its own uniform block.
return objectUniforms.data[instance_index];
#endif
}
+11 -27
View File
@@ -1,36 +1,20 @@
//------------------------------------------------------------------------------
// Instance access
//------------------------------------------------------------------------------
#if defined(MATERIAL_HAS_INSTANCES)
/** @public-api */
int getInstanceIndex() {
return instance_index;
}
#endif
//------------------------------------------------------------------------------
// Uniforms access
//------------------------------------------------------------------------------
PerRenderableData getObjectUniforms() {
#if defined(MATERIAL_HAS_INSTANCES)
// the material manages instancing, all instances share the same uniform block.
return objectUniforms.data[0];
#else
// automatic instancing was used, each instance has its own uniform block.
return objectUniforms.data[instance_index];
#endif
}
/** @public-api */
mat4 getWorldFromModelMatrix() {
return getObjectUniforms().worldFromModelMatrix;
return object_uniforms.worldFromModelMatrix;
}
/** @public-api */
mat3 getWorldFromModelNormalMatrix() {
return getObjectUniforms().worldFromModelNormalMatrix;
return object_uniforms.worldFromModelNormalMatrix;
}
/** sort-of public */
float getObjectUserData() {
return object_uniforms.userData;
}
//------------------------------------------------------------------------------
@@ -94,7 +78,7 @@ void skinPosition(inout vec3 p, const uvec4 ids, const vec4 weights) {
void morphPosition(inout vec4 p) {
ivec3 texcoord = ivec3(getVertexIndex() % MAX_MORPH_TARGET_BUFFER_WIDTH, getVertexIndex() / MAX_MORPH_TARGET_BUFFER_WIDTH, 0);
uint c = getObjectUniforms().morphTargetCount;
uint c = object_uniforms.morphTargetCount;
for (uint i = 0u; i < c; ++i) {
float w = morphingUniforms.weights[i][0];
if (w != 0.0) {
@@ -107,7 +91,7 @@ void morphPosition(inout vec4 p) {
void morphNormal(inout vec3 n) {
vec3 baseNormal = n;
ivec3 texcoord = ivec3(getVertexIndex() % MAX_MORPH_TARGET_BUFFER_WIDTH, getVertexIndex() / MAX_MORPH_TARGET_BUFFER_WIDTH, 0);
uint c = getObjectUniforms().morphTargetCount;
uint c = object_uniforms.morphTargetCount;
for (uint i = 0u; i < c; ++i) {
float w = morphingUniforms.weights[i][0];
if (w != 0.0) {
@@ -127,7 +111,7 @@ vec4 getPosition() {
#if defined(VARIANT_HAS_SKINNING_OR_MORPHING)
if ((getObjectUniforms().flagsChannels & FILAMENT_OBJECT_MORPHING_ENABLED_BIT) != 0u) {
if ((object_uniforms.flagsChannels & FILAMENT_OBJECT_MORPHING_ENABLED_BIT) != 0u) {
#if defined(LEGACY_MORPHING)
pos += morphingUniforms.weights[0] * mesh_custom0;
pos += morphingUniforms.weights[1] * mesh_custom1;
@@ -138,7 +122,7 @@ vec4 getPosition() {
#endif
}
if ((getObjectUniforms().flagsChannels & FILAMENT_OBJECT_SKINNING_ENABLED_BIT) != 0u) {
if ((object_uniforms.flagsChannels & FILAMENT_OBJECT_SKINNING_ENABLED_BIT) != 0u) {
skinPosition(pos.xyz, mesh_bone_indices, mesh_bone_weights);
}
+2 -2
View File
@@ -36,7 +36,7 @@ void evaluateDirectionalLight(const MaterialInputs material,
Light light = getDirectionalLight();
uint channels = getObjectUniforms().flagsChannels & 0xFFu;
uint channels = object_uniforms.flagsChannels & 0xFFu;
if ((light.channels & channels) == 0u) {
return;
}
@@ -60,7 +60,7 @@ void evaluateDirectionalLight(const MaterialInputs material,
visibility = shadow(true, light_shadowMap, cascade, shadowPosition, 0.0f);
}
if ((frameUniforms.directionalShadows & 0x2u) != 0u && visibility > 0.0) {
if ((getObjectUniforms().flagsChannels & FILAMENT_OBJECT_CONTACT_SHADOWS_BIT) != 0u) {
if ((object_uniforms.flagsChannels & FILAMENT_OBJECT_CONTACT_SHADOWS_BIT) != 0u) {
ssContactShadowOcclusion = screenSpaceContactShadow(light.l);
}
}
+2 -2
View File
@@ -191,7 +191,7 @@ void evaluatePunctualLights(const MaterialInputs material,
uint index = froxel.recordOffset;
uint end = index + froxel.count;
uint channels = getObjectUniforms().flagsChannels & 0xFFu;
uint channels = object_uniforms.flagsChannels & 0xFFu;
// Iterate point lights
for ( ; index < end; index++) {
@@ -225,7 +225,7 @@ void evaluatePunctualLights(const MaterialInputs material,
shadowPosition, light.zLight);
}
if (light.contactShadows && visibility > 0.0) {
if ((getObjectUniforms().flagsChannels & FILAMENT_OBJECT_CONTACT_SHADOWS_BIT) != 0u) {
if ((object_uniforms.flagsChannels & FILAMENT_OBJECT_CONTACT_SHADOWS_BIT) != 0u) {
visibility *= 1.0 - screenSpaceContactShadow(light.l);
}
}
+2
View File
@@ -19,6 +19,8 @@ void blendPostLightingColor(const MaterialInputs material, inout vec4 color) {
void main() {
filament_lodBias = frameUniforms.lodBias;
initObjectUniforms(object_uniforms);
// See shading_parameters.fs
// Computes global variables we need to evaluate material and lighting
computeShadingParams();
+6 -4
View File
@@ -13,6 +13,8 @@ void main() {
instance_index = gl_InstanceID;
#endif
initObjectUniforms(object_uniforms);
// Initialize the inputs to sensible default values, see material_inputs.vs
#if defined(USE_OPTIMIZED_DEPTH_VERTEX_SHADER)
@@ -41,7 +43,7 @@ void main() {
toTangentFrame(mesh_tangents, material.worldNormal, vertex_worldTangent.xyz);
#if defined(VARIANT_HAS_SKINNING_OR_MORPHING)
if ((getObjectUniforms().flagsChannels & FILAMENT_OBJECT_MORPHING_ENABLED_BIT) != 0u) {
if ((object_uniforms.flagsChannels & FILAMENT_OBJECT_MORPHING_ENABLED_BIT) != 0u) {
#if defined(LEGACY_MORPHING)
vec3 normal0, normal1, normal2, normal3;
toTangentFrame(mesh_custom4, normal0);
@@ -59,7 +61,7 @@ void main() {
#endif
}
if ((getObjectUniforms().flagsChannels & FILAMENT_OBJECT_SKINNING_ENABLED_BIT) != 0u) {
if ((object_uniforms.flagsChannels & FILAMENT_OBJECT_SKINNING_ENABLED_BIT) != 0u) {
skinNormal(material.worldNormal, mesh_bone_indices, mesh_bone_weights);
skinNormal(vertex_worldTangent.xyz, mesh_bone_indices, mesh_bone_weights);
}
@@ -77,7 +79,7 @@ void main() {
toTangentFrame(mesh_tangents, material.worldNormal);
#if defined(VARIANT_HAS_SKINNING_OR_MORPHING)
if ((getObjectUniforms().flagsChannels & FILAMENT_OBJECT_MORPHING_ENABLED_BIT) != 0u) {
if ((object_uniforms.flagsChannels & FILAMENT_OBJECT_MORPHING_ENABLED_BIT) != 0u) {
#if defined(LEGACY_MORPHING)
vec3 normal0, normal1, normal2, normal3;
toTangentFrame(mesh_custom4, normal0);
@@ -95,7 +97,7 @@ void main() {
#endif
}
if ((getObjectUniforms().flagsChannels & FILAMENT_OBJECT_SKINNING_ENABLED_BIT) != 0u) {
if ((object_uniforms.flagsChannels & FILAMENT_OBJECT_SKINNING_ENABLED_BIT) != 0u) {
skinNormal(material.worldNormal, mesh_bone_indices, mesh_bone_weights);
}
#endif
+1 -1
View File
@@ -54,7 +54,7 @@ vec4 evaluateMaterial(const MaterialInputs material) {
visibility = shadow(true, light_shadowMap, cascade, shadowPosition, 0.0f);
}
if ((frameUniforms.directionalShadows & 0x2u) != 0u && visibility > 0.0) {
if ((getObjectUniforms().flagsChannels & FILAMENT_OBJECT_CONTACT_SHADOWS_BIT) != 0u) {
if ((object_uniforms.flagsChannels & FILAMENT_OBJECT_CONTACT_SHADOWS_BIT) != 0u) {
visibility *= (1.0 - screenSpaceContactShadow(frameUniforms.lightDirection));
}
}