Bladeren bron

Correct the validation of vk::image_format. Fixes #5189 (#5190)

* Correct the validation of vk::image_format. Fixes #5189

* - Fix a bug where the image format doesn't propagate from OpTypeArray to OpTypeImage
- Add a unit test that tests the vk::image_format on arrays
Panagiotis Christopoulos Charitos 2 jaren geleden
bovenliggende
commit
3cf68d5def

+ 29 - 1
tools/clang/include/clang/Basic/Attr.td

@@ -977,6 +977,23 @@ def RWTexture
                   S->getType()->getAs<RecordType>()->getDecl()->getName() ==
                       "RWTexture3D")}]>;
 
+// Global variable of array of "RWTexture" type
+def ArrayOfRWTexture
+    : SubsetSubject<
+          Var, [{S->hasGlobalStorage() && S->getType()->getAsArrayTypeUnsafe() &&
+                 S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>() &&
+                 S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl() &&
+                  (S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
+                      "RWTexture1D" ||
+                  S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
+                      "RWTexture1DArray" ||
+                  S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
+                      "RWTexture2D" ||
+                  S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
+                      "RWTexture2DArray" ||
+                  S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
+                      "RWTexture3D")}]>;
+
 // Global variable with "[RW]Buffer" type
 def Buffer
     : SubsetSubject<
@@ -987,6 +1004,17 @@ def Buffer
                   S->getType()->getAs<RecordType>()->getDecl()->getName() ==
                       "RWBuffer")}]>;
 
+// Global variable or array of "[RW]Buffer" type
+def ArrayOfBuffer
+    : SubsetSubject<
+          Var, [{S->hasGlobalStorage() && S->getType()->getAsArrayTypeUnsafe() &&
+                 S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>() &&
+                 S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl() &&
+                 (S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
+                      "Buffer" ||
+                  S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
+                      "RWBuffer")}]>;
+
 // Global variable with "Texture" or "SamplerState" type
 def TextureOrSampler
     : SubsetSubject<
@@ -1115,7 +1143,7 @@ def VKCombinedImageSampler : InheritableAttr {
 
 def VKImageFormat : InheritableAttr {
   let Spellings = [CXX11<"vk", "image_format">];
-  let Subjects = SubjectList<[RWTexture, Buffer],
+  let Subjects = SubjectList<[RWTexture, ArrayOfRWTexture, Buffer, ArrayOfBuffer],
                              ErrorDiag, "ExpectedRWTextureOrBuffer">;
   let Args = [EnumArgument<"ImageFormat", "ImageFormatType",
                            ["unknown", "rgba32f", "rgba16f", "r32f", "rgba8", "rgba8snorm",

+ 10 - 0
tools/clang/lib/SPIRV/LowerTypeVisitor.cpp

@@ -199,6 +199,16 @@ bool LowerTypeVisitor::visitInstruction(SpirvInstruction *instr) {
         if (const auto *imageType = dyn_cast<ImageType>(resultType)) {
           resultType = spvContext.getImageType(imageType, vkImgFeatures.format);
           instr->setResultType(resultType);
+        } else if (const auto *arrayType = dyn_cast<ArrayType>(resultType)) {
+          if (const auto *imageType =
+                  dyn_cast<ImageType>(arrayType->getElementType())) {
+            auto newImgType =
+                spvContext.getImageType(imageType, vkImgFeatures.format);
+            resultType = spvContext.getArrayType(newImgType,
+                                                 arrayType->getElementCount(),
+                                                 arrayType->getStride());
+            instr->setResultType(resultType);
+          }
         }
       }
     }

+ 17 - 0
tools/clang/test/CodeGenSPIRV/vk.attribute.image-format.arrays.hlsl

@@ -0,0 +1,17 @@
+// RUN: %dxc -T cs_6_0 -E main
+
+// CHECK: OpTypeImage %float Buffer 2 0 0 2 Rgba16f
+[[vk::image_format("rgba16f")]]
+RWBuffer<float4> RWBuf[2];
+
+// CHECK: OpTypeImage %float Buffer 2 0 0 1 Rgba16ui
+[[vk::image_format("rgba16ui")]]
+Buffer<float4> Buf[2];
+
+//CHECK: OpTypeImage %float 2D 2 0 0 2 Rgba16f
+[[vk::image_format("rgba16f")]]
+RWTexture2D<float4> Tex[2];
+
+[numthreads(1, 1, 1)]
+void main() {
+}

+ 4 - 0
tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp

@@ -1935,6 +1935,10 @@ TEST_F(FileTest, VulkanAttributeImageFormatO3) {
 TEST_F(FileTest, VulkanAttributeImageFormatSimple) {
   runFileTest("vk.attribute.image-format.simple.hlsl", Expect::Success);
 }
+TEST_F(FileTest, VulkanAttributeImageFormatArray) {
+  runFileTest("vk.attribute.image-format.arrays.hlsl", Expect::Success,
+              /*runValidation*/ false);
+}
 
 TEST_F(FileTest, VulkanCLOptionInvertYVS) {
   runFileTest("vk.cloption.invert-y.vs.hlsl");