• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2019 Google LLC.
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 // Validation tests for non-semantic instructions
16 
17 #include <string>
18 #include <vector>
19 
20 #include "gmock/gmock.h"
21 #include "test/unit_spirv.h"
22 #include "test/val/val_code_generator.h"
23 #include "test/val/val_fixtures.h"
24 
25 namespace spvtools {
26 namespace val {
27 namespace {
28 
29 struct TestResult {
TestResultspvtools::val::__anon98967dd60111::TestResult30   TestResult(spv_result_t in_validation_result = SPV_SUCCESS,
31              const char* in_error_str = nullptr,
32              const char* in_error_str2 = nullptr)
33       : validation_result(in_validation_result),
34         error_str(in_error_str),
35         error_str2(in_error_str2) {}
36   spv_result_t validation_result;
37   const char* error_str;
38   const char* error_str2;
39 };
40 
41 using ::testing::Combine;
42 using ::testing::HasSubstr;
43 using ::testing::Values;
44 using ::testing::ValuesIn;
45 
46 using ValidateNonSemanticGenerated = spvtest::ValidateBase<
47     std::tuple<bool, bool, const char*, const char*, TestResult>>;
48 using ValidateNonSemanticString = spvtest::ValidateBase<bool>;
49 
GetNonSemanticCodeGenerator(const bool declare_ext,const bool declare_extinst,const char * const global_extinsts,const char * const function_extinsts)50 CodeGenerator GetNonSemanticCodeGenerator(const bool declare_ext,
51                                           const bool declare_extinst,
52                                           const char* const global_extinsts,
53                                           const char* const function_extinsts) {
54   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
55 
56   if (declare_ext) {
57     generator.extensions_ += "OpExtension \"SPV_KHR_non_semantic_info\"\n";
58   }
59   if (declare_extinst) {
60     generator.extensions_ +=
61         "%extinst = OpExtInstImport \"NonSemantic.Testing.Set\"\n";
62   }
63 
64   generator.after_types_ = global_extinsts;
65 
66   generator.before_types_ = "%decorate_group = OpDecorationGroup";
67 
68   EntryPoint entry_point;
69   entry_point.name = "main";
70   entry_point.execution_model = "Vertex";
71 
72   entry_point.body = R"(
73 )";
74   entry_point.body += function_extinsts;
75   generator.entry_points_.push_back(std::move(entry_point));
76 
77   return generator;
78 }
79 
TEST_P(ValidateNonSemanticGenerated,InTest)80 TEST_P(ValidateNonSemanticGenerated, InTest) {
81   const bool declare_ext = std::get<0>(GetParam());
82   const bool declare_extinst = std::get<1>(GetParam());
83   const char* const global_extinsts = std::get<2>(GetParam());
84   const char* const function_extinsts = std::get<3>(GetParam());
85   const TestResult& test_result = std::get<4>(GetParam());
86 
87   CodeGenerator generator = GetNonSemanticCodeGenerator(
88       declare_ext, declare_extinst, global_extinsts, function_extinsts);
89 
90   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
91   ASSERT_EQ(test_result.validation_result,
92             ValidateInstructions(SPV_ENV_VULKAN_1_0));
93   if (test_result.error_str) {
94     EXPECT_THAT(getDiagnosticString(),
95                 testing::ContainsRegex(test_result.error_str));
96   }
97   if (test_result.error_str2) {
98     EXPECT_THAT(getDiagnosticString(),
99                 testing::ContainsRegex(test_result.error_str2));
100   }
101 }
102 
103 INSTANTIATE_TEST_SUITE_P(OnlyOpExtension, ValidateNonSemanticGenerated,
104                          Combine(Values(true), Values(false), Values(""),
105                                  Values(""), Values(TestResult())));
106 
107 INSTANTIATE_TEST_SUITE_P(
108     MissingOpExtension, ValidateNonSemanticGenerated,
109     Combine(Values(false), Values(true), Values(""), Values(""),
110             Values(TestResult(
111                 SPV_ERROR_INVALID_DATA,
112                 "NonSemantic extended instruction sets cannot be declared "
113                 "without SPV_KHR_non_semantic_info."))));
114 
115 INSTANTIATE_TEST_SUITE_P(NoExtInst, ValidateNonSemanticGenerated,
116                          Combine(Values(true), Values(true), Values(""),
117                                  Values(""), Values(TestResult())));
118 
119 INSTANTIATE_TEST_SUITE_P(
120     SimpleGlobalExtInst, ValidateNonSemanticGenerated,
121     Combine(Values(true), Values(true),
122             Values("%result = OpExtInst %void %extinst 123 %i32"), Values(""),
123             Values(TestResult())));
124 
125 INSTANTIATE_TEST_SUITE_P(
126     ComplexGlobalExtInst, ValidateNonSemanticGenerated,
127     Combine(Values(true), Values(true),
128             Values("%result = OpExtInst %void %extinst  123 %i32 %u32_2 "
129                    "%f32vec4_1234 %u32_0"),
130             Values(""), Values(TestResult())));
131 
132 INSTANTIATE_TEST_SUITE_P(
133     SimpleFunctionLevelExtInst, ValidateNonSemanticGenerated,
134     Combine(Values(true), Values(true), Values(""),
135             Values("%result = OpExtInst %void %extinst 123 %i32"),
136             Values(TestResult())));
137 
138 INSTANTIATE_TEST_SUITE_P(
139     FunctionTypeReference, ValidateNonSemanticGenerated,
140     Combine(Values(true), Values(true),
141             Values("%result = OpExtInst %void %extinst 123 %func"), Values(""),
142             Values(TestResult())));
143 
144 INSTANTIATE_TEST_SUITE_P(
145     EntryPointReference, ValidateNonSemanticGenerated,
146     Combine(Values(true), Values(true), Values(""),
147             Values("%result = OpExtInst %void %extinst 123 %main"),
148             Values(TestResult())));
149 
150 INSTANTIATE_TEST_SUITE_P(
151     DecorationGroupReference, ValidateNonSemanticGenerated,
152     Combine(Values(true), Values(true), Values(""),
153             Values("%result = OpExtInst %void %extinst 123 %decorate_group"),
154             Values(TestResult())));
155 
156 INSTANTIATE_TEST_SUITE_P(
157     UnknownIDReference, ValidateNonSemanticGenerated,
158     Combine(Values(true), Values(true),
159             Values("%result = OpExtInst %void %extinst 123 %undefined_id"),
160             Values(""),
161             Values(TestResult(SPV_ERROR_INVALID_ID,
162                               "ID .* has not been defined"))));
163 
164 INSTANTIATE_TEST_SUITE_P(
165     NonSemanticUseInSemantic, ValidateNonSemanticGenerated,
166     Combine(Values(true), Values(true),
167             Values("%result = OpExtInst %f32 %extinst 123 %i32\n"
168                    "%invalid = OpConstantComposite %f32vec2 %f32_0 %result"),
169             Values(""),
170             Values(TestResult(SPV_ERROR_INVALID_ID,
171                               "in semantic instruction cannot be a "
172                               "non-semantic instruction"))));
173 
TEST_F(ValidateNonSemanticString,InvalidSectionOpExtInst)174 TEST_F(ValidateNonSemanticString, InvalidSectionOpExtInst) {
175   const std::string spirv = R"(
176 OpCapability Shader
177 OpExtension "SPV_KHR_non_semantic_info"
178 %extinst = OpExtInstImport "NonSemantic.Testing.Set"
179 %test = OpExtInst %void %extinst 4 %void
180 OpMemoryModel Logical GLSL450
181 OpEntryPoint Vertex %main "main"
182 )";
183 
184   CompileSuccessfully(spirv);
185   EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
186 
187   // there's no specific error for using an OpExtInst too early, it requires a
188   // type so by definition any use of a type in it will be an undefined ID
189   EXPECT_THAT(getDiagnosticString(),
190               HasSubstr("ID 2[%2] has not been defined"));
191 }
192 
193 }  // namespace
194 }  // namespace val
195 }  // namespace spvtools
196