Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workaround for a bug in Adreno's shader compiler #6383

Merged
merged 1 commit into from
Dec 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions libs/filamat/src/shaders/CodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion libs/gltfio/materials/volume.mat.in
Original file line number Diff line number Diff line change
Expand Up @@ -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 *
Expand Down
1 change: 1 addition & 0 deletions shaders/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
35 changes: 35 additions & 0 deletions shaders/src/common_instancing.glsl
Original file line number Diff line number Diff line change
@@ -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.
pixelflinger marked this conversation as resolved.
Show resolved Hide resolved

// 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
2 changes: 1 addition & 1 deletion shaders/src/depth_main.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 4 additions & 15 deletions shaders/src/getters.fs
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
}
38 changes: 11 additions & 27 deletions shaders/src/getters.vs
Original file line number Diff line number Diff line change
@@ -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;
}

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -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;
Expand All @@ -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);
}

Expand Down
4 changes: 2 additions & 2 deletions shaders/src/light_directional.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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);
}
}
Expand Down
4 changes: 2 additions & 2 deletions shaders/src/light_punctual.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand Down Expand Up @@ -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);
}
}
Expand Down
2 changes: 2 additions & 0 deletions shaders/src/main.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
10 changes: 6 additions & 4 deletions shaders/src/main.vs
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
Expand All @@ -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);
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion shaders/src/shading_unlit.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}
Expand Down