Commit 3b0fcf6a by Shahbaz Youssefi Committed by Angle LUCI CQ

Vulkan: SPIR-V Gen: Support type casts in constructors

GLSL basic, vector and matrix constructors can convert between types. This was already done for constants used in constructors. This change implements the cast for non-constant expressions. Bug: angleproject:4889 Change-Id: I0a8c1a6e97ffced0d1652032a41fb87c70be16ca Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2999022Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
parent 0fa2e7f9
...@@ -362,6 +362,23 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const TSymbol *bl ...@@ -362,6 +362,23 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const TSymbol *bl
spirv::LiteralInteger(0)); spirv::LiteralInteger(0));
break; break;
case EbtBool: case EbtBool:
// TODO: In SPIR-V, it's invalid to have a bool type in an interface block. An AST
// transformation should be written to rewrite the blocks to use a uint type with
// appropriate casts where used. Need to handle:
//
// - Store: cast the rhs of assignment
// - Non-array load: cast the expression
// - Array load (for example to use in a struct constructor): reconstruct the array
// with elements cast.
// - Pass to function as out parameter: Use
// MonomorphizeUnsupportedFunctionsInVulkanGLSL to avoid it, as there's no easy
// way to handle such function calls inside if conditions and such.
//
// It might be simplest to do this for bools in structs as well, to avoid having to
// convert between an old and new struct type if the struct is used both inside and
// outside an interface block.
//
// http://anglebug.com/4889.
spirv::WriteTypeBool(&mSpirvTypeAndConstantDecls, typeId); spirv::WriteTypeBool(&mSpirvTypeAndConstantDecls, typeId);
break; break;
default: default:
...@@ -836,6 +853,41 @@ spirv::IdRef SPIRVBuilder::getFloatConstant(float value) ...@@ -836,6 +853,41 @@ spirv::IdRef SPIRVBuilder::getFloatConstant(float value)
return getBasicConstantHelper(asUint.u, EbtFloat, &mFloatConstants); return getBasicConstantHelper(asUint.u, EbtFloat, &mFloatConstants);
} }
spirv::IdRef SPIRVBuilder::getVectorConstantHelper(spirv::IdRef valueId, TBasicType type, int size)
{
if (size == 1)
{
return valueId;
}
SpirvType vecType;
vecType.type = type;
vecType.primarySize = static_cast<uint8_t>(size);
const spirv::IdRef typeId = getSpirvTypeData(vecType, nullptr).id;
const spirv::IdRefList valueIds(size, valueId);
return getCompositeConstant(typeId, valueIds);
}
spirv::IdRef SPIRVBuilder::getUvecConstant(uint32_t value, int size)
{
const spirv::IdRef valueId = getUintConstant(value);
return getVectorConstantHelper(valueId, EbtUInt, size);
}
spirv::IdRef SPIRVBuilder::getIvecConstant(int32_t value, int size)
{
const spirv::IdRef valueId = getIntConstant(value);
return getVectorConstantHelper(valueId, EbtInt, size);
}
spirv::IdRef SPIRVBuilder::getVecConstant(float value, int size)
{
const spirv::IdRef valueId = getFloatConstant(value);
return getVectorConstantHelper(valueId, EbtFloat, size);
}
spirv::IdRef SPIRVBuilder::getCompositeConstant(spirv::IdRef typeId, const spirv::IdRefList &values) spirv::IdRef SPIRVBuilder::getCompositeConstant(spirv::IdRef typeId, const spirv::IdRefList &values)
{ {
SpirvIdAndIdList key{typeId, values}; SpirvIdAndIdList key{typeId, values};
......
...@@ -323,6 +323,9 @@ class SPIRVBuilder : angle::NonCopyable ...@@ -323,6 +323,9 @@ class SPIRVBuilder : angle::NonCopyable
spirv::IdRef getUintConstant(uint32_t value); spirv::IdRef getUintConstant(uint32_t value);
spirv::IdRef getIntConstant(int32_t value); spirv::IdRef getIntConstant(int32_t value);
spirv::IdRef getFloatConstant(float value); spirv::IdRef getFloatConstant(float value);
spirv::IdRef getUvecConstant(uint32_t value, int size);
spirv::IdRef getIvecConstant(int32_t value, int size);
spirv::IdRef getVecConstant(float value, int size);
spirv::IdRef getCompositeConstant(spirv::IdRef typeId, const spirv::IdRefList &values); spirv::IdRef getCompositeConstant(spirv::IdRef typeId, const spirv::IdRefList &values);
// Helpers to start and end a function. // Helpers to start and end a function.
...@@ -381,6 +384,7 @@ class SPIRVBuilder : angle::NonCopyable ...@@ -381,6 +384,7 @@ class SPIRVBuilder : angle::NonCopyable
spirv::IdRef getBasicConstantHelper(uint32_t value, spirv::IdRef getBasicConstantHelper(uint32_t value,
TBasicType type, TBasicType type,
angle::HashMap<uint32_t, spirv::IdRef> *constants); angle::HashMap<uint32_t, spirv::IdRef> *constants);
spirv::IdRef getVectorConstantHelper(spirv::IdRef valueId, TBasicType type, int size);
uint32_t nextUnusedBinding(); uint32_t nextUnusedBinding();
uint32_t nextUnusedInputLocation(uint32_t consumedCount); uint32_t nextUnusedInputLocation(uint32_t consumedCount);
......
...@@ -3376,7 +3376,9 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferTest_ES3); ...@@ -3376,7 +3376,9 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferTest_ES3);
ANGLE_INSTANTIATE_TEST_ES3_AND(FramebufferTest_ES3, ANGLE_INSTANTIATE_TEST_ES3_AND(FramebufferTest_ES3,
WithEmulatedPrerotation(ES3_VULKAN(), 90), WithEmulatedPrerotation(ES3_VULKAN(), 90),
WithEmulatedPrerotation(ES3_VULKAN(), 180), WithEmulatedPrerotation(ES3_VULKAN(), 180),
WithEmulatedPrerotation(ES3_VULKAN(), 270)); WithEmulatedPrerotation(ES3_VULKAN(), 270),
WithDirectSPIRVGeneration(WithEmulatedPrerotation(ES3_VULKAN(),
90)));
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferTest_ES31); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferTest_ES31);
ANGLE_INSTANTIATE_TEST_ES31(FramebufferTest_ES31); ANGLE_INSTANTIATE_TEST_ES31(FramebufferTest_ES31);
...@@ -2585,6 +2585,83 @@ TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2) ...@@ -2585,6 +2585,83 @@ TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
EXPECT_NE(0u, program); EXPECT_NE(0u, program);
} }
// Test that constructing matrices from non-float types works.
TEST_P(GLSLTest_ES3, ConstructMatrixFromNonFloat)
{
constexpr char kFS[] = R"(#version 300 es
precision highp float;
out vec4 color;
uniform int i;
uniform uint u;
void main()
{
bool b = i > 10;
mat3x2 mi = mat3x2(i);
mat4 mu = mat4(u);
mat2x4 mb = mat2x4(b);
mat3x2 m = mat3x2(ivec2(i), uvec2(u), bvec2(b));
color = vec4(mi[0][0] == float(i) ? 1 : 0,
mu[2][2] == float(u) ? 1 : 0,
mb[1][1] == float(b) ? 1 : 0,
m[0][1] == float(i) && m[1][0] == float(u) && m[2][0] == float(b) ? 1 : 0);
})";
ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
glUseProgram(program);
GLint iloc = glGetUniformLocation(program, "i");
GLint uloc = glGetUniformLocation(program, "u");
ASSERT_NE(iloc, -1);
ASSERT_NE(uloc, -1);
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 constructing non-float vectors from matrix types works.
TEST_P(GLSLTest_ES3, ConstructNonFloatVectorFromMatrix)
{
constexpr char kFS[] = R"(#version 300 es
precision highp float;
out vec4 color;
uniform float f;
void main()
{
mat4 m = mat4(f);
ivec3 vi = ivec3(m);
uvec2 vu = uvec2(m);
bvec4 vb = bvec4(m);
color = vec4(vi.x == int(f) ? 1 : 0,
vu.x == uint(f) ? 1 : 0,
vb.x == bool(f) ? 1 : 0,
1);
})";
ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
glUseProgram(program);
GLint floc = glGetUniformLocation(program, "f");
ASSERT_NE(floc, -1);
glUniform1f(floc, 123);
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 // Test that an user-defined function with a large number of float4 parameters doesn't fail due to
// the function name being too long. // the function name being too long.
TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters) TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
......
...@@ -9468,7 +9468,8 @@ ANGLE_INSTANTIATE_TEST_ES2(TextureCubeTest); ...@@ -9468,7 +9468,8 @@ ANGLE_INSTANTIATE_TEST_ES2(TextureCubeTest);
ANGLE_INSTANTIATE_TEST_ES2(Texture2DTestWithDrawScale); ANGLE_INSTANTIATE_TEST_ES2(Texture2DTestWithDrawScale);
ANGLE_INSTANTIATE_TEST_ES2(Sampler2DAsFunctionParameterTest); ANGLE_INSTANTIATE_TEST_ES2(Sampler2DAsFunctionParameterTest);
ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayTest); ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayTest);
ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayAsFunctionParameterTest); ANGLE_INSTANTIATE_TEST_ES2_AND(SamplerArrayAsFunctionParameterTest,
WithDirectSPIRVGeneration(ES2_VULKAN()));
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3);
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DTestES3, WithAllocateNonZeroMemory(ES3_VULKAN())); ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DTestES3, WithAllocateNonZeroMemory(ES3_VULKAN()));
...@@ -9501,7 +9502,8 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DArrayTestES3); ...@@ -9501,7 +9502,8 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DArrayTestES3);
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DArrayTestES3, WithDirectSPIRVGeneration(ES3_VULKAN())); ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DArrayTestES3, WithDirectSPIRVGeneration(ES3_VULKAN()));
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureSizeTextureArrayTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureSizeTextureArrayTest);
ANGLE_INSTANTIATE_TEST_ES3(TextureSizeTextureArrayTest); ANGLE_INSTANTIATE_TEST_ES3_AND(TextureSizeTextureArrayTest,
WithDirectSPIRVGeneration(ES3_VULKAN()));
ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructTest); ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructTest);
ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructAsFunctionParameterTest); ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructAsFunctionParameterTest);
...@@ -9546,10 +9548,12 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeIntegerEdgeTestES3); ...@@ -9546,10 +9548,12 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeIntegerEdgeTestES3);
ANGLE_INSTANTIATE_TEST_ES3(TextureCubeIntegerEdgeTestES3); ANGLE_INSTANTIATE_TEST_ES3(TextureCubeIntegerEdgeTestES3);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DIntegerProjectiveOffsetTestES3); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DIntegerProjectiveOffsetTestES3);
ANGLE_INSTANTIATE_TEST_ES3(Texture2DIntegerProjectiveOffsetTestES3); ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DIntegerProjectiveOffsetTestES3,
WithDirectSPIRVGeneration(ES3_VULKAN()));
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DArrayIntegerTestES3); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DArrayIntegerTestES3);
ANGLE_INSTANTIATE_TEST_ES3(Texture2DArrayIntegerTestES3); ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DArrayIntegerTestES3,
WithDirectSPIRVGeneration(ES3_VULKAN()));
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture3DIntegerTestES3); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture3DIntegerTestES3);
ANGLE_INSTANTIATE_TEST_ES3(Texture3DIntegerTestES3); ANGLE_INSTANTIATE_TEST_ES3(Texture3DIntegerTestES3);
......
...@@ -168,6 +168,11 @@ struct CombinedPrintToStringParamName ...@@ -168,6 +168,11 @@ struct CombinedPrintToStringParamName
INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \ INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
testing::PrintToStringParamName()) testing::PrintToStringParamName())
#define ANGLE_INSTANTIATE_TEST_ES2_AND(testName, ...) \
const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2, __VA_ARGS__}; \
INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
testing::PrintToStringParamName())
// Instantiate the test once for each GLES3 platform // Instantiate the test once for each GLES3 platform
#define ANGLE_INSTANTIATE_TEST_ES3(testName) \ #define ANGLE_INSTANTIATE_TEST_ES3(testName) \
const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES3}; \ const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES3}; \
......
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