瀏覽代碼

[spirv] Emit warnings for cbuffer/tbuffer member initializers (#794)

Also modified the testing infrastructure to support checking
warning messages.
Lei Zhang 7 年之前
父節點
當前提交
df7fcb5469

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

@@ -303,6 +303,18 @@ void SPIRVEmitter::HandleTranslationUnit(ASTContext &context) {
       }
     } else if (auto *bufferDecl = dyn_cast<HLSLBufferDecl>(decl)) {
       // This is a cbuffer/tbuffer decl.
+
+      // Check and emit warnings for member intializers which are not
+      // supported in Vulkan
+      for (const auto *member : bufferDecl->decls()) {
+        if (const auto *varMember = dyn_cast<VarDecl>(member))
+          if (const auto *init = varMember->getInit())
+            emitWarning("%select{tbuffer|cbuffer}0 member initializer "
+                        "ignored since no equivalent in Vulkan",
+                        init->getExprLoc())
+                << bufferDecl->isCBuffer() << init->getSourceRange();
+      }
+
       (void)declIdMapper.createCTBuffer(bufferDecl);
     }
   }

+ 13 - 0
tools/clang/test/CodeGenSPIRV/var.init.cbuffer.hlsl

@@ -0,0 +1,13 @@
+// Run: %dxc -T vs_6_0 -E main
+
+cbuffer MyCBuffer {
+    float a = 1.0;
+    float4 b = 2.0;
+};
+
+float main() : A {
+    return 1.0;
+}
+
+// CHECK: :4:15: warning: cbuffer member initializer ignored since no equivalent in Vulkan
+// CHECK: :5:16: warning: cbuffer member initializer ignored since no equivalent in Vulkan

+ 14 - 0
tools/clang/test/CodeGenSPIRV/var.init.tbuffer.hlsl

@@ -0,0 +1,14 @@
+// Run: %dxc -T vs_6_0 -E main
+
+tbuffer MyTBuffer {
+    float a = 1.0;
+    float4 b = 2.0;
+};
+
+float main() : A {
+    return 1.0;
+}
+
+// CHECK: :4:15: warning: tbuffer member initializer ignored since no equivalent in Vulkan
+// CHECK: :5:16: warning: tbuffer member initializer ignored since no equivalent in Vulkan
+

+ 16 - 10
tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp

@@ -99,6 +99,12 @@ TEST_F(FileTest, VarInitMatrix1xN) { runFileTest("var.init.matrix.1xn.hlsl"); }
 TEST_F(FileTest, VarInitMatrix1x1) { runFileTest("var.init.matrix.1x1.hlsl"); }
 TEST_F(FileTest, VarInitStruct) { runFileTest("var.init.struct.hlsl"); }
 TEST_F(FileTest, VarInitArray) { runFileTest("var.init.array.hlsl"); }
+TEST_F(FileTest, VarInitCbuffer) {
+  runFileTest("var.init.cbuffer.hlsl", FileTest::Expect::Warning);
+}
+TEST_F(FileTest, VarInitTbuffer) {
+  runFileTest("var.init.tbuffer.hlsl", FileTest::Expect::Warning);
+}
 TEST_F(FileTest, StaticVar) { runFileTest("var.static.hlsl"); }
 
 // For prefix/postfix increment/decrement
@@ -399,7 +405,7 @@ TEST_F(FileTest, SemanticArbitraryAlphaLocation) {
   runFileTest("semantic.arbitrary.location.alpha.hlsl");
 }
 TEST_F(FileTest, SemanticDuplication) {
-  runFileTest("semantic.duplication.hlsl", /*expectSuccess*/ false);
+  runFileTest("semantic.duplication.hlsl", FileTest::Expect::Failure);
 }
 TEST_F(FileTest, SemanticDispatchThreadId) {
   runFileTest("semantic.dispatch-thread-id.cs.hlsl");
@@ -761,7 +767,7 @@ TEST_F(FileTest, PrimitiveTriangleAdjGS) {
   runFileTest("primitive.triangleadj.gs.hlsl");
 }
 TEST_F(FileTest, PrimitiveErrorGS) {
-  runFileTest("primitive.error.gs.hlsl", /*expectSuccess*/ false);
+  runFileTest("primitive.error.gs.hlsl", FileTest::Expect::Failure);
 }
 
 // SPIR-V specific
@@ -796,11 +802,11 @@ TEST_F(FileTest, SpirvInterpolation) {
   runFileTest("spirv.interpolation.hlsl");
 }
 TEST_F(FileTest, SpirvInterpolationError) {
-  runFileTest("spirv.interpolation.error.hlsl", /*expectSuccess*/ false);
+  runFileTest("spirv.interpolation.error.hlsl", FileTest::Expect::Failure);
 }
 
 TEST_F(FileTest, VulkanAttributeErrors) {
-  runFileTest("vk.attribute.error.hlsl", /*expectSuccess*/ false);
+  runFileTest("vk.attribute.error.hlsl", FileTest::Expect::Failure);
 }
 
 // Vulkan specific
@@ -812,13 +818,13 @@ TEST_F(FileTest, VulkanLocationInputImplicitOutputExplicit) {
   runFileTest("vk.location.exp-out.hlsl");
 }
 TEST_F(FileTest, VulkanLocationTooLarge) {
-  runFileTest("vk.location.large.hlsl", /*expectSuccess*/ false);
+  runFileTest("vk.location.large.hlsl", FileTest::Expect::Failure);
 }
 TEST_F(FileTest, VulkanLocationReassigned) {
-  runFileTest("vk.location.reassign.hlsl", /*expectSuccess*/ false);
+  runFileTest("vk.location.reassign.hlsl", FileTest::Expect::Failure);
 }
 TEST_F(FileTest, VulkanLocationPartiallyAssigned) {
-  runFileTest("vk.location.mixed.hlsl", /*expectSuccess*/ false);
+  runFileTest("vk.location.mixed.hlsl", FileTest::Expect::Failure);
 }
 
 TEST_F(FileTest, VulkanExplicitBinding) {
@@ -839,13 +845,13 @@ TEST_F(FileTest, VulkanRegisterBindingShift) {
   runFileTest("vk.binding.cl.hlsl");
 }
 TEST_F(FileTest, VulkanExplicitBindingReassigned) {
-  runFileTest("vk.binding.explicit.error.hlsl", /*expectSuccess*/ false);
+  runFileTest("vk.binding.explicit.error.hlsl", FileTest::Expect::Failure);
 }
 TEST_F(FileTest, VulkanRegisterBindingReassigned) {
-  runFileTest("vk.binding.register.error.hlsl", /*expectSuccess*/ false);
+  runFileTest("vk.binding.register.error.hlsl", FileTest::Expect::Failure);
 }
 TEST_F(FileTest, VulkanRegisterBindingShiftReassigned) {
-  runFileTest("vk.binding.cl.error.hlsl", /*expectSuccess*/ false);
+  runFileTest("vk.binding.cl.error.hlsl", FileTest::Expect::Failure);
 }
 TEST_F(FileTest, VulkanStructuredBufferCounter) {
   // [[vk::counter_binding()]] for RWStructuredBuffer, AppendStructuredBuffer,

+ 18 - 5
tools/clang/unittests/SPIRV/FileTestFixture.cpp

@@ -60,8 +60,7 @@ bool FileTest::parseInputFile() {
   return true;
 }
 
-void FileTest::runFileTest(llvm::StringRef filename, bool expectSuccess,
-                           bool runSpirvValidation) {
+void FileTest::runFileTest(llvm::StringRef filename, Expect expect) {
   inputFilePath = utils::getAbsPathOfInputDataFile(filename);
 
   // Parse the input file.
@@ -76,7 +75,7 @@ void FileTest::runFileTest(llvm::StringRef filename, bool expectSuccess,
 
   effcee::Result result(effcee::Result::Status::Ok);
 
-  if (expectSuccess) {
+  if (expect == Expect::Success) {
     ASSERT_TRUE(compileOk);
 
     // Disassemble the generated SPIR-V binary.
@@ -90,6 +89,20 @@ void FileTest::runFileTest(llvm::StringRef filename, bool expectSuccess,
     // Run CHECK commands via effcee on disassembly.
     result = effcee::Match(generatedSpirvAsm, checkCommands, options);
 
+  } else if (expect == Expect::Warning) {
+    ASSERT_TRUE(compileOk);
+
+    // Still check that we can disassemble the generated SPIR-V binary.
+    ASSERT_TRUE(utils::disassembleSpirvBinary(
+        generatedBinary, &generatedSpirvAsm, true /* generateHeader */));
+
+    auto options = effcee::Options()
+                       .SetChecksName(filename.str())
+                       .SetInputName("<message>");
+
+    // Run CHECK commands via effcee on warning messages.
+    result = effcee::Match(errorMessages, checkCommands, options);
+
   } else {
     ASSERT_FALSE(compileOk);
 
@@ -109,8 +122,8 @@ void FileTest::runFileTest(llvm::StringRef filename, bool expectSuccess,
   // All checks must have passed.
   ASSERT_EQ(result.status(), effcee::Result::Status::Ok);
 
-  // Run SPIR-V validation if requested.
-  if (expectSuccess && runSpirvValidation) {
+  // Run SPIR-V validation for successful compilations
+  if (expect != Expect::Failure) {
     EXPECT_TRUE(utils::validateSpirvBinary(generatedBinary));
   }
 }

+ 8 - 8
tools/clang/unittests/SPIRV/FileTestFixture.h

@@ -18,15 +18,15 @@ namespace spirv {
 
 class FileTest : public ::testing::Test {
 public:
+  /// \brief Expected test result to be
+  enum class Expect {
+    Success, // Success (with or without warnings) - check disassembly
+    Warning, // Success (with warnings) - check warning message
+    Failure, // Failure (with errors) - check error message
+  };
+
   /// \brief Runs a File Test! (See class description for more info)
-  ///
-  /// If the compilation is expected to fail, expectedSuccess should be
-  /// set to false.
-  /// It is important that all generated SPIR-V code is valid. Users of
-  /// FileTest may choose not to run the SPIR-V validator (for cases where
-  /// a certain feature has not been added to the validator yet).
-  void runFileTest(llvm::StringRef path, bool expectSuccess = true,
-                   bool runSpirvValidation = true);
+  void runFileTest(llvm::StringRef path, Expect expect = Expect::Success);
 
 private:
   /// \brief Reads in the given input file.