Skip to content

Commit

Permalink
Workaround for some PowerVR devices
Browse files Browse the repository at this point in the history
The PowerVR compiler systematically crashes on some devices when
`gl_Position` is written twice in the vertex shader.


fixes #5118, b/190221124
  • Loading branch information
pixelflinger committed Aug 8, 2023
1 parent 1e4172b commit 018d6f8
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 11 deletions.
1 change: 1 addition & 0 deletions NEW_RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).

## Release notes for next branch cut
- backend: fix #6997 : picking can fail on Adreno [⚠️ **New Material Version**]
- backend: A partial workaround for PowerVR devices (#5118, b/190221124) [⚠️ **Recompile Materials**]
22 changes: 14 additions & 8 deletions shaders/src/main.vs
Original file line number Diff line number Diff line change
Expand Up @@ -154,28 +154,29 @@ void main() {

#endif // !defined(USE_OPTIMIZED_DEPTH_VERTEX_SHADER)

vec4 position;

#if defined(VERTEX_DOMAIN_DEVICE)
// The other vertex domains are handled in initMaterialVertex()->computeWorldPosition()
gl_Position = getPosition();
position = getPosition();

#if !defined(USE_OPTIMIZED_DEPTH_VERTEX_SHADER)
#if defined(MATERIAL_HAS_CLIP_SPACE_TRANSFORM)
gl_Position = getMaterialClipSpaceTransform(material) * gl_Position;
position = getMaterialClipSpaceTransform(material) * position;
#endif
#endif // !USE_OPTIMIZED_DEPTH_VERTEX_SHADER

#if defined(MATERIAL_HAS_VERTEX_DOMAIN_DEVICE_JITTERED)
// Apply the clip-space transform which is normally part of the projection
gl_Position.xy = gl_Position.xy * frameUniforms.clipTransform.xy + (gl_Position.w * frameUniforms.clipTransform.zw);
position.xy = position.xy * frameUniforms.clipTransform.xy + (position.w * frameUniforms.clipTransform.zw);
#endif
#else
gl_Position = getClipFromWorldMatrix() * getWorldPosition(material);
position = getClipFromWorldMatrix() * getWorldPosition(material);
#endif

#if defined(VERTEX_DOMAIN_DEVICE)
// GL convention to inverted DX convention (must happen after clipSpaceTransform)
gl_Position.z = gl_Position.z * -0.5 + 0.5;
position.z = position.z * -0.5 + 0.5;
#endif

#if defined(VARIANT_HAS_VSM)
Expand All @@ -197,15 +198,20 @@ void main() {
#endif

// this must happen before we compensate for vulkan below
vertex_position = gl_Position;
vertex_position = position;

#if defined(TARGET_VULKAN_ENVIRONMENT)
// In Vulkan, clip space is Y-down. In OpenGL and Metal, clip space is Y-up.
gl_Position.y = -gl_Position.y;
position.y = -position.y;
#endif

#if !defined(TARGET_VULKAN_ENVIRONMENT) && !defined(TARGET_METAL_ENVIRONMENT)
// This is not needed in Vulkan or Metal because clipControl is always (1, 0)
gl_Position.z = dot(gl_Position.zw, frameUniforms.clipControl);
// (We don't use a dot() here because it workaround a spirv-opt optimization that in turn
// causes a crash on PowerVR, see #5118)
position.z = position.z * frameUniforms.clipControl.x + position.w * frameUniforms.clipControl.y;
#endif

// some PowerVR drivers crash when gl_Position is written more than once
gl_Position = position;
}
12 changes: 9 additions & 3 deletions shaders/src/post_process.vs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ void main() {

inputs.normalizedUV = position.xy * 0.5 + 0.5;

gl_Position = getPosition();
vec4 position = getPosition();

// GL convention to inverted DX convention
gl_Position.z = gl_Position.z * -0.5 + 0.5;
position.z = position.z * -0.5 + 0.5;

// Adjust clip-space
#if !defined(TARGET_VULKAN_ENVIRONMENT) && !defined(TARGET_METAL_ENVIRONMENT)
// This is not needed in Vulkan or Metal because clipControl is always (1, 0)
gl_Position.z = dot(gl_Position.zw, frameUniforms.clipControl);
// (We don't use a dot() here because it workaround a spirv-opt optimization that in turn
// causes a crash on PowerVR, see #5118)
position.z = position.z * frameUniforms.clipControl.x + position.w * frameUniforms.clipControl.y;
#endif

// Invoke user code
Expand All @@ -31,4 +34,7 @@ void main() {
#if defined(VARIABLE_CUSTOM3)
VARIABLE_CUSTOM_AT3 = inputs.VARIABLE_CUSTOM3;
#endif

// some PowerVR drivers crash when gl_Position is written more than once
gl_Position = position;
}

0 comments on commit 018d6f8

Please sign in to comment.