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