Opengl es 如果我可以使用任何操作来检查GLSL int精度是否与声明的精度匹配,该怎么办?
我有一个OpenGL ES 2.0应用程序,它可以为Opengl es 如果我可以使用任何操作来检查GLSL int精度是否与声明的精度匹配,该怎么办?,opengl-es,opengl-es-2.0,Opengl Es,Opengl Es 2.0,我有一个OpenGL ES 2.0应用程序,它可以为mediump和highp获得不同的结果。完全有道理 除非我提出质疑 int range[2], precision; glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range, &precision); printf("Fragment shader high precision float range: %d %d precision: %d\n", ra
mediump
和highp
获得不同的结果。完全有道理
除非我提出质疑
int range[2], precision;
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range, &precision);
printf("Fragment shader high precision float range: %d %d precision: %d\n", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, range, &precision);
printf("Fragment shader medium precision float range: %d %d precision: %d\n", range[0], range[1], precision);
两者都打印相同的内容
Fragment shader high precision float range: 127 127 precision: 23
Fragment shader medium precision float range: 127 127 precision: 23
这看起来像是驱动程序中的一个bug,很糟糕,我将提交一个bug(假设它是驱动程序中的一个bug)
对于mediump float,我可以进行测试
int range[2], precision;
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range, &precision);
float value = sqrtf(powf(2.0f, precision) - 1.0f);
我通过mediump uniform将其上传到着色器,如中所示
glUniform3f(vLocation, value, value, value);
对于此着色器
precision mediump float;
uniform mediump vec3 v;
void main() {
gl_FragColor = vec4(normalize(v) * 0.5 + 0.5, 1);
}
结果如何。结果应该是0.577,当转换为8位颜色时大约是146,所以我检查了146
测试它的工作原理。该设备未通过测试,因为它报告的精度错误,但其他设备报告的精度通过正确
实际上,我花了一段时间才找到一个失败的测试,我不知道为什么。我最初的测试只是
precision mediump float;
uniform mediump vec2 v;
void () {
gl_FragColor = vec4(v.x / v.y);
}
我会过去的
float value = powf(2.0f, precision) - 1.0f;
glUniform2f(vLocation, value / 2, value);
我的想法是,如果在内部它真的是16位mediump,那么v.x是4194303,v.y是8388607,将产生错误的结果,但事实并非如此。我知道驾驶员没有义务在任何地方使用最低精度,但仍然。。。首先让我注意到驱动程序错误的是镜面反射结果不同,这就是为什么我切换到使用normalize
进行测试的原因,这确实表明了这个问题
无论如何,现在我想对mediump int做一个类似的测试,但是我找不到一个失败的测试。例如,您不能在ivec3
上调用normalize
我的第一次尝试是根据报告的范围[1]得到最大的整数,除以2、4、8和16的整数。通过均匀上传到着色器,在着色器中乘以2、4、8、16。每个的结果应该是值除以值*2、4、8、16。如果驱动程序为mediump报告了错误的范围[1]
(它报告了31,但我知道它是15),那么它应该溢出并得到错误的结果
precision mediump float;
uniform mediump ivec4 v;
uniform mediump ivec4 expected;
ivec4 iabs(ivec4 v) {
return ivec4(
v.x < 0 ? -v.x : v.x,
v.y < 0 ? -v.y : v.y,
v.z < 0 ? -v.z : v.z,
v.w < 0 ? -v.w : v.w);
}
void main() {
mediump ivec4 t = ivec4(2, 4, 8, 16);
mediump ivec4 m = v * t;
mediump ivec4 diff = iabs(m - expected);
mediump ivec4 maxDiff = ivec4(4);
bvec4 pass = lessThan(diff, maxDiff);
gl_FragColor = pass;
}
知道我还可以用什么测试来验证mediump int的实际精度>=mediump int的报告精度吗?我不知道你的意思。我传入
uniformintv
其中v=2如果我理解正确,则您假设该值将超出范围。正如在2中一样,如果实现首先是关于范围的,那么这只是一个溢出,如果有人假设,那么规范中的任何其他假设都不成立,因此我不认为没有UB你想做什么。但是,上传这两个2怎么样?我不认为你会找到一个真正的设备,其中(真实的)range\u int(mediump)>range\u float(最高支持的\u float\u精度)。如果设备是通过float模拟int,那么我的假设总是成立的,如果不是,我们只需要整数位数的对数作为浮点格式的指数位数(manitssa位数完全无关)。然而,我真正的意思不是2我不知道你的意思。我传入uniformintv
其中v=2如果我理解正确,则您假设该值将超出范围。正如在2中一样,如果实现首先是关于范围的,那么这只是一个溢出,如果有人假设,那么规范中的任何其他假设都不成立,因此我不认为没有UB你想做什么。但是,上传这两个2怎么样?我不认为你会找到一个真正的设备,其中(真实的)range\u int(mediump)>range\u float(最高支持的\u float\u精度)。如果设备是通过float模拟int,那么我的假设总是成立的,如果不是,我们只需要整数位数的对数作为浮点格式的指数位数(manitssa位数完全无关)。然而,我真正的意思不是2
v = 536870910, 268435454, 134217726, 67108862
expected = 1073741820, 1073741816, 1073741808, 1073741792