1fd4e5da5Sopenharmony_ci// Copyright (c) 2015-2016 The Khronos Group Inc. 2fd4e5da5Sopenharmony_ci// 3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License. 5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at 6fd4e5da5Sopenharmony_ci// 7fd4e5da5Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8fd4e5da5Sopenharmony_ci// 9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and 13fd4e5da5Sopenharmony_ci// limitations under the License. 14fd4e5da5Sopenharmony_ci 15fd4e5da5Sopenharmony_ci// Assembler tests for instructions in the "Mode-Setting" section of the 16fd4e5da5Sopenharmony_ci// SPIR-V spec. 17fd4e5da5Sopenharmony_ci 18fd4e5da5Sopenharmony_ci#include <string> 19fd4e5da5Sopenharmony_ci#include <tuple> 20fd4e5da5Sopenharmony_ci#include <vector> 21fd4e5da5Sopenharmony_ci 22fd4e5da5Sopenharmony_ci#include "gmock/gmock.h" 23fd4e5da5Sopenharmony_ci#include "source/util/string_utils.h" 24fd4e5da5Sopenharmony_ci#include "test/test_fixture.h" 25fd4e5da5Sopenharmony_ci#include "test/unit_spirv.h" 26fd4e5da5Sopenharmony_ci 27fd4e5da5Sopenharmony_cinamespace spvtools { 28fd4e5da5Sopenharmony_cinamespace { 29fd4e5da5Sopenharmony_ci 30fd4e5da5Sopenharmony_ciusing spvtest::EnumCase; 31fd4e5da5Sopenharmony_ciusing spvtest::MakeInstruction; 32fd4e5da5Sopenharmony_ciusing utils::MakeVector; 33fd4e5da5Sopenharmony_ciusing ::testing::Combine; 34fd4e5da5Sopenharmony_ciusing ::testing::Eq; 35fd4e5da5Sopenharmony_ciusing ::testing::TestWithParam; 36fd4e5da5Sopenharmony_ciusing ::testing::Values; 37fd4e5da5Sopenharmony_ciusing ::testing::ValuesIn; 38fd4e5da5Sopenharmony_ci 39fd4e5da5Sopenharmony_ci// Test OpMemoryModel 40fd4e5da5Sopenharmony_ci 41fd4e5da5Sopenharmony_ci// An example case for OpMemoryModel 42fd4e5da5Sopenharmony_cistruct MemoryModelCase { 43fd4e5da5Sopenharmony_ci uint32_t get_addressing_value() const { 44fd4e5da5Sopenharmony_ci return static_cast<uint32_t>(addressing_value); 45fd4e5da5Sopenharmony_ci } 46fd4e5da5Sopenharmony_ci uint32_t get_memory_value() const { 47fd4e5da5Sopenharmony_ci return static_cast<uint32_t>(memory_value); 48fd4e5da5Sopenharmony_ci } 49fd4e5da5Sopenharmony_ci spv::AddressingModel addressing_value; 50fd4e5da5Sopenharmony_ci std::string addressing_name; 51fd4e5da5Sopenharmony_ci spv::MemoryModel memory_value; 52fd4e5da5Sopenharmony_ci std::string memory_name; 53fd4e5da5Sopenharmony_ci}; 54fd4e5da5Sopenharmony_ci 55fd4e5da5Sopenharmony_ciusing OpMemoryModelTest = 56fd4e5da5Sopenharmony_ci spvtest::TextToBinaryTestBase<TestWithParam<MemoryModelCase>>; 57fd4e5da5Sopenharmony_ci 58fd4e5da5Sopenharmony_ciTEST_P(OpMemoryModelTest, AnyMemoryModelCase) { 59fd4e5da5Sopenharmony_ci const std::string input = "OpMemoryModel " + GetParam().addressing_name + 60fd4e5da5Sopenharmony_ci " " + GetParam().memory_name; 61fd4e5da5Sopenharmony_ci EXPECT_THAT(CompiledInstructions(input), 62fd4e5da5Sopenharmony_ci Eq(MakeInstruction(spv::Op::OpMemoryModel, 63fd4e5da5Sopenharmony_ci {GetParam().get_addressing_value(), 64fd4e5da5Sopenharmony_ci GetParam().get_memory_value()}))); 65fd4e5da5Sopenharmony_ci} 66fd4e5da5Sopenharmony_ci 67fd4e5da5Sopenharmony_ci#define CASE(ADDRESSING, MEMORY) \ 68fd4e5da5Sopenharmony_ci { \ 69fd4e5da5Sopenharmony_ci spv::AddressingModel::ADDRESSING, #ADDRESSING, spv::MemoryModel::MEMORY, \ 70fd4e5da5Sopenharmony_ci #MEMORY \ 71fd4e5da5Sopenharmony_ci } 72fd4e5da5Sopenharmony_ci// clang-format off 73fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(TextToBinaryMemoryModel, OpMemoryModelTest, 74fd4e5da5Sopenharmony_ci ValuesIn(std::vector<MemoryModelCase>{ 75fd4e5da5Sopenharmony_ci // These cases exercise each addressing model, and 76fd4e5da5Sopenharmony_ci // each memory model, but not necessarily in 77fd4e5da5Sopenharmony_ci // combination. 78fd4e5da5Sopenharmony_ci CASE(Logical,Simple), 79fd4e5da5Sopenharmony_ci CASE(Logical,GLSL450), 80fd4e5da5Sopenharmony_ci CASE(Physical32,OpenCL), 81fd4e5da5Sopenharmony_ci CASE(Physical64,OpenCL), 82fd4e5da5Sopenharmony_ci })); 83fd4e5da5Sopenharmony_ci#undef CASE 84fd4e5da5Sopenharmony_ci// clang-format on 85fd4e5da5Sopenharmony_ci 86fd4e5da5Sopenharmony_ciTEST_F(OpMemoryModelTest, WrongModel) { 87fd4e5da5Sopenharmony_ci EXPECT_THAT(CompileFailure("OpMemoryModel xxyyzz Simple"), 88fd4e5da5Sopenharmony_ci Eq("Invalid addressing model 'xxyyzz'.")); 89fd4e5da5Sopenharmony_ci EXPECT_THAT(CompileFailure("OpMemoryModel Logical xxyyzz"), 90fd4e5da5Sopenharmony_ci Eq("Invalid memory model 'xxyyzz'.")); 91fd4e5da5Sopenharmony_ci} 92fd4e5da5Sopenharmony_ci 93fd4e5da5Sopenharmony_ci// Test OpEntryPoint 94fd4e5da5Sopenharmony_ci 95fd4e5da5Sopenharmony_ci// An example case for OpEntryPoint 96fd4e5da5Sopenharmony_cistruct EntryPointCase { 97fd4e5da5Sopenharmony_ci uint32_t get_execution_value() const { 98fd4e5da5Sopenharmony_ci return static_cast<uint32_t>(execution_value); 99fd4e5da5Sopenharmony_ci } 100fd4e5da5Sopenharmony_ci spv::ExecutionModel execution_value; 101fd4e5da5Sopenharmony_ci std::string execution_name; 102fd4e5da5Sopenharmony_ci std::string entry_point_name; 103fd4e5da5Sopenharmony_ci}; 104fd4e5da5Sopenharmony_ci 105fd4e5da5Sopenharmony_ciusing OpEntryPointTest = 106fd4e5da5Sopenharmony_ci spvtest::TextToBinaryTestBase<TestWithParam<EntryPointCase>>; 107fd4e5da5Sopenharmony_ci 108fd4e5da5Sopenharmony_ciTEST_P(OpEntryPointTest, AnyEntryPointCase) { 109fd4e5da5Sopenharmony_ci // TODO(dneto): utf-8, escaping, quoting cases for entry point name. 110fd4e5da5Sopenharmony_ci const std::string input = "OpEntryPoint " + GetParam().execution_name + 111fd4e5da5Sopenharmony_ci " %1 \"" + GetParam().entry_point_name + "\""; 112fd4e5da5Sopenharmony_ci EXPECT_THAT(CompiledInstructions(input), 113fd4e5da5Sopenharmony_ci Eq(MakeInstruction(spv::Op::OpEntryPoint, 114fd4e5da5Sopenharmony_ci {GetParam().get_execution_value(), 1}, 115fd4e5da5Sopenharmony_ci MakeVector(GetParam().entry_point_name)))); 116fd4e5da5Sopenharmony_ci} 117fd4e5da5Sopenharmony_ci 118fd4e5da5Sopenharmony_ci// clang-format off 119fd4e5da5Sopenharmony_ci#define CASE(NAME) spv::ExecutionModel::NAME, #NAME 120fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(TextToBinaryEntryPoint, OpEntryPointTest, 121fd4e5da5Sopenharmony_ci ValuesIn(std::vector<EntryPointCase>{ 122fd4e5da5Sopenharmony_ci { CASE(Vertex), "" }, 123fd4e5da5Sopenharmony_ci { CASE(TessellationControl), "my tess" }, 124fd4e5da5Sopenharmony_ci { CASE(TessellationEvaluation), "really fancy" }, 125fd4e5da5Sopenharmony_ci { CASE(Geometry), "Euclid" }, 126fd4e5da5Sopenharmony_ci { CASE(Fragment), "FAT32" }, 127fd4e5da5Sopenharmony_ci { CASE(GLCompute), "cubic" }, 128fd4e5da5Sopenharmony_ci { CASE(Kernel), "Sanders" }, 129fd4e5da5Sopenharmony_ci })); 130fd4e5da5Sopenharmony_ci#undef CASE 131fd4e5da5Sopenharmony_ci// clang-format on 132fd4e5da5Sopenharmony_ci 133fd4e5da5Sopenharmony_ciTEST_F(OpEntryPointTest, WrongModel) { 134fd4e5da5Sopenharmony_ci EXPECT_THAT(CompileFailure("OpEntryPoint xxyyzz %1 \"fun\""), 135fd4e5da5Sopenharmony_ci Eq("Invalid execution model 'xxyyzz'.")); 136fd4e5da5Sopenharmony_ci} 137fd4e5da5Sopenharmony_ci 138fd4e5da5Sopenharmony_ci// Test OpExecutionMode 139fd4e5da5Sopenharmony_ciusing OpExecutionModeTest = spvtest::TextToBinaryTestBase< 140fd4e5da5Sopenharmony_ci TestWithParam<std::tuple<spv_target_env, EnumCase<spv::ExecutionMode>>>>; 141fd4e5da5Sopenharmony_ci 142fd4e5da5Sopenharmony_ciTEST_P(OpExecutionModeTest, AnyExecutionMode) { 143fd4e5da5Sopenharmony_ci // This string should assemble, but should not validate. 144fd4e5da5Sopenharmony_ci std::stringstream input; 145fd4e5da5Sopenharmony_ci input << "OpExecutionMode %1 " << std::get<1>(GetParam()).name(); 146fd4e5da5Sopenharmony_ci for (auto operand : std::get<1>(GetParam()).operands()) 147fd4e5da5Sopenharmony_ci input << " " << operand; 148fd4e5da5Sopenharmony_ci EXPECT_THAT(CompiledInstructions(input.str(), std::get<0>(GetParam())), 149fd4e5da5Sopenharmony_ci Eq(MakeInstruction(spv::Op::OpExecutionMode, 150fd4e5da5Sopenharmony_ci {1, std::get<1>(GetParam()).value()}, 151fd4e5da5Sopenharmony_ci std::get<1>(GetParam()).operands()))); 152fd4e5da5Sopenharmony_ci} 153fd4e5da5Sopenharmony_ci 154fd4e5da5Sopenharmony_ci#define CASE(NAME) spv::ExecutionMode::NAME, #NAME 155fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P( 156fd4e5da5Sopenharmony_ci TextToBinaryExecutionMode, OpExecutionModeTest, 157fd4e5da5Sopenharmony_ci Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1), 158fd4e5da5Sopenharmony_ci ValuesIn(std::vector<EnumCase<spv::ExecutionMode>>{ 159fd4e5da5Sopenharmony_ci // The operand literal values are arbitrarily chosen, 160fd4e5da5Sopenharmony_ci // but there are the right number of them. 161fd4e5da5Sopenharmony_ci {CASE(Invocations), {101}}, 162fd4e5da5Sopenharmony_ci {CASE(SpacingEqual), {}}, 163fd4e5da5Sopenharmony_ci {CASE(SpacingFractionalEven), {}}, 164fd4e5da5Sopenharmony_ci {CASE(SpacingFractionalOdd), {}}, 165fd4e5da5Sopenharmony_ci {CASE(VertexOrderCw), {}}, 166fd4e5da5Sopenharmony_ci {CASE(VertexOrderCcw), {}}, 167fd4e5da5Sopenharmony_ci {CASE(PixelCenterInteger), {}}, 168fd4e5da5Sopenharmony_ci {CASE(OriginUpperLeft), {}}, 169fd4e5da5Sopenharmony_ci {CASE(OriginLowerLeft), {}}, 170fd4e5da5Sopenharmony_ci {CASE(EarlyFragmentTests), {}}, 171fd4e5da5Sopenharmony_ci {CASE(PointMode), {}}, 172fd4e5da5Sopenharmony_ci {CASE(Xfb), {}}, 173fd4e5da5Sopenharmony_ci {CASE(DepthReplacing), {}}, 174fd4e5da5Sopenharmony_ci {CASE(DepthGreater), {}}, 175fd4e5da5Sopenharmony_ci {CASE(DepthLess), {}}, 176fd4e5da5Sopenharmony_ci {CASE(DepthUnchanged), {}}, 177fd4e5da5Sopenharmony_ci {CASE(LocalSize), {64, 1, 2}}, 178fd4e5da5Sopenharmony_ci {CASE(LocalSizeHint), {8, 2, 4}}, 179fd4e5da5Sopenharmony_ci {CASE(InputPoints), {}}, 180fd4e5da5Sopenharmony_ci {CASE(InputLines), {}}, 181fd4e5da5Sopenharmony_ci {CASE(InputLinesAdjacency), {}}, 182fd4e5da5Sopenharmony_ci {CASE(Triangles), {}}, 183fd4e5da5Sopenharmony_ci {CASE(InputTrianglesAdjacency), {}}, 184fd4e5da5Sopenharmony_ci {CASE(Quads), {}}, 185fd4e5da5Sopenharmony_ci {CASE(Isolines), {}}, 186fd4e5da5Sopenharmony_ci {CASE(OutputVertices), {21}}, 187fd4e5da5Sopenharmony_ci {CASE(OutputPoints), {}}, 188fd4e5da5Sopenharmony_ci {CASE(OutputLineStrip), {}}, 189fd4e5da5Sopenharmony_ci {CASE(OutputTriangleStrip), {}}, 190fd4e5da5Sopenharmony_ci {CASE(VecTypeHint), {96}}, 191fd4e5da5Sopenharmony_ci {CASE(ContractionOff), {}}, 192fd4e5da5Sopenharmony_ci {CASE(SubgroupUniformControlFlowKHR), {}}, 193fd4e5da5Sopenharmony_ci }))); 194fd4e5da5Sopenharmony_ci 195fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P( 196fd4e5da5Sopenharmony_ci TextToBinaryExecutionModeV11, OpExecutionModeTest, 197fd4e5da5Sopenharmony_ci Combine(Values(SPV_ENV_UNIVERSAL_1_1), 198fd4e5da5Sopenharmony_ci ValuesIn(std::vector<EnumCase<spv::ExecutionMode>>{ 199fd4e5da5Sopenharmony_ci {CASE(Initializer)}, 200fd4e5da5Sopenharmony_ci {CASE(Finalizer)}, 201fd4e5da5Sopenharmony_ci {CASE(SubgroupSize), {12}}, 202fd4e5da5Sopenharmony_ci {CASE(SubgroupsPerWorkgroup), {64}}}))); 203fd4e5da5Sopenharmony_ci#undef CASE 204fd4e5da5Sopenharmony_ci 205fd4e5da5Sopenharmony_ciTEST_F(OpExecutionModeTest, WrongMode) { 206fd4e5da5Sopenharmony_ci EXPECT_THAT(CompileFailure("OpExecutionMode %1 xxyyzz"), 207fd4e5da5Sopenharmony_ci Eq("Invalid execution mode 'xxyyzz'.")); 208fd4e5da5Sopenharmony_ci} 209fd4e5da5Sopenharmony_ci 210fd4e5da5Sopenharmony_ciTEST_F(OpExecutionModeTest, TooManyModes) { 211fd4e5da5Sopenharmony_ci EXPECT_THAT(CompileFailure("OpExecutionMode %1 Xfb PointMode"), 212fd4e5da5Sopenharmony_ci Eq("Expected <opcode> or <result-id> at the beginning of an " 213fd4e5da5Sopenharmony_ci "instruction, found 'PointMode'.")); 214fd4e5da5Sopenharmony_ci} 215fd4e5da5Sopenharmony_ci 216fd4e5da5Sopenharmony_ci// Test OpCapability 217fd4e5da5Sopenharmony_ci 218fd4e5da5Sopenharmony_ciusing OpCapabilityTest = 219fd4e5da5Sopenharmony_ci spvtest::TextToBinaryTestBase<TestWithParam<EnumCase<spv::Capability>>>; 220fd4e5da5Sopenharmony_ci 221fd4e5da5Sopenharmony_ciTEST_P(OpCapabilityTest, AnyCapability) { 222fd4e5da5Sopenharmony_ci const std::string input = "OpCapability " + GetParam().name(); 223fd4e5da5Sopenharmony_ci EXPECT_THAT(CompiledInstructions(input), 224fd4e5da5Sopenharmony_ci Eq(MakeInstruction(spv::Op::OpCapability, {GetParam().value()}))); 225fd4e5da5Sopenharmony_ci} 226fd4e5da5Sopenharmony_ci 227fd4e5da5Sopenharmony_ci// clang-format off 228fd4e5da5Sopenharmony_ci#define CASE(NAME) { spv::Capability::NAME, #NAME } 229fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(TextToBinaryCapability, OpCapabilityTest, 230fd4e5da5Sopenharmony_ci ValuesIn(std::vector<EnumCase<spv::Capability>>{ 231fd4e5da5Sopenharmony_ci CASE(Matrix), 232fd4e5da5Sopenharmony_ci CASE(Shader), 233fd4e5da5Sopenharmony_ci CASE(Geometry), 234fd4e5da5Sopenharmony_ci CASE(Tessellation), 235fd4e5da5Sopenharmony_ci CASE(Addresses), 236fd4e5da5Sopenharmony_ci CASE(Linkage), 237fd4e5da5Sopenharmony_ci CASE(Kernel), 238fd4e5da5Sopenharmony_ci CASE(Vector16), 239fd4e5da5Sopenharmony_ci CASE(Float16Buffer), 240fd4e5da5Sopenharmony_ci CASE(Float16), 241fd4e5da5Sopenharmony_ci CASE(Float64), 242fd4e5da5Sopenharmony_ci CASE(Int64), 243fd4e5da5Sopenharmony_ci CASE(Int64Atomics), 244fd4e5da5Sopenharmony_ci CASE(ImageBasic), 245fd4e5da5Sopenharmony_ci CASE(ImageReadWrite), 246fd4e5da5Sopenharmony_ci CASE(ImageMipmap), 247fd4e5da5Sopenharmony_ci // Value 16 intentionally missing 248fd4e5da5Sopenharmony_ci CASE(Pipes), 249fd4e5da5Sopenharmony_ci CASE(Groups), 250fd4e5da5Sopenharmony_ci CASE(DeviceEnqueue), 251fd4e5da5Sopenharmony_ci CASE(LiteralSampler), 252fd4e5da5Sopenharmony_ci CASE(AtomicStorage), 253fd4e5da5Sopenharmony_ci CASE(Int16), 254fd4e5da5Sopenharmony_ci CASE(TessellationPointSize), 255fd4e5da5Sopenharmony_ci CASE(GeometryPointSize), 256fd4e5da5Sopenharmony_ci CASE(ImageGatherExtended), 257fd4e5da5Sopenharmony_ci // Value 26 intentionally missing 258fd4e5da5Sopenharmony_ci CASE(StorageImageMultisample), 259fd4e5da5Sopenharmony_ci CASE(UniformBufferArrayDynamicIndexing), 260fd4e5da5Sopenharmony_ci CASE(SampledImageArrayDynamicIndexing), 261fd4e5da5Sopenharmony_ci CASE(StorageBufferArrayDynamicIndexing), 262fd4e5da5Sopenharmony_ci CASE(StorageImageArrayDynamicIndexing), 263fd4e5da5Sopenharmony_ci CASE(ClipDistance), 264fd4e5da5Sopenharmony_ci CASE(CullDistance), 265fd4e5da5Sopenharmony_ci CASE(ImageCubeArray), 266fd4e5da5Sopenharmony_ci CASE(SampleRateShading), 267fd4e5da5Sopenharmony_ci CASE(ImageRect), 268fd4e5da5Sopenharmony_ci CASE(SampledRect), 269fd4e5da5Sopenharmony_ci CASE(GenericPointer), 270fd4e5da5Sopenharmony_ci CASE(Int8), 271fd4e5da5Sopenharmony_ci CASE(InputAttachment), 272fd4e5da5Sopenharmony_ci CASE(SparseResidency), 273fd4e5da5Sopenharmony_ci CASE(MinLod), 274fd4e5da5Sopenharmony_ci CASE(Sampled1D), 275fd4e5da5Sopenharmony_ci CASE(Image1D), 276fd4e5da5Sopenharmony_ci CASE(SampledCubeArray), 277fd4e5da5Sopenharmony_ci CASE(SampledBuffer), 278fd4e5da5Sopenharmony_ci CASE(ImageBuffer), 279fd4e5da5Sopenharmony_ci CASE(ImageMSArray), 280fd4e5da5Sopenharmony_ci CASE(StorageImageExtendedFormats), 281fd4e5da5Sopenharmony_ci CASE(ImageQuery), 282fd4e5da5Sopenharmony_ci CASE(DerivativeControl), 283fd4e5da5Sopenharmony_ci CASE(InterpolationFunction), 284fd4e5da5Sopenharmony_ci CASE(TransformFeedback), 285fd4e5da5Sopenharmony_ci })); 286fd4e5da5Sopenharmony_ci#undef CASE 287fd4e5da5Sopenharmony_ci// clang-format on 288fd4e5da5Sopenharmony_ci 289fd4e5da5Sopenharmony_ciusing TextToBinaryCapability = spvtest::TextToBinaryTest; 290fd4e5da5Sopenharmony_ci 291fd4e5da5Sopenharmony_ciTEST_F(TextToBinaryCapability, BadMissingCapability) { 292fd4e5da5Sopenharmony_ci EXPECT_THAT(CompileFailure("OpCapability"), 293fd4e5da5Sopenharmony_ci Eq("Expected operand for OpCapability instruction, but found the " 294fd4e5da5Sopenharmony_ci "end of the stream.")); 295fd4e5da5Sopenharmony_ci} 296fd4e5da5Sopenharmony_ci 297fd4e5da5Sopenharmony_ciTEST_F(TextToBinaryCapability, BadInvalidCapability) { 298fd4e5da5Sopenharmony_ci EXPECT_THAT(CompileFailure("OpCapability 123"), 299fd4e5da5Sopenharmony_ci Eq("Invalid capability '123'.")); 300fd4e5da5Sopenharmony_ci} 301fd4e5da5Sopenharmony_ci 302fd4e5da5Sopenharmony_ci// TODO(dneto): OpExecutionMode 303fd4e5da5Sopenharmony_ci 304fd4e5da5Sopenharmony_ci} // namespace 305fd4e5da5Sopenharmony_ci} // namespace spvtools 306