Commit afdf378f by Shahbaz Youssefi Committed by Angle LUCI CQ

Vulkan: SPIR-V Gen: Support == and != on complex types

In GLSL, == and != produce a bool. In SPIR-V, there are only component-wise comparison operations. For ==, OpAll should be used to reduce it to a single bool, and for !=, OpAny. For matrices, the comparison is done column by column with a similar reduction for each column, and one for the final result. For structs and arrays, the comparison is similarly done field by field or element by element respectively. Bug: angleproject:4889 Change-Id: I8157c1931b7d1dedd74a3825967f5e212d346900 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3001905 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent c9dcc553
......@@ -157,6 +157,14 @@ const SpirvTypeData &SPIRVBuilder::getSpirvTypeData(const SpirvType &type, const
return iter->second;
}
spirv::IdRef SPIRVBuilder::getBasicTypeId(TBasicType basicType, size_t size)
{
SpirvType type;
type.type = basicType;
type.primarySize = static_cast<uint8_t>(size);
return getSpirvTypeData(type, nullptr).id;
}
spirv::IdRef SPIRVBuilder::getTypePointerId(spirv::IdRef typeId, spv::StorageClass storageClass)
{
SpirvIdAndStorageClass key{typeId, storageClass};
......
......@@ -253,6 +253,7 @@ class SPIRVBuilder : angle::NonCopyable
SpirvType getSpirvType(const TType &type, TLayoutBlockStorage blockStorage) const;
const SpirvTypeData &getTypeData(const TType &type, TLayoutBlockStorage blockStorage);
const SpirvTypeData &getSpirvTypeData(const SpirvType &type, const TSymbol *block);
spirv::IdRef getBasicTypeId(TBasicType basicType, size_t size);
spirv::IdRef getTypePointerId(spirv::IdRef typeId, spv::StorageClass storageClass);
spirv::IdRef getFunctionTypeId(spirv::IdRef returnTypeId, const spirv::IdRefList &paramTypeIds);
......
......@@ -700,6 +700,14 @@ void TType::toArrayBaseType()
onArrayDimensionsChange(TSpan<const unsigned int>());
}
void TType::toMatrixColumnType()
{
ASSERT(isMatrix());
primarySize = secondarySize;
secondarySize = 1;
invalidateMangledName();
}
void TType::setInterfaceBlock(const TInterfaceBlock *interfaceBlockIn)
{
if (mInterfaceBlock != interfaceBlockIn)
......
......@@ -227,6 +227,8 @@ class TType
void toArrayElementType();
// Removes all array sizes.
void toArrayBaseType();
// Turns a matrix into a column of it.
void toMatrixColumnType();
const TInterfaceBlock *getInterfaceBlock() const { return mInterfaceBlock; }
void setInterfaceBlock(const TInterfaceBlock *interfaceBlockIn);
......
......@@ -65,11 +65,15 @@
// D3D
6091 WIN D3D11 : GLSLTest_ES3.InitGlobalComplexConstant/* = SKIP
6122 WIN D3D11 : GLSLTestLoops.*ContinueInSwitch/* = SKIP
6150 WIN D3D11 : GLSLTest_ES31.StructAndArrayEqualOperator/* = SKIP
// Android
6095 ANDROID GLES : GLSLTest_ES3.InitGlobalComplexConstant/ES3_OpenGLES = SKIP
6116 ANDROID GLES : GLSLTestLoops.ForNoCondition/ES3_OpenGLES = SKIP
// Nexus 5X expectations.
6149 NEXUS5X GLES : GLSLTest_ES31.StructAndArrayEqualOperator/* = SKIP
// Pixel 4 expectations.
5981 PIXEL4ORXL GLES : BlitFramebufferTest.BlitSRGBToRGBOversizedDestArea/* = SKIP
5981 PIXEL4ORXL GLES : CopyTexImageTest.CopyTexSubImageFrom3DTexureOES/* = SKIP
......
......@@ -2662,6 +2662,145 @@ void main()
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
}
// Test that == and != for vector and matrix types work.
TEST_P(GLSLTest_ES3, NonScalarEqualOperator)
{
constexpr char kFS[] = R"(#version 300 es
precision highp float;
out vec4 color;
uniform float f;
uniform int i;
uniform uint u;
void main()
{
mat3x2 m32_1 = mat3x2(vec2(f), vec2(i), vec2(u));
mat3x2 m32_2 = mat3x2(m32_1);
mat3x2 m32_3 = mat3x2(vec2(i), vec2(u), vec2(f));
mat2x3 m23_1 = mat2x3(vec3(f), vec3(i));
mat2x3 m23_2 = mat2x3(m23_1);
mat2x3 m23_3 = mat2x3(vec3(i), vec3(u));
vec2 v2_1 = m32_1[0];
vec2 v2_2 = m32_2[0];
ivec3 v3_1 = ivec3(transpose(m32_1)[0]);
ivec3 v3_2 = ivec3(transpose(m32_2)[0]);
uvec4 v4_1 = uvec4(m32_1[1], m32_1[2]);
uvec4 v4_2 = uvec4(m32_2[1], m32_2[2]);
color = vec4((m32_1 == m32_2 ? 0.5 : 0.0) + (m23_1 == m23_2 ? 0.5 : 0.0),
v2_1 == v2_2 ? 1 : 0,
(v3_1 == v3_2 ? 0.5 : 0.0) +
(v4_1 == v4_2 ? 0.5 : 0.0),
(m32_1 != m32_3 ? 0.125 : 0.0) +
(m23_1 != m23_3 ? 0.125 : 0.0) +
(v2_1 != vec2(v3_2) ? 0.25 : 0.0) +
(v3_1 != ivec3(v4_2) ? 0.25 : 0.0) +
(v4_1 != uvec4(v2_1, v2_2) ? 0.25 : 0.0));
})";
ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
glUseProgram(program);
GLint floc = glGetUniformLocation(program, "f");
GLint iloc = glGetUniformLocation(program, "i");
GLint uloc = glGetUniformLocation(program, "u");
ASSERT_NE(floc, -1);
ASSERT_NE(iloc, -1);
ASSERT_NE(uloc, -1);
glUniform1f(floc, 1.5);
glUniform1i(iloc, -123);
glUniform1ui(uloc, 456);
drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
}
// Test that == and != for structs and array types work.
TEST_P(GLSLTest_ES31, StructAndArrayEqualOperator)
{
constexpr char kFS[] = R"(#version 310 es
precision highp float;
out vec4 color;
uniform float f;
uniform int i;
uniform uint u;
struct S
{
float f;
int i;
uint u;
vec4 v;
ivec3 iv;
uvec2 uv;
mat3x2 m32;
mat2x3 m23;
float fa[3][4][5];
int ia[4];
uint ua[6][2];
};
struct T
{
S s1;
S s2[3][2];
};
void main()
{
float fa[5] = float[5](f, f, f, f, f);
int ia[4] = int[4](i, i, i, i);
uint ua[2] = uint[2](u, u);
S s1 = S(f, i, u, vec4(f), ivec3(i), uvec2(u),
mat3x2(vec2(f), vec2(i), vec2(u)),
mat2x3(vec3(f), vec3(i)),
float[3][4][5](
float[4][5](fa, fa, fa, fa),
float[4][5](fa, fa, fa, fa),
float[4][5](fa, fa, fa, fa)),
ia,
uint[6][2](ua, ua, ua, ua, ua, ua));
S s2[2] = S[2](s1, s1);
s2[1].fa[0][1][2] = float(i);
T t1 = T(s1, S[3][2](s2, s2, s2));
T t2 = T(s2[1], S[3][2](s2, s2, s2));
T ta1[2] = T[2](t1, t2);
T ta2[2] = T[2](t1, t2);
T ta3[2] = T[2](t2, t1);
color = vec4((s1 == s2[0] ? 0.5 : 0.0) + (s1 != s2[1] ? 0.5 : 0.0),
(s1.fa[0] == s2[0].fa[0] ? 0.5 : 0.0) + (s1.fa[0] != s2[1].fa[0] ? 0.5 : 0.0),
(ta1[0] == t1 ? 0.5 : 0.0) + (ta1[1] != t1 ? 0.5 : 0.0),
(ta1 == ta2 ? 0.5 : 0.0) + (ta1 != ta3 ? 0.5 : 0.0));
})";
ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
glUseProgram(program);
GLint floc = glGetUniformLocation(program, "f");
GLint iloc = glGetUniformLocation(program, "i");
GLint uloc = glGetUniformLocation(program, "u");
ASSERT_NE(floc, -1);
ASSERT_NE(iloc, -1);
ASSERT_NE(uloc, -1);
glUniform1f(floc, 1.5);
glUniform1i(iloc, -123);
glUniform1ui(uloc, 456);
drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
}
// Test that an user-defined function with a large number of float4 parameters doesn't fail due to
// the function name being too long.
TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment