From 37547b230483a4b7b514006b152ab9318ae5d125 Mon Sep 17 00:00:00 2001 From: David Neto Date: Thu, 10 Sep 2015 13:23:11 -0400 Subject: [PATCH] Assembler tests for all decorations except Linkage attributes Fixes typos in various parser tables. Updates readme.md with the fixes. --- CMakeLists.txt | 1 + readme.md | 6 + source/operand.cpp | 10 +- test/TextToBinary.Annotation.cpp | 246 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 258 insertions(+), 5 deletions(-) create mode 100644 test/TextToBinary.Annotation.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index eab48a2..58eca15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -185,6 +185,7 @@ if (NOT ${SPIRV_SKIP_EXECUTABLES}) ${CMAKE_CURRENT_SOURCE_DIR}/test/TextLiteral.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/TextStartsNewInst.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/TextToBinary.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/TextToBinary.Annotation.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/TextToBinary.Debug.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/TextToBinary.Miscellaneous.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/TextWordGet.cpp diff --git a/readme.md b/readme.md index befeb5e..4ebc22f 100644 --- a/readme.md +++ b/readme.md @@ -27,6 +27,12 @@ The validator is incomplete. See the Future Work section for more information. ## CHANGES (for tools hackers) +* Fixes decorations: + * Names: SaturatedConversion, FuncParamAttr NoCapture + * Values: Fixes values for some decorations: BuiltIn LocalInvocationId, and BuiltIn + SubgroupId + * All handling of FPFastMathMode masks. + 2015-09-09 * Avoid confusion about ownership of storage: * `spv_binary` is only used for output of the assembler, and should diff --git a/source/operand.cpp b/source/operand.cpp index 68212e1..1f15f54 100644 --- a/source/operand.cpp +++ b/source/operand.cpp @@ -522,7 +522,7 @@ static const spv_operand_desc_t functionParameterAttributeEntries[] = { SPV_OPCODE_FLAGS_CAPABILITIES, CapabilityKernel, {SPV_OPERAND_TYPE_NONE}}, - {"NoCapabilityture", + {"NoCapture", FunctionParameterAttributeNoCapture, SPV_OPCODE_FLAGS_CAPABILITIES, CapabilityKernel, @@ -682,7 +682,7 @@ static const spv_operand_desc_t decorationEntries[] = { SPV_OPCODE_FLAGS_NONE, 0, {SPV_OPERAND_TYPE_NONE}}, - {"FPSaturatedConversion", + {"SaturatedConversion", DecorationSaturatedConversion, SPV_OPCODE_FLAGS_CAPABILITIES, CapabilityKernel, @@ -743,7 +743,7 @@ static const spv_operand_desc_t decorationEntries[] = { CapabilityKernel, {SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_NONE}}, {"FPFastMathMode", - DecorationFPRoundingMode, + DecorationFPFastMathMode, SPV_OPCODE_FLAGS_CAPABILITIES, CapabilityKernel, {SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, SPV_OPERAND_TYPE_NONE}}, @@ -896,7 +896,7 @@ static const spv_operand_desc_t builtInEntries[] = { 0, {SPV_OPERAND_TYPE_NONE}}, {"LocalInvocationIndex", - BuiltInLocalInvocationId, + BuiltInLocalInvocationIndex, SPV_OPCODE_FLAGS_CAPABILITIES, CapabilityShader, {SPV_OPERAND_TYPE_NONE}}, @@ -951,7 +951,7 @@ static const spv_operand_desc_t builtInEntries[] = { CapabilityKernel, {SPV_OPERAND_TYPE_NONE}}, {"SubgroupId", - BuiltInSampleId, + BuiltInSubgroupId, SPV_OPCODE_FLAGS_CAPABILITIES, CapabilityKernel, {SPV_OPERAND_TYPE_NONE}}, diff --git a/test/TextToBinary.Annotation.cpp b/test/TextToBinary.Annotation.cpp new file mode 100644 index 0000000..9844c73 --- /dev/null +++ b/test/TextToBinary.Annotation.cpp @@ -0,0 +1,246 @@ +// Copyright (c) 2015 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + +// Assembler tests for instructions in the "Annotation" section of the +// SPIR-V spec. + +#include "UnitSPIRV.h" + +#include + +#include "gmock/gmock.h" +#include "TestFixture.h" + +namespace { + +using spvtest::MakeInstruction; +using spvtest::MakeVector; +using ::testing::Eq; + +// Test OpDecorate + +// A single test case for a simple OpDecorate. +// Simple decorations have no operands, or just literal numbers +// as operands. +struct DecorateSimpleCase { + // Place the enum value first, so it's easier to read the binary dumps when + // the test fails. + const spv::Decoration decoration; + const std::string name; + const std::vector operands; +}; + +using OpDecorateSimpleTest = + test_fixture::TextToBinaryTestBase<::testing::TestWithParam>; + +TEST_P(OpDecorateSimpleTest, AnySimpleDecoration) { + // This string should assemble, but should not validate. + std::stringstream input; + input << "OpDecorate %1 " << GetParam().name; + for (auto operand : GetParam().operands) input << " " << operand; + std::vector expected_operands{1, uint32_t(GetParam().decoration)}; + expected_operands.insert(expected_operands.end(), GetParam().operands.begin(), + GetParam().operands.end()); + EXPECT_THAT(CompiledInstructions(input.str()), + Eq(MakeInstruction(spv::OpDecorate, expected_operands))); +} + +#define CASE(NAME) spv::Decoration##NAME, #NAME +INSTANTIATE_TEST_CASE_P(TextToBinaryDecorateSimple, OpDecorateSimpleTest, + ::testing::ValuesIn(std::vector{ + // The operand literal values are arbitrarily chosen, + // but there are the right number of them. + {CASE(RelaxedPrecision), {}}, + {CASE(SpecId), {100}}, + {CASE(Block), {}}, + {CASE(BufferBlock), {}}, + {CASE(RowMajor), {}}, + {CASE(ColMajor), {}}, + {CASE(ArrayStride), {4}}, + {CASE(MatrixStride), {16}}, + {CASE(GLSLShared), {}}, + {CASE(GLSLPacked), {}}, + {CASE(CPacked), {}}, + {CASE(Smooth), {}}, + {CASE(Noperspective), {}}, + {CASE(Flat), {}}, + {CASE(Patch), {}}, + {CASE(Centroid), {}}, + {CASE(Sample), {}}, + {CASE(Invariant), {}}, + {CASE(Restrict), {}}, + {CASE(Aliased), {}}, + {CASE(Volatile), {}}, + {CASE(Constant), {}}, + {CASE(Coherent), {}}, + {CASE(Nonwritable), {}}, + {CASE(Nonreadable), {}}, + {CASE(Uniform), {}}, + {CASE(NoStaticUse), {}}, + {CASE(SaturatedConversion), {}}, + {CASE(Stream), {2}}, + {CASE(Location), {6}}, + {CASE(Component), {3}}, + {CASE(Index), {14}}, + {CASE(Binding), {19}}, + {CASE(DescriptorSet), {7}}, + {CASE(Offset), {12}}, + {CASE(XfbBuffer), {1}}, + {CASE(XfbStride), {8}}, + })); +#undef CASE + +// A single test case for an enum decoration. +struct DecorateEnumCase { + // Place the enum value first, so it's easier to read the binary dumps when + // the test fails. + const uint32_t value; // The value within the enum, e.g. Position + const std::string name; + const uint32_t enum_value; // Which enum, e.g. BuiltIn + const std::string enum_name; +}; + +using OpDecorateEnumTest = test_fixture::TextToBinaryTestBase< + ::testing::TestWithParam>; + +TEST_P(OpDecorateEnumTest, AnyEnumDecoration) { + // This string should assemble, but should not validate. + std::string input = "OpDecorate %1 " + GetParam().enum_name + " " + GetParam().name; + EXPECT_THAT(CompiledInstructions(input), + Eq(MakeInstruction(spv::OpDecorate, {1, GetParam().enum_value, GetParam().value}))); +} + +// Test OpDecorate BuiltIn. +// clang-format off +#define CASE(NAME) \ + { spv::BuiltIn##NAME, #NAME, spv::DecorationBuiltIn, "BuiltIn" } +INSTANTIATE_TEST_CASE_P(TextToBinaryDecorateBuiltIn, OpDecorateEnumTest, + ::testing::ValuesIn(std::vector{ + CASE(Position), + CASE(PointSize), + CASE(ClipDistance), + CASE(CullDistance), + CASE(VertexId), + CASE(InstanceId), + CASE(PrimitiveId), + CASE(InvocationId), + CASE(Layer), + CASE(ViewportIndex), + CASE(TessLevelOuter), + CASE(TessLevelInner), + CASE(TessCoord), + CASE(PatchVertices), + CASE(FragCoord), + CASE(PointCoord), + CASE(FrontFacing), + CASE(SampleId), + CASE(SamplePosition), + CASE(SampleMask), + CASE(FragColor), + CASE(FragDepth), + CASE(HelperInvocation), + CASE(NumWorkgroups), + CASE(WorkgroupSize), + CASE(WorkgroupId), + CASE(LocalInvocationId), + CASE(GlobalInvocationId), + CASE(LocalInvocationIndex), + CASE(WorkDim), + CASE(GlobalSize), + CASE(EnqueuedWorkgroupSize), + CASE(GlobalOffset), + CASE(GlobalLinearId), + CASE(WorkgroupLinearId), + CASE(SubgroupSize), + CASE(SubgroupMaxSize), + CASE(NumSubgroups), + CASE(NumEnqueuedSubgroups), + CASE(SubgroupId), + CASE(SubgroupLocalInvocationId), + })); +#undef CASE +// clang-format on + +// Test OpDecorate FuncParamAttr +// clang-format off +#define CASE(NAME) \ + { spv::FunctionParameterAttribute##NAME, #NAME, spv::DecorationFuncParamAttr, "FuncParamAttr" } +INSTANTIATE_TEST_CASE_P(TextToBinaryDecorateFuncParamAttr, OpDecorateEnumTest, + ::testing::ValuesIn(std::vector{ + CASE(Zext), + CASE(Sext), + CASE(ByVal), + CASE(Sret), + CASE(NoAlias), + CASE(NoCapture), + CASE(NoWrite), + CASE(NoReadWrite), + })); +#undef CASE +// clang-format on + +// Test OpDecorate FPRoundingMode +// clang-format off +#define CASE(NAME) \ + { spv::FPRoundingMode##NAME, #NAME, spv::DecorationFPRoundingMode, "FPRoundingMode" } +INSTANTIATE_TEST_CASE_P(TextToBinaryDecorateFPRoundingMode, OpDecorateEnumTest, + ::testing::ValuesIn(std::vector{ + CASE(RTE), + CASE(RTZ), + CASE(RTP), + CASE(RTN), + })); +#undef CASE +// clang-format on + +// Test OpDecorate FPFastMathMode. +// These can by named enums for the single-bit masks. However, we don't support +// symbolic combinations of the masks. Rather, they can use ! +// syntax, e.g. !0x3 + +// clang-format off +#define CASE(ENUM,NAME) \ + { spv::FPFastMathMode##ENUM, #NAME, spv::DecorationFPFastMathMode, "FPFastMathMode" } +INSTANTIATE_TEST_CASE_P(TextToBinaryDecorateFPFastMathMode, OpDecorateEnumTest, + ::testing::ValuesIn(std::vector{ + CASE(MaskNone, None), + CASE(NotNaNMask, NotNaN), + CASE(NotInfMask, NotInf), + CASE(NSZMask, NSZ), + CASE(AllowRecipMask, AllowRecip), + CASE(FastMask, Fast), + })); +#undef CASE +// clang-format on + +// TODO(dneto): OpDecorate with Linkage attributes + +// TODO(dneto): OpMemberDecorate +// TODO(dneto): OpDecorationGroup +// TODO(dneto): OpGroupDecorate +// TODO(dneto): OpGroupMemberDecorate + +} // anonymous namespace -- 2.7.4