• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2015-2016 The Khronos Group Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <algorithm>
16 #include <string>
17 #include <vector>
18 
19 #include "source/latest_version_glsl_std_450_header.h"
20 #include "test/unit_spirv.h"
21 
22 namespace spvtools {
23 namespace {
24 
25 /// Context for an extended instruction.
26 ///
27 /// Information about a GLSL extended instruction (including its opname, return
28 /// type, etc.) and related instructions used to generate the return type and
29 /// constant as the operands. Used in generating extended instruction tests.
30 struct ExtInstContext {
31   const char* extInstOpName;
32   const char* extInstOperandVars;
33   /// The following fields are used to check the SPIR-V binary representation
34   /// of this instruction.
35   uint32_t extInstOpcode;  ///< Opcode value for this extended instruction.
36   uint32_t extInstLength;  ///< Wordcount of this extended instruction.
37   std::vector<uint32_t> extInstOperandIds;  ///< Ids for operands.
38 };
39 
40 using ExtInstGLSLstd450RoundTripTest = ::testing::TestWithParam<ExtInstContext>;
41 
TEST_P(ExtInstGLSLstd450RoundTripTest,ParameterizedExtInst)42 TEST_P(ExtInstGLSLstd450RoundTripTest, ParameterizedExtInst) {
43   spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_0);
44   const std::string spirv = R"(
45 OpCapability Shader
46 %1 = OpExtInstImport "GLSL.std.450"
47 OpMemoryModel Logical Simple
48 OpEntryPoint Vertex %2 "main"
49 %3 = OpTypeVoid
50 %4 = OpTypeFunction %3
51 %2 = OpFunction %3 None %5
52 %6 = OpLabel
53 %8 = OpExtInst %7 %1 )" + std::string(GetParam().extInstOpName) +
54                             " " + GetParam().extInstOperandVars + R"(
55 OpReturn
56 OpFunctionEnd
57 )";
58   const std::string spirv_header =
59       R"(; SPIR-V
60 ; Version: 1.0
61 ; Generator: Khronos SPIR-V Tools Assembler; 0
62 ; Bound: 9
63 ; Schema: 0)";
64   spv_binary binary = nullptr;
65   spv_diagnostic diagnostic;
66   spv_result_t error = spvTextToBinary(context, spirv.c_str(), spirv.size(),
67                                        &binary, &diagnostic);
68   if (error) {
69     spvDiagnosticPrint(diagnostic);
70     spvDiagnosticDestroy(diagnostic);
71     ASSERT_EQ(SPV_SUCCESS, error)
72         << "Source was: " << std::endl
73         << spirv << std::endl
74         << "Test case for : " << GetParam().extInstOpName << std::endl;
75   }
76 
77   // Check we do have the extended instruction's corresponding binary code in
78   // the generated SPIR-V binary.
79   std::vector<uint32_t> expected_contains(
80       {12 /*OpExtInst*/ | GetParam().extInstLength << 16, 7 /*return type*/,
81        8 /*result id*/, 1 /*glsl450 import*/, GetParam().extInstOpcode});
82   for (uint32_t operand : GetParam().extInstOperandIds) {
83     expected_contains.push_back(operand);
84   }
85   EXPECT_NE(binary->code + binary->wordCount,
86             std::search(binary->code, binary->code + binary->wordCount,
87                         expected_contains.begin(), expected_contains.end()))
88       << "Cannot find\n"
89       << spvtest::WordVector(expected_contains).str() << "in\n"
90       << spvtest::WordVector(*binary).str();
91 
92   // Check round trip gives the same text.
93   spv_text output_text = nullptr;
94   error = spvBinaryToText(context, binary->code, binary->wordCount,
95                           SPV_BINARY_TO_TEXT_OPTION_NONE, &output_text,
96                           &diagnostic);
97 
98   if (error) {
99     spvDiagnosticPrint(diagnostic);
100     spvDiagnosticDestroy(diagnostic);
101     ASSERT_EQ(SPV_SUCCESS, error);
102   }
103   EXPECT_EQ(spirv_header + spirv, output_text->str);
104   spvTextDestroy(output_text);
105   spvBinaryDestroy(binary);
106   spvContextDestroy(context);
107 }
108 
109 INSTANTIATE_TEST_CASE_P(
110     ExtInstParameters, ExtInstGLSLstd450RoundTripTest,
111     ::testing::ValuesIn(std::vector<ExtInstContext>({
112         // We are only testing the correctness of encoding and decoding here.
113         // Semantic correctness should be the responsibility of validator. So
114         // some of the instructions below have incorrect operand and/or return
115         // types, e.g, Modf, ModfStruct, etc.
116         {"Round", "%5", 1, 6, {5}},
117         {"RoundEven", "%5", 2, 6, {5}},
118         {"Trunc", "%5", 3, 6, {5}},
119         {"FAbs", "%5", 4, 6, {5}},
120         {"SAbs", "%5", 5, 6, {5}},
121         {"FSign", "%5", 6, 6, {5}},
122         {"SSign", "%5", 7, 6, {5}},
123         {"Floor", "%5", 8, 6, {5}},
124         {"Ceil", "%5", 9, 6, {5}},
125         {"Fract", "%5", 10, 6, {5}},
126         {"Radians", "%5", 11, 6, {5}},
127         {"Degrees", "%5", 12, 6, {5}},
128         {"Sin", "%5", 13, 6, {5}},
129         {"Cos", "%5", 14, 6, {5}},
130         {"Tan", "%5", 15, 6, {5}},
131         {"Asin", "%5", 16, 6, {5}},
132         {"Acos", "%5", 17, 6, {5}},
133         {"Atan", "%5", 18, 6, {5}},
134         {"Sinh", "%5", 19, 6, {5}},
135         {"Cosh", "%5", 20, 6, {5}},
136         {"Tanh", "%5", 21, 6, {5}},
137         {"Asinh", "%5", 22, 6, {5}},
138         {"Acosh", "%5", 23, 6, {5}},
139         {"Atanh", "%5", 24, 6, {5}},
140         {"Atan2", "%5 %5", 25, 7, {5, 5}},
141         {"Pow", "%5 %5", 26, 7, {5, 5}},
142         {"Exp", "%5", 27, 6, {5}},
143         {"Log", "%5", 28, 6, {5}},
144         {"Exp2", "%5", 29, 6, {5}},
145         {"Log2", "%5", 30, 6, {5}},
146         {"Sqrt", "%5", 31, 6, {5}},
147         {"InverseSqrt", "%5", 32, 6, {5}},
148         {"Determinant", "%5", 33, 6, {5}},
149         {"MatrixInverse", "%5", 34, 6, {5}},
150         {"Modf", "%5 %5", 35, 7, {5, 5}},
151         {"ModfStruct", "%5", 36, 6, {5}},
152         {"FMin", "%5 %5", 37, 7, {5, 5}},
153         {"UMin", "%5 %5", 38, 7, {5, 5}},
154         {"SMin", "%5 %5", 39, 7, {5, 5}},
155         {"FMax", "%5 %5", 40, 7, {5, 5}},
156         {"UMax", "%5 %5", 41, 7, {5, 5}},
157         {"SMax", "%5 %5", 42, 7, {5, 5}},
158         {"FClamp", "%5 %5 %5", 43, 8, {5, 5, 5}},
159         {"UClamp", "%5 %5 %5", 44, 8, {5, 5, 5}},
160         {"SClamp", "%5 %5 %5", 45, 8, {5, 5, 5}},
161         {"FMix", "%5 %5 %5", 46, 8, {5, 5, 5}},
162         {"IMix", "%5 %5 %5", 47, 8, {5, 5, 5}},  // Bug 15452. Reserved.
163         {"Step", "%5 %5", 48, 7, {5, 5}},
164         {"SmoothStep", "%5 %5 %5", 49, 8, {5, 5, 5}},
165         {"Fma", "%5 %5 %5", 50, 8, {5, 5, 5}},
166         {"Frexp", "%5 %5", 51, 7, {5, 5}},
167         {"FrexpStruct", "%5", 52, 6, {5}},
168         {"Ldexp", "%5 %5", 53, 7, {5, 5}},
169         {"PackSnorm4x8", "%5", 54, 6, {5}},
170         {"PackUnorm4x8", "%5", 55, 6, {5}},
171         {"PackSnorm2x16", "%5", 56, 6, {5}},
172         {"PackUnorm2x16", "%5", 57, 6, {5}},
173         {"PackHalf2x16", "%5", 58, 6, {5}},
174         {"PackDouble2x32", "%5", 59, 6, {5}},
175         {"UnpackSnorm2x16", "%5", 60, 6, {5}},
176         {"UnpackUnorm2x16", "%5", 61, 6, {5}},
177         {"UnpackHalf2x16", "%5", 62, 6, {5}},
178         {"UnpackSnorm4x8", "%5", 63, 6, {5}},
179         {"UnpackUnorm4x8", "%5", 64, 6, {5}},
180         {"UnpackDouble2x32", "%5", 65, 6, {5}},
181         {"Length", "%5", 66, 6, {5}},
182         {"Distance", "%5 %5", 67, 7, {5, 5}},
183         {"Cross", "%5 %5", 68, 7, {5, 5}},
184         {"Normalize", "%5", 69, 6, {5}},
185         // clang-format off
186         {"FaceForward", "%5 %5 %5", 70, 8, {5, 5, 5}},
187         // clang-format on
188         {"Reflect", "%5 %5", 71, 7, {5, 5}},
189         {"Refract", "%5 %5 %5", 72, 8, {5, 5, 5}},
190         {"FindILsb", "%5", 73, 6, {5}},
191         {"FindSMsb", "%5", 74, 6, {5}},
192         {"FindUMsb", "%5", 75, 6, {5}},
193         {"InterpolateAtCentroid", "%5", 76, 6, {5}},
194         // clang-format off
195         {"InterpolateAtSample", "%5 %5", 77, 7, {5, 5}},
196         {"InterpolateAtOffset", "%5 %5", 78, 7, {5, 5}},
197         // clang-format on
198         {"NMin", "%5 %5", 79, 7, {5, 5}},
199         {"NMax", "%5 %5", 80, 7, {5, 5}},
200         {"NClamp", "%5 %5 %5", 81, 8, {5, 5, 5}},
201     })), );
202 
203 }  // namespace
204 }  // namespace spvtools
205