diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 5251ba28189..4e1db26ac09 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -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 diff --git a/libs/filamat/src/shaders/CodeGenerator.cpp b/libs/filamat/src/shaders/CodeGenerator.cpp index a4c83247733..4feed72219d 100644 --- a/libs/filamat/src/shaders/CodeGenerator.cpp +++ b/libs/filamat/src/shaders/CodeGenerator.cpp @@ -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; diff --git a/libs/gltfio/materials/volume.mat.in b/libs/gltfio/materials/volume.mat.in index 364da896276..2f02f70530e 100644 --- a/libs/gltfio/materials/volume.mat.in +++ b/libs/gltfio/materials/volume.mat.in @@ -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 * diff --git a/shaders/CMakeLists.txt b/shaders/CMakeLists.txt index 64e39e33c93..d6b62d9346e 100644 --- a/shaders/CMakeLists.txt +++ b/shaders/CMakeLists.txt @@ -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 diff --git a/shaders/src/common_instancing.glsl b/shaders/src/common_instancing.glsl new file mode 100644 index 00000000000..3ed14541be2 --- /dev/null +++ b/shaders/src/common_instancing.glsl @@ -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 diff --git a/shaders/src/depth_main.fs b/shaders/src/depth_main.fs index 5d8ca4cee6c..4d7455a4af8 100644 --- a/shaders/src/depth_main.fs +++ b/shaders/src/depth_main.fs @@ -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 diff --git a/shaders/src/getters.fs b/shaders/src/getters.fs index e2414eb1f94..6b675348c61 100644 --- a/shaders/src/getters.fs +++ b/shaders/src/getters.fs @@ -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 -} diff --git a/shaders/src/getters.vs b/shaders/src/getters.vs index f06e2dd44f6..ea3e198b2ba 100644 --- a/shaders/src/getters.vs +++ b/shaders/src/getters.vs @@ -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); } diff --git a/shaders/src/light_directional.fs b/shaders/src/light_directional.fs index 2c4dc4b9076..3e336f5d5b9 100644 --- a/shaders/src/light_directional.fs +++ b/shaders/src/light_directional.fs @@ -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); } } diff --git a/shaders/src/light_punctual.fs b/shaders/src/light_punctual.fs index 650f1cd5b9a..74f144fce22 100644 --- a/shaders/src/light_punctual.fs +++ b/shaders/src/light_punctual.fs @@ -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); } } diff --git a/shaders/src/main.fs b/shaders/src/main.fs index 4665b01e348..54e554d9bd0 100644 --- a/shaders/src/main.fs +++ b/shaders/src/main.fs @@ -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(); diff --git a/shaders/src/main.vs b/shaders/src/main.vs index f87de9e6e5d..e3cfbc570e2 100644 --- a/shaders/src/main.vs +++ b/shaders/src/main.vs @@ -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 diff --git a/shaders/src/shading_unlit.fs b/shaders/src/shading_unlit.fs index d4fd556e08f..b7d0bd70547 100644 --- a/shaders/src/shading_unlit.fs +++ b/shaders/src/shading_unlit.fs @@ -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)); } }