Browse Source

[spirv] Add cl options into the emitted SPIRV. (#1515)

Ehsan 7 years ago
parent
commit
339bf4fffc

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

@@ -55,6 +55,8 @@ struct EmitSPIRVOptions {
   spirv::LayoutRule tBufferLayoutRule;
   spirv::LayoutRule tBufferLayoutRule;
   spirv::LayoutRule sBufferLayoutRule;
   spirv::LayoutRule sBufferLayoutRule;
   llvm::SmallVector<llvm::StringRef, 4> optConfig;
   llvm::SmallVector<llvm::StringRef, 4> optConfig;
+  // String representation of all command line options.
+  std::string clOptions;
 
 
   // Initializes dependent fields appropriately
   // Initializes dependent fields appropriately
   void Initialize();
   void Initialize();

+ 5 - 4
tools/clang/include/clang/SPIRV/ModuleBuilder.h

@@ -36,7 +36,8 @@ namespace spirv {
 class ModuleBuilder {
 class ModuleBuilder {
 public:
 public:
   /// \brief Constructs a ModuleBuilder with the given SPIR-V context.
   /// \brief Constructs a ModuleBuilder with the given SPIR-V context.
-  ModuleBuilder(SPIRVContext *, FeatureManager *features, bool enableReflect);
+  ModuleBuilder(SPIRVContext *, FeatureManager *features,
+                const EmitSPIRVOptions &opts);
 
 
   /// \brief Returns the associated SPIRVContext.
   /// \brief Returns the associated SPIRVContext.
   inline SPIRVContext *getSPIRVContext();
   inline SPIRVContext *getSPIRVContext();
@@ -508,9 +509,9 @@ private:
       uint32_t sample, uint32_t minLod,
       uint32_t sample, uint32_t minLod,
       llvm::SmallVectorImpl<uint32_t> *orderedParams);
       llvm::SmallVectorImpl<uint32_t> *orderedParams);
 
 
-  SPIRVContext &theContext;       ///< The SPIR-V context.
-  FeatureManager *featureManager; ///< SPIR-V version/extension manager.
-  const bool allowReflect;        ///< Whether allow reflect instructions.
+  SPIRVContext &theContext;             ///< The SPIR-V context.
+  FeatureManager *featureManager;       ///< SPIR-V version/extension manager.
+  const EmitSPIRVOptions &spirvOptions; ///< Command line options.
 
 
   SPIRVModule theModule;                 ///< The module under building.
   SPIRVModule theModule;                 ///< The module under building.
   std::unique_ptr<Function> theFunction; ///< The function under building.
   std::unique_ptr<Function> theFunction; ///< The function under building.

+ 6 - 0
tools/clang/include/clang/SPIRV/Structure.h

@@ -297,6 +297,9 @@ public:
   /// \brief Sets the id bound to the given bound.
   /// \brief Sets the id bound to the given bound.
   inline void setBound(uint32_t newBound);
   inline void setBound(uint32_t newBound);
 
 
+  /// \brief Sets the string representation of the command line options.
+  inline void setClOptions(llvm::StringRef opts);
+
   inline void addCapability(spv::Capability);
   inline void addCapability(spv::Capability);
   inline void addExtension(llvm::StringRef extension);
   inline void addExtension(llvm::StringRef extension);
   inline void addExtInstSet(uint32_t setId, llvm::StringRef extInstSet);
   inline void addExtInstSet(uint32_t setId, llvm::StringRef extInstSet);
@@ -359,6 +362,8 @@ private:
 
 
   std::vector<Instruction> variables;
   std::vector<Instruction> variables;
   std::vector<std::unique_ptr<Function>> functions;
   std::vector<std::unique_ptr<Function>> functions;
+
+  std::string clOptions; ///< String representation of command line options.
 };
 };
 
 
 // === Instruction inline implementations ===
 // === Instruction inline implementations ===
@@ -462,6 +467,7 @@ void SPIRVModule::useVulkan1p1() {
   header.version = 0x00010300u;
   header.version = 0x00010300u;
 }
 }
 void SPIRVModule::setBound(uint32_t newBound) { header.bound = newBound; }
 void SPIRVModule::setBound(uint32_t newBound) { header.bound = newBound; }
+void SPIRVModule::setClOptions(llvm::StringRef opts) { clOptions = opts; }
 
 
 void SPIRVModule::addCapability(spv::Capability cap) {
 void SPIRVModule::addCapability(spv::Capability cap) {
   capabilities.insert(cap);
   capabilities.insert(cap);

+ 12 - 8
tools/clang/lib/SPIRV/ModuleBuilder.cpp

@@ -18,17 +18,21 @@ namespace clang {
 namespace spirv {
 namespace spirv {
 
 
 ModuleBuilder::ModuleBuilder(SPIRVContext *C, FeatureManager *features,
 ModuleBuilder::ModuleBuilder(SPIRVContext *C, FeatureManager *features,
-                             bool reflect)
-    : theContext(*C), featureManager(features), allowReflect(reflect),
-      theModule(), theFunction(nullptr), insertPoint(nullptr),
-      instBuilder(nullptr), glslExtSetId(0) {
+                             const EmitSPIRVOptions &opts)
+    : theContext(*C), featureManager(features), spirvOptions(opts), theModule(),
+      theFunction(nullptr), insertPoint(nullptr), instBuilder(nullptr),
+      glslExtSetId(0) {
   instBuilder.setConsumer([this](std::vector<uint32_t> &&words) {
   instBuilder.setConsumer([this](std::vector<uint32_t> &&words) {
     this->constructSite = std::move(words);
     this->constructSite = std::move(words);
   });
   });
 
 
-  // Set the SPIR-V version if needed.
-  if (featureManager && featureManager->getTargetEnv() == SPV_ENV_VULKAN_1_1)
+  // Set the SPIR-V version and the command line options that were used to
+  // generate this module, if needed.
+  if (featureManager && featureManager->getTargetEnv() == SPV_ENV_VULKAN_1_1) {
     theModule.useVulkan1p1();
     theModule.useVulkan1p1();
+    if (spirvOptions.enableDebugInfo)
+      theModule.setClOptions(opts.clOptions);
+  }
 }
 }
 
 
 std::vector<uint32_t> ModuleBuilder::takeModule() {
 std::vector<uint32_t> ModuleBuilder::takeModule() {
@@ -809,7 +813,7 @@ void ModuleBuilder::decorateInputAttachmentIndex(uint32_t targetId,
 
 
 void ModuleBuilder::decorateCounterBufferId(uint32_t mainBufferId,
 void ModuleBuilder::decorateCounterBufferId(uint32_t mainBufferId,
                                             uint32_t counterBufferId) {
                                             uint32_t counterBufferId) {
-  if (allowReflect) {
+  if (spirvOptions.enableReflect) {
     addExtension(Extension::GOOGLE_hlsl_functionality1, "SPIR-V reflection",
     addExtension(Extension::GOOGLE_hlsl_functionality1, "SPIR-V reflection",
                  {});
                  {});
     theModule.addDecoration(
     theModule.addDecoration(
@@ -821,7 +825,7 @@ void ModuleBuilder::decorateCounterBufferId(uint32_t mainBufferId,
 void ModuleBuilder::decorateHlslSemantic(uint32_t targetId,
 void ModuleBuilder::decorateHlslSemantic(uint32_t targetId,
                                          llvm::StringRef semantic,
                                          llvm::StringRef semantic,
                                          llvm::Optional<uint32_t> memberIdx) {
                                          llvm::Optional<uint32_t> memberIdx) {
-  if (allowReflect) {
+  if (spirvOptions.enableReflect) {
     addExtension(Extension::GOOGLE_hlsl_functionality1, "SPIR-V reflection",
     addExtension(Extension::GOOGLE_hlsl_functionality1, "SPIR-V reflection",
                  {});
                  {});
     theModule.addDecoration(
     theModule.addDecoration(

+ 1 - 1
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -596,7 +596,7 @@ SPIRVEmitter::SPIRVEmitter(CompilerInstance &ci, EmitSPIRVOptions &options)
       shaderModel(*hlsl::ShaderModel::GetByName(
       shaderModel(*hlsl::ShaderModel::GetByName(
           ci.getCodeGenOpts().HLSLProfile.c_str())),
           ci.getCodeGenOpts().HLSLProfile.c_str())),
       theContext(), featureManager(diags, options),
       theContext(), featureManager(diags, options),
-      theBuilder(&theContext, &featureManager, options.enableReflect),
+      theBuilder(&theContext, &featureManager, options),
       typeTranslator(astContext, theBuilder, diags, options),
       typeTranslator(astContext, theBuilder, diags, options),
       declIdMapper(shaderModel, astContext, theBuilder, typeTranslator,
       declIdMapper(shaderModel, astContext, theBuilder, typeTranslator,
                    featureManager, options),
                    featureManager, options),

+ 9 - 0
tools/clang/lib/SPIRV/Structure.cpp

@@ -363,6 +363,7 @@ void SPIRVModule::take(InstBuilder *builder) {
   }
   }
 
 
   if (isVulkan1p1) {
   if (isVulkan1p1) {
+    // Emit OpModuleProcessed to indicate the commit information.
     std::string commitHash =
     std::string commitHash =
         std::string("dxc-commit-hash: ") + clang::getGitCommitHash();
         std::string("dxc-commit-hash: ") + clang::getGitCommitHash();
     builder->opModuleProcessed(commitHash).x();
     builder->opModuleProcessed(commitHash).x();
@@ -370,6 +371,14 @@ void SPIRVModule::take(InstBuilder *builder) {
     std::string commitCount = std::string("dxc-commit-count: ") +
     std::string commitCount = std::string("dxc-commit-count: ") +
                               std::to_string(clang::getGitCommitCount());
                               std::to_string(clang::getGitCommitCount());
     builder->opModuleProcessed(commitCount).x();
     builder->opModuleProcessed(commitCount).x();
+
+    // Emit OpModuleProcessed to indicate the command line options that were
+    // used to generate this module.
+    if (!clOptions.empty()) {
+      // Using this format: "dxc-cl-option: XXXXXX"
+      std::string clOptionStr = "dxc-cl-option:" + clOptions;
+      builder->opModuleProcessed(clOptionStr).x();
+    }
   }
   }
 
 
   for (const auto &idDecorPair : decorations) {
   for (const auto &idDecorPair : decorations) {

+ 9 - 0
tools/clang/test/CodeGenSPIRV/spirv.debug.cl-option.hlsl

@@ -0,0 +1,9 @@
+// Run: %dxc -E main -T ps_6_1 -fspv-target-env=vulkan1.1 -Zi
+
+// This test ensures that command line options used to generate this module
+// are added to the SPIR-V using OpModuleProcessed.
+
+// CHECK: OpModuleProcessed "dxc-cl-option: -E main -T ps_6_1 
+// CHECK-SAME: -fspv-target-env=vulkan1.1 -Zi
+
+void main() {}

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

@@ -532,6 +532,11 @@ public:
           spirvOpts.enableDebugInfo = opts.DebugInfo;
           spirvOpts.enableDebugInfo = opts.DebugInfo;
           spirvOpts.optConfig = opts.SpvOconfig;
           spirvOpts.optConfig = opts.SpvOconfig;
 
 
+          // Store a string representation of command line options.
+          if (opts.DebugInfo)
+            for (auto opt : mainArgs.getArrayRef())
+              spirvOpts.clOptions += " " + std::string(opt);
+
           clang::EmitSPIRVAction action(spirvOpts);
           clang::EmitSPIRVAction action(spirvOpts);
           FrontendInputFile file(utf8SourceName.m_psz, IK_HLSL);
           FrontendInputFile file(utf8SourceName.m_psz, IK_HLSL);
           action.BeginSourceFile(compiler, file);
           action.BeginSourceFile(compiler, file);

+ 6 - 0
tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp

@@ -1269,6 +1269,12 @@ TEST_F(FileTest, SpirvOptOconfigInvalidFlag) {
 }
 }
 TEST_F(FileTest, SpirvOptOconfig) { runFileTest("spirv.opt.cl.oconfig.hlsl"); }
 TEST_F(FileTest, SpirvOptOconfig) { runFileTest("spirv.opt.cl.oconfig.hlsl"); }
 
 
+// Test that command line options are exposed using OpModuleProcessed.
+TEST_F(FileTest, SpirvDebugClOption) {
+  useVulkan1p1();
+  runFileTest("spirv.debug.cl-option.hlsl");
+}
+
 // For shader stage input/output interface
 // For shader stage input/output interface
 // For semantic SV_Position, SV_ClipDistance, SV_CullDistance
 // For semantic SV_Position, SV_ClipDistance, SV_CullDistance
 TEST_F(FileTest, SpirvStageIOInterfaceVS) {
 TEST_F(FileTest, SpirvStageIOInterfaceVS) {

+ 3 - 3
tools/clang/unittests/SPIRV/ModuleBuilderTest.cpp

@@ -21,7 +21,7 @@ using ::testing::ElementsAre;
 
 
 TEST(ModuleBuilder, TakeModuleDirectlyCreatesHeader) {
 TEST(ModuleBuilder, TakeModuleDirectlyCreatesHeader) {
   SPIRVContext context;
   SPIRVContext context;
-  ModuleBuilder builder(&context, nullptr, false);
+  ModuleBuilder builder(&context, nullptr, {0});
 
 
   EXPECT_THAT(builder.takeModule(),
   EXPECT_THAT(builder.takeModule(),
               ElementsAre(spv::MagicNumber, 0x00010000, 14u << 16, 1u, 0u));
               ElementsAre(spv::MagicNumber, 0x00010000, 14u << 16, 1u, 0u));
@@ -29,7 +29,7 @@ TEST(ModuleBuilder, TakeModuleDirectlyCreatesHeader) {
 
 
 TEST(ModuleBuilder, CreateFunction) {
 TEST(ModuleBuilder, CreateFunction) {
   SPIRVContext context;
   SPIRVContext context;
-  ModuleBuilder builder(&context, nullptr, false);
+  ModuleBuilder builder(&context, nullptr, {0});
 
 
   const auto rType = context.takeNextId();
   const auto rType = context.takeNextId();
   const auto fType = context.takeNextId();
   const auto fType = context.takeNextId();
@@ -47,7 +47,7 @@ TEST(ModuleBuilder, CreateFunction) {
 
 
 TEST(ModuleBuilder, CreateBasicBlock) {
 TEST(ModuleBuilder, CreateBasicBlock) {
   SPIRVContext context;
   SPIRVContext context;
-  ModuleBuilder builder(&context, nullptr, false);
+  ModuleBuilder builder(&context, nullptr, {0});
 
 
   const auto rType = context.takeNextId();
   const auto rType = context.takeNextId();
   const auto fType = context.takeNextId();
   const auto fType = context.takeNextId();

+ 1 - 1
tools/clang/unittests/SPIRV/WholeFileTestFixture.cpp

@@ -108,7 +108,7 @@ void WholeFileTest::runWholeFileTest(llvm::StringRef filename,
   // Run SPIR-V validation if requested.
   // Run SPIR-V validation if requested.
   if (runSpirvValidation) {
   if (runSpirvValidation) {
     EXPECT_TRUE(utils::validateSpirvBinary(
     EXPECT_TRUE(utils::validateSpirvBinary(
-        SPV_ENV_VULKAN_1_0, generatedBinary,
+        targetEnv, generatedBinary,
         /*relaxLogicalPointer=*/false, /*glLayout=*/false, /*dxLayout=*/false));
         /*relaxLogicalPointer=*/false, /*glLayout=*/false, /*dxLayout=*/false));
   }
   }
 }
 }