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:
committed by
Mathias Agopian
parent
aa5504aad3
commit
ee6612ecfa
@@ -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;
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user