Hash :
6deca89e
Author :
Date :
2023-03-22T22:33:40
Add Spirv Instruction to explicitly cast mediump float to 16 bit If the GLSL shader code expects the comparison between two mediump float values returning true, but the SpirV compiler treats one of them as 32-bit, and treats the other one as 16-bit, the comparison would return false instead. The SpirV compiler may not automatically cast the mediump float values to 16 bits, because it may utilize the RelaxedPrecision decoration to keep a mediump float as 32-bit, so that the compiler can avoid the type cast from 32-bit highp to 16-bit mediump. This change adds an additional OpQuantizeToF16 SpirV instruction to explicitly cast mediump float scalar or mediump float vector to 16 bit, if they are assigned with a highp float value. This ensures that if the GLSL shader code ever compares two meiump float values, the SpirV shader compiler is not accidentally comparing a 16 bit with a 32 bit float value. This fixe the deqp test failure on Pixel 6 and Pixel 7: dEQP-GLES2.functional.shaders.algorithm.rgb_to_hsl_vertex. Bug: b/274859104 Bug: b/274408172 Change-Id: Ifd996cea14c0f77f45ae90f38c8e53cf5035139f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4400404 Commit-Queue: Yuxin Hu <yuxinhu@google.com> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Cody Northrop <cnorthrop@google.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
using namespace angle;
namespace
{
const int GRID_SIZE = 3;
class ShaderAlgorithmTest : public ANGLETest<>
{
protected:
ShaderAlgorithmTest()
{
setWindowWidth(64);
setWindowHeight(64);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
}
~ShaderAlgorithmTest() {}
};
// Simplied version of dEQP test dEQP?GLES2.functional.shaders.algorithm.rgb_to_hsl_vertex
TEST_P(ShaderAlgorithmTest, rgb_to_hsl_vertex_shader)
{
const char kVS[] =
"attribute highp vec3 a_position;\n"
"attribute highp vec3 a_unitCoords;\n"
"varying mediump vec3 v_color;\n"
"void main()\n"
"{\n"
" gl_Position =vec4(a_position.x, a_position.y, a_position.z, 1.0);\n"
" mediump vec3 coords = a_unitCoords;\n"
" mediump vec3 res = vec3(0.0);\n"
" mediump float r = coords.x, g = coords.y, b = coords.z;\n"
" mediump float minVal = min(min(r, g), b);\n"
" mediump float maxVal = max(max(r, g), b);\n"
" mediump float H = 0.0; \n"
" mediump float S = 0.0; \n"
" if (r == maxVal)\n"
" H = 1.0;\n"
" else\n"
" S = 1.0;\n"
" res = vec3(H, S, 0);\n"
" v_color = res;\n"
"}\n";
const char kFS[] =
"varying mediump vec3 v_color;\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(v_color, 1.0);\n"
"}\n";
ANGLE_GL_PROGRAM(program, kVS, kFS);
// compute a_position vertex data
std::vector<Vector3> positions{Vector3(-1.0f, -1.0f, 0.0f), Vector3(-1.0f, 1.0f, 0.0f),
Vector3(1.0f, 1.0f, 0.0f), Vector3(1.0f, -1.0f, 0.0f)};
// Pass the vertex data to VBO
GLBuffer posBuffer;
glBindBuffer(GL_ARRAY_BUFFER, posBuffer.get());
glBufferData(GL_ARRAY_BUFFER, sizeof(positions[0]) * positions.size(), positions.data(),
GL_STATIC_DRAW);
// Link position data to "a_position" vertex attrib
GLint posLocation = glGetAttribLocation(program.get(), "a_position");
ASSERT_NE(-1, posLocation);
glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(posLocation);
// Pass the index data to EBO
std::vector<GLuint> indices{0, 1, 2, 0, 2, 3};
GLBuffer indexBuffer;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * indices.size(), indices.data(),
GL_STATIC_DRAW);
// Initialize the "a_unitCoords" vertex attributes data
std::vector<Vector3> unitcoords;
unitcoords.resize(4);
GLBuffer unitCoordBuffer;
GLint unitCoordLocation = glGetAttribLocation(program.get(), "a_unitCoords");
ASSERT_NE(-1, unitCoordLocation);
const float epsilon = 1.0e-7;
int gridSize = GRID_SIZE;
for (int y = 0; y < gridSize + 1; y++)
{
for (int x = 0; x < gridSize + 1; x++)
{
float sx = (float)x / (float)gridSize;
float sy = (float)y / (float)gridSize;
// Pass the a_unitCoords data to VBO
for (int vtx = 0; vtx < 4; vtx++)
{
unitcoords[vtx] = Vector3(sx, sy, 0.33f * sx + 0.5f * sy);
}
glBindBuffer(GL_ARRAY_BUFFER, unitCoordBuffer.get());
glBufferData(GL_ARRAY_BUFFER, sizeof(unitcoords[0]) * unitcoords.size(),
unitcoords.data(), GL_STATIC_DRAW);
// Link the unitcoords data to "a_unitCoords" vertex attrib
glVertexAttribPointer(unitCoordLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(unitCoordLocation);
// Draw and verify
glUseProgram(program.get());
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
ASSERT_GL_NO_ERROR();
float maxVal = std::max(sx, std::max(sy, 0.33f * sx + 0.5f * sy));
if (abs(maxVal - sx) <= epsilon)
{
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
}
else
{
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
}
}
}
ANGLE_INSTANTIATE_TEST_ES2(ShaderAlgorithmTest);
} // namespace