| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841 |
- // Copyright (c) 2015-2016 The Khronos Group Inc.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- // Assembler tests for instructions in the "Group Instrucions" section of the
- // SPIR-V spec.
- #include <cstdint>
- #include <limits>
- #include <string>
- #include <vector>
- #include "gmock/gmock.h"
- #include "test/test_fixture.h"
- #include "test/unit_spirv.h"
- namespace spvtools {
- namespace {
- using spvtest::Concatenate;
- using spvtest::EnumCase;
- using spvtest::MakeInstruction;
- using ::testing::Eq;
- // Test Sampler Addressing Mode enum values
- using SamplerAddressingModeTest = spvtest::TextToBinaryTestBase<
- ::testing::TestWithParam<EnumCase<spv::SamplerAddressingMode>>>;
- TEST_P(SamplerAddressingModeTest, AnySamplerAddressingMode) {
- const std::string input =
- "%result = OpConstantSampler %type " + GetParam().name() + " 0 Nearest";
- EXPECT_THAT(CompiledInstructions(input),
- Eq(MakeInstruction(spv::Op::OpConstantSampler,
- {1, 2, uint32_t(GetParam().value()), 0, 0})));
- }
- // clang-format off
- #define CASE(NAME) { spv::SamplerAddressingMode::NAME, #NAME }
- INSTANTIATE_TEST_SUITE_P(
- TextToBinarySamplerAddressingMode, SamplerAddressingModeTest,
- ::testing::ValuesIn(std::vector<EnumCase<spv::SamplerAddressingMode>>{
- CASE(None),
- CASE(ClampToEdge),
- CASE(Clamp),
- CASE(Repeat),
- CASE(RepeatMirrored),
- }));
- #undef CASE
- // clang-format on
- TEST_F(SamplerAddressingModeTest, WrongMode) {
- EXPECT_THAT(CompileFailure("%r = OpConstantSampler %t xxyyzz 0 Nearest"),
- Eq("Invalid sampler addressing mode 'xxyyzz'."));
- }
- // Test Sampler Filter Mode enum values
- using SamplerFilterModeTest = spvtest::TextToBinaryTestBase<
- ::testing::TestWithParam<EnumCase<spv::SamplerFilterMode>>>;
- TEST_P(SamplerFilterModeTest, AnySamplerFilterMode) {
- const std::string input =
- "%result = OpConstantSampler %type Clamp 0 " + GetParam().name();
- EXPECT_THAT(CompiledInstructions(input),
- Eq(MakeInstruction(spv::Op::OpConstantSampler,
- {1, 2, 2, 0, uint32_t(GetParam().value())})));
- }
- // clang-format off
- #define CASE(NAME) { spv::SamplerFilterMode::NAME, #NAME}
- INSTANTIATE_TEST_SUITE_P(
- TextToBinarySamplerFilterMode, SamplerFilterModeTest,
- ::testing::ValuesIn(std::vector<EnumCase<spv::SamplerFilterMode>>{
- CASE(Nearest),
- CASE(Linear),
- }));
- #undef CASE
- // clang-format on
- TEST_F(SamplerFilterModeTest, WrongMode) {
- EXPECT_THAT(CompileFailure("%r = OpConstantSampler %t Clamp 0 xxyyzz"),
- Eq("Invalid sampler filter mode 'xxyyzz'."));
- }
- struct ConstantTestCase {
- std::string constant_type;
- std::string constant_value;
- std::vector<uint32_t> expected_instructions;
- };
- using OpConstantValidTest =
- spvtest::TextToBinaryTestBase<::testing::TestWithParam<ConstantTestCase>>;
- TEST_P(OpConstantValidTest, ValidTypes) {
- const std::string input = "%1 = " + GetParam().constant_type +
- "\n"
- "%2 = OpConstant %1 " +
- GetParam().constant_value + "\n";
- std::vector<uint32_t> instructions;
- EXPECT_THAT(CompiledInstructions(input), Eq(GetParam().expected_instructions))
- << " type: " << GetParam().constant_type
- << " literal: " << GetParam().constant_value;
- }
- // clang-format off
- INSTANTIATE_TEST_SUITE_P(
- TextToBinaryOpConstantValid, OpConstantValidTest,
- ::testing::ValuesIn(std::vector<ConstantTestCase>{
- // Check 16 bits
- {"OpTypeInt 16 0", "0x1234",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0x1234})})},
- {"OpTypeInt 16 0", "0x8000",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0x8000})})},
- {"OpTypeInt 16 0", "0",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
- {"OpTypeInt 16 0", "65535",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 65535})})},
- {"OpTypeInt 16 0", "0xffff",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 65535})})},
- {"OpTypeInt 16 1", "0x8000", // Test sign extension.
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffff8000})})},
- {"OpTypeInt 16 1", "-32",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-32)})})},
- {"OpTypeInt 16 1", "0",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
- {"OpTypeInt 16 1", "-0",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
- {"OpTypeInt 16 1", "-0x0",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
- {"OpTypeInt 16 1", "-32768",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-32768)})})},
- // Check 32 bits
- {"OpTypeInt 32 0", "42",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 0}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 42})})},
- {"OpTypeInt 32 1", "-32",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-32)})})},
- {"OpTypeInt 32 1", "0",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
- {"OpTypeInt 32 1", "-0",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
- {"OpTypeInt 32 1", "-0x0",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
- {"OpTypeInt 32 1", "-0x001",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-1)})})},
- {"OpTypeInt 32 1", "2147483647",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0x7fffffffu})})},
- {"OpTypeInt 32 1", "-2147483648",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0x80000000u})})},
- {"OpTypeFloat 32", "1.0",
- Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0x3f800000})})},
- {"OpTypeFloat 32", "10.0",
- Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0x41200000})})},
- {"OpTypeFloat 32", "-0x1p+128", // -infinity
- Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0xFF800000})})},
- {"OpTypeFloat 32", "0x1p+128", // +infinity
- Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0x7F800000})})},
- {"OpTypeFloat 32", "-0x1.8p+128", // A -NaN
- Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0xFFC00000})})},
- {"OpTypeFloat 32", "-0x1.0002p+128", // A +NaN
- Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0xFF800100})})},
- // Check 48 bits
- {"OpTypeInt 48 0", "0x1234",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 0}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0x1234, 0})})},
- {"OpTypeInt 48 0", "0x800000000001",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 0}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 1, 0x00008000})})},
- {"OpTypeInt 48 1", "0x800000000000", // Test sign extension.
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0, 0xffff8000})})},
- {"OpTypeInt 48 1", "-32",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-32), uint32_t(-1)})})},
- // Check 64 bits
- {"OpTypeInt 64 0", "0x1234",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0x1234, 0})})},
- {"OpTypeInt 64 0", "18446744073709551615",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
- {"OpTypeInt 64 0", "0xffffffffffffffff",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
- {"OpTypeInt 64 1", "0x1234",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0x1234, 0})})},
- {"OpTypeInt 64 1", "-42",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})},
- {"OpTypeInt 64 1", "-0x01",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
- {"OpTypeInt 64 1", "9223372036854775807",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffffffffu, 0x7fffffffu})})},
- {"OpTypeInt 64 1", "0x7fffffff",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
- MakeInstruction(spv::Op::OpConstant, {1, 2, 0x7fffffffu, 0})})},
- }));
- // clang-format on
- // A test case for checking OpConstant with invalid literals with a leading
- // minus.
- struct InvalidLeadingMinusCase {
- std::string type;
- std::string literal;
- };
- using OpConstantInvalidLeadingMinusTest = spvtest::TextToBinaryTestBase<
- ::testing::TestWithParam<InvalidLeadingMinusCase>>;
- TEST_P(OpConstantInvalidLeadingMinusTest, InvalidCase) {
- const std::string input = "%1 = " + GetParam().type +
- "\n"
- "%2 = OpConstant %1 " +
- GetParam().literal;
- EXPECT_THAT(CompileFailure(input),
- Eq("Cannot put a negative number in an unsigned literal"));
- }
- // clang-format off
- INSTANTIATE_TEST_SUITE_P(
- TextToBinaryOpConstantInvalidLeadingMinus, OpConstantInvalidLeadingMinusTest,
- ::testing::ValuesIn(std::vector<InvalidLeadingMinusCase>{
- {"OpTypeInt 16 0", "-0"},
- {"OpTypeInt 16 0", "-0x0"},
- {"OpTypeInt 16 0", "-1"},
- {"OpTypeInt 32 0", "-0"},
- {"OpTypeInt 32 0", "-0x0"},
- {"OpTypeInt 32 0", "-1"},
- {"OpTypeInt 64 0", "-0"},
- {"OpTypeInt 64 0", "-0x0"},
- {"OpTypeInt 64 0", "-1"},
- }));
- // clang-format on
- // A test case for invalid floating point literals.
- struct InvalidFloatConstantCase {
- uint32_t width;
- std::string literal;
- };
- using OpConstantInvalidFloatConstant = spvtest::TextToBinaryTestBase<
- ::testing::TestWithParam<InvalidFloatConstantCase>>;
- TEST_P(OpConstantInvalidFloatConstant, Samples) {
- // Check both kinds of instructions that take literal floats.
- for (const auto& instruction : {"OpConstant", "OpSpecConstant"}) {
- std::stringstream input;
- input << "%1 = OpTypeFloat " << GetParam().width << "\n"
- << "%2 = " << instruction << " %1 " << GetParam().literal;
- std::stringstream expected_error;
- expected_error << "Invalid " << GetParam().width
- << "-bit float literal: " << GetParam().literal;
- EXPECT_THAT(CompileFailure(input.str()), Eq(expected_error.str()));
- }
- }
- // clang-format off
- INSTANTIATE_TEST_SUITE_P(
- TextToBinaryInvalidFloatConstant, OpConstantInvalidFloatConstant,
- ::testing::ValuesIn(std::vector<InvalidFloatConstantCase>{
- {16, "abc"},
- {16, "--1"},
- {16, "-+1"},
- {16, "+-1"},
- {16, "++1"},
- {16, "1e30"}, // Overflow is an error for 16-bit floats.
- {16, "-1e30"},
- {16, "1e40"},
- {16, "-1e40"},
- {16, "1e400"},
- {16, "-1e400"},
- {32, "abc"},
- {32, "--1"},
- {32, "-+1"},
- {32, "+-1"},
- {32, "++1"},
- {32, "1e40"}, // Overflow is an error for 32-bit floats.
- {32, "-1e40"},
- {32, "1e400"},
- {32, "-1e400"},
- {64, "abc"},
- {64, "--1"},
- {64, "-+1"},
- {64, "+-1"},
- {64, "++1"},
- {32, "1e400"}, // Overflow is an error for 64-bit floats.
- {32, "-1e400"},
- }));
- // clang-format on
- using OpConstantInvalidTypeTest =
- spvtest::TextToBinaryTestBase<::testing::TestWithParam<std::string>>;
- TEST_P(OpConstantInvalidTypeTest, InvalidTypes) {
- const std::string input = "%1 = " + GetParam() +
- "\n"
- "%2 = OpConstant %1 0\n";
- EXPECT_THAT(
- CompileFailure(input),
- Eq("Type for Constant must be a scalar floating point or integer type"));
- }
- // clang-format off
- INSTANTIATE_TEST_SUITE_P(
- TextToBinaryOpConstantInvalidValidType, OpConstantInvalidTypeTest,
- ::testing::ValuesIn(std::vector<std::string>{
- {"OpTypeVoid",
- "OpTypeBool",
- "OpTypeVector %a 32",
- "OpTypeMatrix %a 32",
- "OpTypeImage %a 1D 0 0 0 0 Unknown",
- "OpTypeSampler",
- "OpTypeSampledImage %a",
- "OpTypeArray %a %b",
- "OpTypeRuntimeArray %a",
- "OpTypeStruct %a",
- "OpTypeOpaque \"Foo\"",
- "OpTypePointer UniformConstant %a",
- "OpTypeFunction %a %b",
- "OpTypeEvent",
- "OpTypeDeviceEvent",
- "OpTypeReserveId",
- "OpTypeQueue",
- "OpTypePipe ReadOnly",
- // Skip OpTypeForwardPointer doesn't even produce a result ID.
- // The assembler errors out if we try to check it in this scenario.
- // Try at least one thing that isn't a type at all
- "OpNot %a %b"
- },
- }));
- // clang-format on
- using OpSpecConstantValidTest =
- spvtest::TextToBinaryTestBase<::testing::TestWithParam<ConstantTestCase>>;
- TEST_P(OpSpecConstantValidTest, ValidTypes) {
- const std::string input = "%1 = " + GetParam().constant_type +
- "\n"
- "%2 = OpSpecConstant %1 " +
- GetParam().constant_value + "\n";
- std::vector<uint32_t> instructions;
- EXPECT_THAT(CompiledInstructions(input),
- Eq(GetParam().expected_instructions));
- }
- // clang-format off
- INSTANTIATE_TEST_SUITE_P(
- TextToBinaryOpSpecConstantValid, OpSpecConstantValidTest,
- ::testing::ValuesIn(std::vector<ConstantTestCase>{
- // Check 16 bits
- {"OpTypeInt 16 0", "0x1234",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
- MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x1234})})},
- {"OpTypeInt 16 0", "0x8000",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
- MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x8000})})},
- {"OpTypeInt 16 1", "0x8000", // Test sign extension.
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
- MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0xffff8000})})},
- {"OpTypeInt 16 1", "-32",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
- MakeInstruction(spv::Op::OpSpecConstant, {1, 2, uint32_t(-32)})})},
- // Check 32 bits
- {"OpTypeInt 32 0", "42",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 0}),
- MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 42})})},
- {"OpTypeInt 32 1", "-32",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
- MakeInstruction(spv::Op::OpSpecConstant, {1, 2, uint32_t(-32)})})},
- {"OpTypeFloat 32", "1.0",
- Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
- MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x3f800000})})},
- {"OpTypeFloat 32", "10.0",
- Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
- MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x41200000})})},
- // Check 48 bits
- {"OpTypeInt 48 0", "0x1234",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 0}),
- MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x1234, 0})})},
- {"OpTypeInt 48 0", "0x800000000001",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 0}),
- MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 1, 0x00008000})})},
- {"OpTypeInt 48 1", "0x800000000000", // Test sign extension.
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 1}),
- MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0, 0xffff8000})})},
- {"OpTypeInt 48 1", "-32",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 1}),
- MakeInstruction(spv::Op::OpSpecConstant, {1, 2, uint32_t(-32), uint32_t(-1)})})},
- // Check 64 bits
- {"OpTypeInt 64 0", "0x1234",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
- MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x1234, 0})})},
- {"OpTypeInt 64 1", "0x1234",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
- MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x1234, 0})})},
- {"OpTypeInt 64 1", "-42",
- Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
- MakeInstruction(spv::Op::OpSpecConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})},
- }));
- // clang-format on
- using OpSpecConstantInvalidTypeTest =
- spvtest::TextToBinaryTestBase<::testing::TestWithParam<std::string>>;
- TEST_P(OpSpecConstantInvalidTypeTest, InvalidTypes) {
- const std::string input = "%1 = " + GetParam() +
- "\n"
- "%2 = OpSpecConstant %1 0\n";
- EXPECT_THAT(CompileFailure(input),
- Eq("Type for SpecConstant must be a scalar floating point or "
- "integer type"));
- }
- // clang-format off
- INSTANTIATE_TEST_SUITE_P(
- TextToBinaryOpSpecConstantInvalidValidType, OpSpecConstantInvalidTypeTest,
- ::testing::ValuesIn(std::vector<std::string>{
- {"OpTypeVoid",
- "OpTypeBool",
- "OpTypeVector %a 32",
- "OpTypeMatrix %a 32",
- "OpTypeImage %a 1D 0 0 0 0 Unknown",
- "OpTypeSampler",
- "OpTypeSampledImage %a",
- "OpTypeArray %a %b",
- "OpTypeRuntimeArray %a",
- "OpTypeStruct %a",
- "OpTypeOpaque \"Foo\"",
- "OpTypePointer UniformConstant %a",
- "OpTypeFunction %a %b",
- "OpTypeEvent",
- "OpTypeDeviceEvent",
- "OpTypeReserveId",
- "OpTypeQueue",
- "OpTypePipe ReadOnly",
- // Skip testing OpTypeForwardPointer because it doesn't even produce a result ID.
- // Try at least one thing that isn't a type at all
- "OpNot %a %b"
- },
- }));
- // clang-format on
- const int64_t kMaxUnsigned48Bit = (int64_t(1) << 48) - 1;
- const int64_t kMaxSigned48Bit = (int64_t(1) << 47) - 1;
- const int64_t kMinSigned48Bit = -kMaxSigned48Bit - 1;
- using ConstantRoundTripTest = RoundTripTest;
- TEST_P(ConstantRoundTripTest, DisassemblyEqualsAssemblyInput) {
- const std::string assembly = GetParam();
- EXPECT_THAT(EncodeAndDecodeSuccessfully(assembly), Eq(assembly)) << assembly;
- }
- INSTANTIATE_TEST_SUITE_P(
- OpConstantRoundTrip, ConstantRoundTripTest,
- ::testing::ValuesIn(std::vector<std::string>{
- // 16 bit
- "%1 = OpTypeInt 16 0\n%2 = OpConstant %1 0\n",
- "%1 = OpTypeInt 16 0\n%2 = OpConstant %1 65535\n",
- "%1 = OpTypeInt 16 1\n%2 = OpConstant %1 -32768\n",
- "%1 = OpTypeInt 16 1\n%2 = OpConstant %1 32767\n",
- "%1 = OpTypeInt 32 0\n%2 = OpConstant %1 0\n",
- // 32 bit
- std::string("%1 = OpTypeInt 32 0\n%2 = OpConstant %1 0\n"),
- std::string("%1 = OpTypeInt 32 0\n%2 = OpConstant %1 ") +
- std::to_string(std::numeric_limits<uint32_t>::max()) + "\n",
- std::string("%1 = OpTypeInt 32 1\n%2 = OpConstant %1 ") +
- std::to_string(std::numeric_limits<int32_t>::max()) + "\n",
- std::string("%1 = OpTypeInt 32 1\n%2 = OpConstant %1 ") +
- std::to_string(std::numeric_limits<int32_t>::min()) + "\n",
- // 48 bit
- std::string("%1 = OpTypeInt 48 0\n%2 = OpConstant %1 0\n"),
- std::string("%1 = OpTypeInt 48 0\n%2 = OpConstant %1 ") +
- std::to_string(kMaxUnsigned48Bit) + "\n",
- std::string("%1 = OpTypeInt 48 1\n%2 = OpConstant %1 ") +
- std::to_string(kMaxSigned48Bit) + "\n",
- std::string("%1 = OpTypeInt 48 1\n%2 = OpConstant %1 ") +
- std::to_string(kMinSigned48Bit) + "\n",
- // 64 bit
- std::string("%1 = OpTypeInt 64 0\n%2 = OpConstant %1 0\n"),
- std::string("%1 = OpTypeInt 64 0\n%2 = OpConstant %1 ") +
- std::to_string(std::numeric_limits<uint64_t>::max()) + "\n",
- std::string("%1 = OpTypeInt 64 1\n%2 = OpConstant %1 ") +
- std::to_string(std::numeric_limits<int64_t>::max()) + "\n",
- std::string("%1 = OpTypeInt 64 1\n%2 = OpConstant %1 ") +
- std::to_string(std::numeric_limits<int64_t>::min()) + "\n",
- // 32-bit float
- "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0\n",
- "%1 = OpTypeFloat 32\n%2 = OpConstant %1 13.5\n",
- "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -12.5\n",
- // 64-bit float
- "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0\n",
- "%1 = OpTypeFloat 64\n%2 = OpConstant %1 1.79767e+308\n",
- "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -1.79767e+308\n",
- }));
- INSTANTIATE_TEST_SUITE_P(
- OpConstantHalfRoundTrip, ConstantRoundTripTest,
- ::testing::ValuesIn(std::vector<std::string>{
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x0p+0\n",
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x0p+0\n",
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1p+0\n",
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.1p+0\n",
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.01p-1\n",
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.8p+1\n",
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ffcp+1\n",
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1p+0\n",
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.1p+0\n",
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.01p-1\n",
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.8p+1\n",
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.ffcp+1\n",
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1p-16\n", // some denorms
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1p-24\n",
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1p-24\n",
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1p+16\n", // +inf
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1p+16\n", // -inf
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.01p+16\n", // -inf
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.01p+16\n", // nan
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.11p+16\n", // nan
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ffp+16\n", // nan
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ffcp+16\n", // nan
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.004p+16\n", // nan
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.01p+16\n", // -nan
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.11p+16\n", // -nan
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.ffp+16\n", // -nan
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.ffcp+16\n", // -nan
- "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.004p+16\n", // -nan
- }));
- // clang-format off
- // (Clang-format really wants to break up these strings across lines.
- INSTANTIATE_TEST_SUITE_P(
- OpConstantRoundTripNonFinite, ConstantRoundTripTest,
- ::testing::ValuesIn(std::vector<std::string>{
- "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1p+128\n", // -inf
- "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1p+128\n", // inf
- "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.8p+128\n", // -nan
- "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.0002p+128\n", // -nan
- "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.0018p+128\n", // -nan
- "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.01ep+128\n", // -nan
- "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.fffffep+128\n", // -nan
- "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.8p+128\n", // +nan
- "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.0002p+128\n", // +nan
- "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.0018p+128\n", // +nan
- "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.01ep+128\n", // +nan
- "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.fffffep+128\n", // +nan
- "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1p+1024\n", // -inf
- "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1p+1024\n", // +inf
- "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.8p+1024\n", // -nan
- "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.0fp+1024\n", // -nan
- "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.0000000000001p+1024\n", // -nan
- "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.00003p+1024\n", // -nan
- "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.fffffffffffffp+1024\n", // -nan
- "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.8p+1024\n", // +nan
- "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.0fp+1024\n", // +nan
- "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.0000000000001p+1024\n", // -nan
- "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.00003p+1024\n", // -nan
- "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.fffffffffffffp+1024\n", // -nan
- }));
- // clang-format on
- INSTANTIATE_TEST_SUITE_P(
- OpSpecConstantRoundTrip, ConstantRoundTripTest,
- ::testing::ValuesIn(std::vector<std::string>{
- // 16 bit
- "%1 = OpTypeInt 16 0\n%2 = OpSpecConstant %1 0\n",
- "%1 = OpTypeInt 16 0\n%2 = OpSpecConstant %1 65535\n",
- "%1 = OpTypeInt 16 1\n%2 = OpSpecConstant %1 -32768\n",
- "%1 = OpTypeInt 16 1\n%2 = OpSpecConstant %1 32767\n",
- "%1 = OpTypeInt 32 0\n%2 = OpSpecConstant %1 0\n",
- // 32 bit
- std::string("%1 = OpTypeInt 32 0\n%2 = OpSpecConstant %1 0\n"),
- std::string("%1 = OpTypeInt 32 0\n%2 = OpSpecConstant %1 ") +
- std::to_string(std::numeric_limits<uint32_t>::max()) + "\n",
- std::string("%1 = OpTypeInt 32 1\n%2 = OpSpecConstant %1 ") +
- std::to_string(std::numeric_limits<int32_t>::max()) + "\n",
- std::string("%1 = OpTypeInt 32 1\n%2 = OpSpecConstant %1 ") +
- std::to_string(std::numeric_limits<int32_t>::min()) + "\n",
- // 48 bit
- std::string("%1 = OpTypeInt 48 0\n%2 = OpSpecConstant %1 0\n"),
- std::string("%1 = OpTypeInt 48 0\n%2 = OpSpecConstant %1 ") +
- std::to_string(kMaxUnsigned48Bit) + "\n",
- std::string("%1 = OpTypeInt 48 1\n%2 = OpSpecConstant %1 ") +
- std::to_string(kMaxSigned48Bit) + "\n",
- std::string("%1 = OpTypeInt 48 1\n%2 = OpSpecConstant %1 ") +
- std::to_string(kMinSigned48Bit) + "\n",
- // 64 bit
- std::string("%1 = OpTypeInt 64 0\n%2 = OpSpecConstant %1 0\n"),
- std::string("%1 = OpTypeInt 64 0\n%2 = OpSpecConstant %1 ") +
- std::to_string(std::numeric_limits<uint64_t>::max()) + "\n",
- std::string("%1 = OpTypeInt 64 1\n%2 = OpSpecConstant %1 ") +
- std::to_string(std::numeric_limits<int64_t>::max()) + "\n",
- std::string("%1 = OpTypeInt 64 1\n%2 = OpSpecConstant %1 ") +
- std::to_string(std::numeric_limits<int64_t>::min()) + "\n",
- // 32-bit float
- "%1 = OpTypeFloat 32\n%2 = OpSpecConstant %1 0\n",
- "%1 = OpTypeFloat 32\n%2 = OpSpecConstant %1 13.5\n",
- "%1 = OpTypeFloat 32\n%2 = OpSpecConstant %1 -12.5\n",
- // 64-bit float
- "%1 = OpTypeFloat 64\n%2 = OpSpecConstant %1 0\n",
- "%1 = OpTypeFloat 64\n%2 = OpSpecConstant %1 1.79767e+308\n",
- "%1 = OpTypeFloat 64\n%2 = OpSpecConstant %1 -1.79767e+308\n",
- }));
- // Test OpSpecConstantOp
- using OpSpecConstantOpTestWithIds =
- spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<spv::Op>>>;
- // The operands to the OpSpecConstantOp opcode are all Ids.
- TEST_P(OpSpecConstantOpTestWithIds, Assembly) {
- std::stringstream input;
- input << "%2 = OpSpecConstantOp %1 " << GetParam().name();
- for (auto id : GetParam().operands()) input << " %" << id;
- input << "\n";
- EXPECT_THAT(CompiledInstructions(input.str()),
- Eq(MakeInstruction(spv::Op::OpSpecConstantOp,
- {1, 2, uint32_t(GetParam().value())},
- GetParam().operands())));
- // Check the disassembler as well.
- EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str());
- }
- // clang-format off
- #define CASE1(NAME) { spv::Op::Op##NAME, #NAME, {3} }
- #define CASE2(NAME) { spv::Op::Op##NAME, #NAME, {3, 4} }
- #define CASE3(NAME) { spv::Op::Op##NAME, #NAME, {3, 4, 5} }
- #define CASE4(NAME) { spv::Op::Op##NAME, #NAME, {3, 4, 5, 6} }
- #define CASE5(NAME) { spv::Op::Op##NAME, #NAME, {3, 4, 5, 6, 7} }
- #define CASE6(NAME) { spv::Op::Op##NAME, #NAME, {3, 4, 5, 6, 7, 8} }
- INSTANTIATE_TEST_SUITE_P(
- TextToBinaryOpSpecConstantOp, OpSpecConstantOpTestWithIds,
- ::testing::ValuesIn(std::vector<EnumCase<spv::Op>>{
- // Conversion
- CASE1(SConvert),
- CASE1(FConvert),
- CASE1(ConvertFToS),
- CASE1(ConvertSToF),
- CASE1(ConvertFToU),
- CASE1(ConvertUToF),
- CASE1(UConvert),
- CASE1(ConvertPtrToU),
- CASE1(ConvertUToPtr),
- CASE1(GenericCastToPtr),
- CASE1(PtrCastToGeneric),
- CASE1(Bitcast),
- CASE1(QuantizeToF16),
- // Arithmetic
- CASE1(SNegate),
- CASE1(Not),
- CASE2(IAdd),
- CASE2(ISub),
- CASE2(IMul),
- CASE2(UDiv),
- CASE2(SDiv),
- CASE2(UMod),
- CASE2(SRem),
- CASE2(SMod),
- CASE2(ShiftRightLogical),
- CASE2(ShiftRightArithmetic),
- CASE2(ShiftLeftLogical),
- CASE2(BitwiseOr),
- CASE2(BitwiseAnd),
- CASE2(BitwiseXor),
- CASE1(FNegate),
- CASE2(FAdd),
- CASE2(FSub),
- CASE2(FMul),
- CASE2(FDiv),
- CASE2(FRem),
- CASE2(FMod),
- // Composite operations use literal numbers. So they're in another test.
- // Logical
- CASE2(LogicalOr),
- CASE2(LogicalAnd),
- CASE1(LogicalNot),
- CASE2(LogicalEqual),
- CASE2(LogicalNotEqual),
- CASE3(Select),
- // Comparison
- CASE2(IEqual),
- CASE2(INotEqual), // Allowed in 1.0 Rev 7
- CASE2(ULessThan),
- CASE2(SLessThan),
- CASE2(UGreaterThan),
- CASE2(SGreaterThan),
- CASE2(ULessThanEqual),
- CASE2(SLessThanEqual),
- CASE2(UGreaterThanEqual),
- CASE2(SGreaterThanEqual),
- // Memory
- // For AccessChain, there is a base Id, then a sequence of index Ids.
- // Having no index Ids is a corner case.
- CASE1(AccessChain),
- CASE2(AccessChain),
- CASE6(AccessChain),
- CASE1(InBoundsAccessChain),
- CASE2(InBoundsAccessChain),
- CASE6(InBoundsAccessChain),
- // PtrAccessChain also has an element Id.
- CASE2(PtrAccessChain),
- CASE3(PtrAccessChain),
- CASE6(PtrAccessChain),
- CASE2(InBoundsPtrAccessChain),
- CASE3(InBoundsPtrAccessChain),
- CASE6(InBoundsPtrAccessChain),
- }));
- #undef CASE1
- #undef CASE2
- #undef CASE3
- #undef CASE4
- #undef CASE5
- #undef CASE6
- // clang-format on
- using OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers =
- spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<spv::Op>>>;
- // The operands to the OpSpecConstantOp opcode are two Ids followed by a
- // sequence of literal numbers.
- TEST_P(OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers, Assembly) {
- std::stringstream input;
- input << "%2 = OpSpecConstantOp %1 " << GetParam().name() << " %3 %4";
- for (auto number : GetParam().operands()) input << " " << number;
- input << "\n";
- EXPECT_THAT(CompiledInstructions(input.str()),
- Eq(MakeInstruction(spv::Op::OpSpecConstantOp,
- {1, 2, uint32_t(GetParam().value()), 3, 4},
- GetParam().operands())));
- // Check the disassembler as well.
- EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str());
- }
- #define CASE(NAME) spv::Op::Op##NAME, #NAME
- INSTANTIATE_TEST_SUITE_P(
- TextToBinaryOpSpecConstantOp,
- OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers,
- ::testing::ValuesIn(std::vector<EnumCase<spv::Op>>{
- // For VectorShuffle, there are two vector operands, and at least
- // two selector Ids. OpenCL can have up to 16-element vectors.
- {CASE(VectorShuffle), {0, 0}},
- {CASE(VectorShuffle), {4, 3, 2, 1}},
- {CASE(VectorShuffle), {0, 2, 4, 6, 1, 3, 5, 7}},
- {CASE(VectorShuffle),
- {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}},
- // For CompositeInsert, there is an object to insert, the target
- // composite, and then literal indices.
- {CASE(CompositeInsert), {0}},
- {CASE(CompositeInsert), {4, 3, 99, 1}},
- }));
- using OpSpecConstantOpTestWithOneIdThenLiteralNumbers =
- spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<spv::Op>>>;
- // The operands to the OpSpecConstantOp opcode are one Id followed by a
- // sequence of literal numbers.
- TEST_P(OpSpecConstantOpTestWithOneIdThenLiteralNumbers, Assembly) {
- std::stringstream input;
- input << "%2 = OpSpecConstantOp %1 " << GetParam().name() << " %3";
- for (auto number : GetParam().operands()) input << " " << number;
- input << "\n";
- EXPECT_THAT(CompiledInstructions(input.str()),
- Eq(MakeInstruction(spv::Op::OpSpecConstantOp,
- {1, 2, uint32_t(GetParam().value()), 3},
- GetParam().operands())));
- // Check the disassembler as well.
- EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str());
- }
- #define CASE(NAME) spv::Op::Op##NAME, #NAME
- INSTANTIATE_TEST_SUITE_P(
- TextToBinaryOpSpecConstantOp,
- OpSpecConstantOpTestWithOneIdThenLiteralNumbers,
- ::testing::ValuesIn(std::vector<EnumCase<spv::Op>>{
- // For CompositeExtract, the universal limit permits up to 255 literal
- // indices. Let's only test a few.
- {CASE(CompositeExtract), {0}},
- {CASE(CompositeExtract), {0, 99, 42, 16, 17, 12, 19}},
- }));
- // TODO(dneto): OpConstantTrue
- // TODO(dneto): OpConstantFalse
- // TODO(dneto): OpConstantComposite
- // TODO(dneto): OpConstantSampler: other variations Param is 0 or 1
- // TODO(dneto): OpConstantNull
- // TODO(dneto): OpSpecConstantTrue
- // TODO(dneto): OpSpecConstantFalse
- // TODO(dneto): OpSpecConstantComposite
- // TODO(dneto): Negative tests for OpSpecConstantOp
- } // namespace
- } // namespace spvtools
|