• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/sksl/codegen/SkSLSPIRVValidator.h"
9 
10 #include "src/sksl/SkSLErrorReporter.h"
11 #include "src/sksl/SkSLPosition.h"
12 
13 #include "spirv-tools/libspirv.hpp"
14 
15 namespace SkSL {
16 
validate_spirv(ErrorReporter & reporter,std::string_view program,bool disassemble)17 static bool validate_spirv(ErrorReporter& reporter, std::string_view program, bool disassemble) {
18     SkASSERT(0 == program.size() % 4);
19     const uint32_t* programData = reinterpret_cast<const uint32_t*>(program.data());
20     size_t programSize = program.size() / 4;
21 
22 #ifdef SKSL_EXT
23     spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_4);
24 #else
25     spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
26 #endif
27     std::string errors;
28     auto msgFn = [&errors](spv_message_level_t, const char*, const spv_position_t&, const char* m) {
29         errors += "SPIR-V validation error: ";
30         errors += m;
31         errors += '\n';
32     };
33     tools.SetMessageConsumer(msgFn);
34 
35     bool result = tools.Validate(programData, programSize);
36     if (result) {
37         return true;
38     }
39     // If disassemble is set, we won't abort but instead append the errors. This allows
40     // us to keep going and show all the errors, which is used by skslc to make sure
41     // expected validation errors fail as expected..
42     if (disassemble) {
43         // Send the message, plus the entire disassembled SPIR-V (for easier context & debugging)
44         // as if were an SkSL compile error message.
45         std::string disassembly;
46         uint32_t options = spvtools::SpirvTools::kDefaultDisassembleOption;
47         options |= SPV_BINARY_TO_TEXT_OPTION_INDENT;
48         if (tools.Disassemble(programData, programSize, &disassembly, options)) {
49             errors.append(disassembly);
50         }
51         reporter.error(Position(), errors);
52     } else {
53         // Normal validation mode - abort() in a debug build with an error message.
54         SkDEBUGFAILF("%s", errors.c_str());
55     }
56     return false;
57 }
58 
ValidateSPIRV(ErrorReporter & reporter,std::string_view program)59 bool ValidateSPIRV(ErrorReporter& reporter, std::string_view program) {
60     return validate_spirv(reporter, program, false);
61 }
62 
ValidateSPIRVAndDissassemble(ErrorReporter & reporter,std::string_view program)63 bool ValidateSPIRVAndDissassemble(ErrorReporter& reporter, std::string_view program) {
64     return validate_spirv(reporter, program, true);
65 }
66 
67 }  // namespace SkSL
68