-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Description
Describe the bug
When using Filament materials with vertexDomain=device, rendering issues occur on PowerVR OpenGL ES [OpenGL ES 3.2 build 1.11@5425693] driver if the shader reads gl_InstanceID but does not use it.
Filament uses instance rendering by default (FeatureLevel ≥ 1), and the generated vertex shader always reads gl_InstanceID. However, if the value is only read and not used in further vertex computations (as in fullscreen quad rendering), PowerVR drivers produce incorrect rendering results.
Changing vertexDomain to object avoids the problem, since in that case gl_InstanceID is actually used to index into objectUniforms.
To Reproduce
Steps to reproduce the behavior:
- create filament with OpenGL backend
- prepare fullscreen geometry
- create unlit material with vertexDomain : device
- render it
Alternatively, the issue can also be reproduced with a minimal standalone OpenGL ES shader (outside Filament) that reads gl_InstanceID but doesn’t use it.
A minimal reproducible example can be created using a simple OpenGL ES shader without Filament.
#version 300 es
layout(location = 0) in vec4 aPosition;
layout(location = 1) in vec2 aTexCoord;
uniform mat4 uMVPMatrix;
out vec2 vTexCoord;
void main() {
// Read gl_InstanceID;
int instance_index = gl_InstanceID;
// if instance_index is not used, rendering is incorrect.
//gl_Position = uMVPMatrix * aPosition;
// if instance_index is used, rendering is correct.
gl_Position = uMVPMatrix * aPosition * float(instance_index + 1);
vTexCoord = aTexCoord;
}Expected behavior
using unlit + vertexDomain: device should render correctly
Screenshots
|
Figure 1. Expected 2D texture rendering result |
Figure 2. Wrong 2D texture rendering |
Logs
If applicable, copy full logs from your console here. Please do not
use screenshots of logs, copy them as text, use gist or attach an uncompressed file.
there is no Error log for this but I attached filament engine info logs
filament info log
Using ASurfaceTexture
FEngine resolved backend: OpenGL
[Imagination Technologies], [PowerVR Rogue GE8320], [OpenGL ES 3.2 build 1.11@5425693], [OpenGL ES GLSL ES 3.20 build 1.11@5425693]
Feature level: 2
Active workarounds:
disable_glFlush
allow_read_only_ancillary_feedback_loop
powervr_shader_workarounds
delay_fbo_destruction
GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0
GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = 96
GL_MAX_TEXTURE_SIZE = 4096
GL_MAX_CUBE_MAP_TEXTURE_SIZE = 4096
GL_MAX_3D_TEXTURE_SIZE = 2048
GL_MAX_ARRAY_TEXTURE_LAYERS = 2048
GL_MAX_DRAW_BUFFERS = 8
GL_MAX_RENDERBUFFER_SIZE = 4096
GL_MAX_SAMPLES = 4
GL_MAX_TEXTURE_IMAGE_UNITS = 16
GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = 4
GL_MAX_UNIFORM_BLOCK_SIZE = 134217728
GL_MAX_UNIFORM_BUFFER_BINDINGS = 72
GL_NUM_PROGRAM_BINARY_FORMATS = 1
GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT = 64
OS version: 29
Backend feature level: 2
FEngine feature level: 1
Smartphone (please complete the following information):
- Filament Version: v1.61.0 (but v1.66.1 also same)
- Device: [OPPO CPH2185, Xiaomi Redmi 9C(angelica)]
- OS: [Android 10]
- GPU: [PowerVR Rouge GE8320]
- GPU Driver version: [OpenGL ES 3.2 build 1.11@5425693], [OpenGL ES GLSL ES 3.20 build 1.11@5425693]
Additional context
This issue occurs only on PowerVR OpenGL ES 3.2 build 1.11@5425693 driver.
It is not reproducible on newer versions such as build 1.13@5776728.
As a workaround, we currently set vertexDomain: object for fullscreen unlit materials on affected devices.
Since this configuration uses gl_InstanceID in vertex computations, it works fine.
I’ve attached the generated vertex shaders for both vertexDomain=device and vertexDomain=object cases.
unlit vertexDomain: object shader
#version 300 es
struct MaterialVertexInputs
{
vec2 uv0;
vec4 worldPosition;
};
struct PerRenderableData
{
mat4 worldFromModelMatrix;
mat3 worldFromModelNormalMatrix;
int morphTargetCount;
int flagsChannels;
int objectId;
float userData;
vec4 reserved[8];
};
#ifndef SPIRV_CROSS_CONSTANT_ID_1
#define SPIRV_CROSS_CONSTANT_ID_1 64
#endif
const int CONFIG_MAX_INSTANCES = SPIRV_CROSS_CONSTANT_ID_1;
#ifndef SPIRV_CROSS_CONSTANT_ID_5
#define SPIRV_CROSS_CONSTANT_ID_5 false
#endif
const bool CONFIG_POWER_VR_SHADER_WORKAROUNDS = SPIRV_CROSS_CONSTANT_ID_5;
layout(std140) uniform ObjectUniforms
{
PerRenderableData a[CONFIG_MAX_INSTANCES];
} objectUniforms;
layout(std140) uniform FrameUniforms
{
mat4 a;
mat4 b;
mat4 c;
mat4 d;
mat4 e[4];
mat4 f;
mat4 g;
vec4 h;
vec2 i;
float j;
float k;
vec4 l;
vec4 m;
vec2 n;
vec2 o;
mediump float p;
mediump float q;
mediump vec2 r;
float s;
float t;
float u;
float v;
mediump float w;
mediump float x;
mediump float y;
mediump float z;
mediump vec4 az;
mediump uvec3 bz;
mediump int cz;
mediump vec2 dz;
mediump float ez;
mediump float fz;
mediump vec3 gz[9];
vec3 hz;
mediump float iz;
mediump vec4 jz;
mediump vec4 kz;
vec2 lz;
mediump int mz;
mediump float nz;
vec4 oz;
mediump int pz;
mediump float qz;
vec2 rz;
mediump float sz;
mediump float tz;
mediump float uz;
mediump uint vz;
vec3 wz;
float xz;
mediump float yz;
uint zz;
float azz;
float bzz;
mediump vec3 czz;
mediump float dzz;
float ezz;
mediump float fzz;
float gzz;
float hzz;
mat3 izz;
mat4 jzz;
mat4 kzz;
mediump float lzz;
mediump float mzz;
mediump float nzz;
mediump float ozz;
vec4 pzz[4];
mediump int qzz;
mediump float rzz;
mediump float szz;
mediump float tzz;
mediump vec4 uzz[40];
} frameUniforms;
layout(std140) uniform MaterialParams
{
mediump mat4 a;
} materialParams;
layout(location = 0) in vec4 mesh_position;
layout(location = 3) in vec2 mesh_uv0;
flat out int instance_index;
out vec2 vertex_uv01;
out vec4 vertex_worldPosition;
out vec4 vertex_position;
void main()
{
if (CONFIG_POWER_VR_SHADER_WORKAROUNDS)
{
instance_index = (1 + gl_InstanceID) - 1;
}
else
{
instance_index = gl_InstanceID;
}
MaterialVertexInputs _351 = MaterialVertexInputs(mesh_uv0, (objectUniforms.a[instance_index].worldFromModelMatrix[0] * mesh_position.xyz.x) + ((objectUniforms.a[instance_index].worldFromModelMatrix[1] * mesh_position.xyz.y) + ((objectUniforms.a[instance_index].worldFromModelMatrix[2] * mesh_position.xyz.z) + objectUniforms.a[instance_index].worldFromModelMatrix[3])));
MaterialVertexInputs _358 = MaterialVertexInputs((materialParams.a * vec4(_351.uv0, 0.0, 1.0)).xy, _351.worldPosition);
vec4 _346 = _358.worldPosition;
vertex_uv01 = _358.uv0;
vec3 _212 = _346.xyz;
vertex_worldPosition.x = _212.x;
vertex_worldPosition.y = _212.y;
vertex_worldPosition.z = _212.z;
vec4 _224 = frameUniforms.e[0] * _346;
vertex_position = _224;
_224.z = (_224.z * frameUniforms.i.x) + (_224.w * frameUniforms.i.y);
gl_Position = _224;
}
unlit vertexDomain: device shader
```glsl #version 300 es struct MaterialVertexInputs { vec2 uv0; vec4 worldPosition; }; #ifndef SPIRV_CROSS_CONSTANT_ID_5 #define SPIRV_CROSS_CONSTANT_ID_5 false #endif const bool CONFIG_POWER_VR_SHADER_WORKAROUNDS = SPIRV_CROSS_CONSTANT_ID_5; layout(std140) uniform FrameUniforms { mat4 a; mat4 b; mat4 c; mat4 d; mat4 e[4]; mat4 f; mat4 g; vec4 h; vec2 i; float j; float k; vec4 l; vec4 m; vec2 n; vec2 o; mediump float p; mediump float q; mediump vec2 r; float s; float t; float u; float v; mediump float w; mediump float x; mediump float y; mediump float z; mediump vec4 az; mediump uvec3 bz; mediump int cz; mediump vec2 dz; mediump float ez; mediump float fz; mediump vec3 gz[9]; vec3 hz; mediump float iz; mediump vec4 jz; mediump vec4 kz; vec2 lz; mediump int mz; mediump float nz; vec4 oz; mediump int pz; mediump float qz; vec2 rz; mediump float sz; mediump float tz; mediump float uz; mediump uint vz; vec3 wz; float xz; mediump float yz; uint zz; float azz; float bzz; mediump vec3 czz; mediump float dzz; float ezz; mediump float fzz; float gzz; float hzz; mat3 izz; mat4 jzz; mat4 kzz; mediump float lzz; mediump float mzz; mediump float nzz; mediump float ozz; vec4 pzz[4]; mediump int qzz; mediump float rzz; mediump float szz; mediump float tzz; mediump vec4 uzz[40]; } frameUniforms; layout(std140) uniform MaterialParams { mediump mat4 a; } materialParams; layout(location = 0) in vec4 mesh_position; layout(location = 3) in vec2 mesh_uv0; flat out int instance_index; out vec2 vertex_uv01; out vec4 vertex_worldPosition; out vec4 vertex_position; void main() { if (CONFIG_POWER_VR_SHADER_WORKAROUNDS) { instance_index = (1 + gl_InstanceID) - 1; } else { instance_index = gl_InstanceID; } vec4 _315 = mesh_position; _315.z = (_315.z * (-0.5)) + 0.5; vec4 _291 = frameUniforms.f * _315; float _293 = _291.w; vec4 _364; if (abs(_293) < 1.0842022e-19) { vec4 _355 = _291; _355.w = (_293 < 0.0) ? (-1.0842022e-19) : 1.0842022e-19; _364 = _355; } else { _364 = _291; } MaterialVertexInputs _341 = MaterialVertexInputs(mesh_uv0, _364 * (1.0 / _364.w)); MaterialVertexInputs _348 = MaterialVertexInputs((materialParams.a * vec4(_341.uv0, 0.0, 1.0)).xy, _341.worldPosition); vertex_uv01 = _348.uv0; vec3 _198 = _348.worldPosition.xyz; vertex_worldPosition.x = _198.x; vertex_worldPosition.y = _198.y; vertex_worldPosition.z = _198.z; vertex_position = _315; _315.z = (_315.z * frameUniforms.i.x) + (_315.w * frameUniforms.i.y); gl_Position = _315; } ```To fix this issue, I think it would be better if the generated shader completely omitted any references to gl_InstanceID when instance_index is not used.