Selaa lähdekoodia

[spirv] Validate generated SPIR-V and support -Vd to disable (#955)

Lei Zhang 7 vuotta sitten
vanhempi
commit
b3c7bb1a47

+ 1 - 0
tools/clang/include/clang/SPIRV/EmitSPIRVOptions.h

@@ -17,6 +17,7 @@ namespace clang {
 struct EmitSPIRVOptions {
   /// Disable legalization and optimization and emit raw SPIR-V
   bool codeGenHighLevel;
+  bool disableValidation;
   bool ignoreUnusedResources;
   llvm::StringRef stageIoOrder;
   llvm::SmallVector<uint32_t, 4> bShift;

+ 4 - 0
tools/clang/lib/SPIRV/DeclResultIdMapper.cpp

@@ -238,6 +238,10 @@ SpirvEvalInfo DeclResultIdMapper::getDeclResultId(const ValueDecl *decl,
   if (checkRegistered) {
     emitFatalError("found unregistered decl", decl->getLocation())
         << decl->getName();
+    emitNote("please file a bug report on "
+             "https://github.com/Microsoft/DirectXShaderCompiler/issues with "
+             "source code if possible",
+             {});
   }
 
   return 0;

+ 32 - 0
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -258,6 +258,17 @@ bool spirvToolsOptimize(std::vector<uint32_t> *module, std::string *messages) {
   return optimizer.Run(module->data(), module->size(), module);
 }
 
+bool spirvToolsValidate(std::vector<uint32_t> *module, std::string *messages) {
+  spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
+
+  tools.SetMessageConsumer(
+      [messages](spv_message_level_t /*level*/, const char * /*source*/,
+                 const spv_position_t & /*position*/,
+                 const char *message) { *messages += message; });
+
+  return tools.Validate(module->data(), module->size());
+}
+
 /// Translates atomic HLSL opcodes into the equivalent SPIR-V opcode.
 spv::Op translateAtomicHlslOpcodeToSpirvOpcode(hlsl::IntrinsicOp opcode) {
   using namespace hlsl;
@@ -458,6 +469,10 @@ void SPIRVEmitter::HandleTranslationUnit(ASTContext &context) {
       std::string messages;
       if (!spirvToolsLegalize(&m, &messages)) {
         emitFatalError("failed to legalize SPIR-V: %0", {}) << messages;
+        emitNote("please file a bug report on "
+                 "https://github.com/Microsoft/DirectXShaderCompiler/issues "
+                 "with source code if possible",
+                 {});
         return;
       }
     }
@@ -467,6 +482,23 @@ void SPIRVEmitter::HandleTranslationUnit(ASTContext &context) {
       std::string messages;
       if (!spirvToolsOptimize(&m, &messages)) {
         emitFatalError("failed to optimize SPIR-V: %0", {}) << messages;
+        emitNote("please file a bug report on "
+                 "https://github.com/Microsoft/DirectXShaderCompiler/issues "
+                 "with source code if possible",
+                 {});
+        return;
+      }
+    }
+
+    // Validate the generated SPIR-V code
+    if (!spirvOptions.disableValidation) {
+      std::string messages;
+      if (!spirvToolsValidate(&m, &messages)) {
+        emitFatalError("generated SPIR-V is invalid: %0", {}) << messages;
+        emitNote("please file a bug report on "
+                 "https://github.com/Microsoft/DirectXShaderCompiler/issues "
+                 "with source code if possible",
+                 {});
         return;
       }
     }

+ 3 - 0
tools/clang/tools/dxcompiler/dxcompilerobj.cpp

@@ -464,13 +464,16 @@ public:
 #ifdef ENABLE_SPIRV_CODEGEN
       else if (opts.GenSPIRV) {
           clang::EmitSPIRVOptions spirvOpts;
+
           spirvOpts.codeGenHighLevel = opts.CodeGenHighLevel;
+          spirvOpts.disableValidation = opts.DisableValidation;
           spirvOpts.ignoreUnusedResources = opts.VkIgnoreUnusedResources;
           spirvOpts.stageIoOrder = opts.VkStageIoOrder;
           spirvOpts.bShift = opts.VkBShift;
           spirvOpts.tShift = opts.VkTShift;
           spirvOpts.sShift = opts.VkSShift;
           spirvOpts.uShift = opts.VkUShift;
+
           clang::EmitSPIRVAction action(spirvOpts);
           FrontendInputFile file(utf8SourceName.m_psz, IK_HLSL);
           action.BeginSourceFile(compiler, file);