Преглед изворни кода

[spirv] GetDimension for ACSBuffer. (#658)

GetDimensions for AppendStructuredBuffer
GetDimensions for ConsumeStructuredBuffer
Ehsan пре 8 година
родитељ
комит
a0684306a6

+ 11 - 0
docs/SPIR-V.rst

@@ -1156,6 +1156,12 @@ be used as the index for storing the new element. E.g., for ``buf.Append(vec)``:
       %val = OpLoad %v4float %vec
              OpStore %ptr %val
 
+``.GetDimensions()``
+~~~~~~~~~~~~~~~~~~~~
+Since AppendStructuredBuffers are represented as a struct with one member that is a
+runtime array, ``OpArrayLength`` is invoked on the runtime array in order to find the
+number of elements. The stride is also calculated based on GLSL ``std430`` as explained above.
+
 ``ConsumeStructuredBuffer``
 ---------------------------
 
@@ -1176,6 +1182,11 @@ will be used as the index for reading the new element. E.g., for
       %val = OpLoad %v4float %vec
              OpStore %ptr %val
 
+``.GetDimensions()``
+~~~~~~~~~~~~~~~~~~~~
+Since ConsumeStructuredBuffers are represented as a struct with one member that is a
+runtime array, ``OpArrayLength`` is invoked on the runtime array in order to find the
+number of elements. The stride is also calculated based on GLSL ``std430`` as explained above.
 
 ``Buffer``
 --------------------------

+ 7 - 2
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -1439,7 +1439,10 @@ uint32_t SPIRVEmitter::processByteAddressBufferStructuredBufferGetDimensions(
   const auto type = object->getType();
   const bool isByteAddressBuffer = TypeTranslator::isByteAddressBuffer(type) ||
                                    TypeTranslator::isRWByteAddressBuffer(type);
-  const bool isStructuredBuffer = TypeTranslator::isStructuredBuffer(type);
+  const bool isStructuredBuffer =
+      TypeTranslator::isStructuredBuffer(type) ||
+      TypeTranslator::isAppendStructuredBuffer(type) ||
+      TypeTranslator::isConsumeStructuredBuffer(type);
   assert(isByteAddressBuffer || isStructuredBuffer);
 
   // (RW)ByteAddressBuffers/(RW)StructuredBuffers are represented as a structure
@@ -2068,7 +2071,9 @@ uint32_t SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
       return processBufferTextureGetDimensions(expr);
     } else if (TypeTranslator::isByteAddressBuffer(objectType) ||
                TypeTranslator::isRWByteAddressBuffer(objectType) ||
-               TypeTranslator::isStructuredBuffer(objectType)) {
+               TypeTranslator::isStructuredBuffer(objectType) ||
+               TypeTranslator::isAppendStructuredBuffer(objectType) ||
+               TypeTranslator::isConsumeStructuredBuffer(objectType)) {
       return processByteAddressBufferStructuredBufferGetDimensions(expr);
     } else {
       emitError("GetDimensions not implmented for the given type yet.");

+ 16 - 0
tools/clang/lib/SPIRV/TypeTranslator.cpp

@@ -310,6 +310,22 @@ bool TypeTranslator::isRWByteAddressBuffer(QualType type) {
   return false;
 }
 
+bool TypeTranslator::isAppendStructuredBuffer(QualType type) {
+  const auto *recordType = type->getAs<RecordType>();
+  if (!recordType)
+    return false;
+  const auto name = recordType->getDecl()->getName();
+  return name == "AppendStructuredBuffer";
+}
+
+bool TypeTranslator::isConsumeStructuredBuffer(QualType type) {
+  const auto *recordType = type->getAs<RecordType>();
+  if (!recordType)
+    return false;
+  const auto name = recordType->getDecl()->getName();
+  return name == "ConsumeStructuredBuffer";
+}
+
 bool TypeTranslator::isStructuredBuffer(QualType type) {
   const auto *recordType = type->getAs<RecordType>();
   if (!recordType)

+ 6 - 0
tools/clang/lib/SPIRV/TypeTranslator.h

@@ -62,6 +62,12 @@ public:
   /// \brief Returns true if the given type is a (RW)StructuredBuffer type.
   static bool isStructuredBuffer(QualType type);
 
+  /// \brief Returns true if the given type is an AppendStructuredBuffer type.
+  static bool isAppendStructuredBuffer(QualType type);
+
+  /// \brief Returns true if the given type is a ConsumeStructuredBuffer type.
+  static bool isConsumeStructuredBuffer(QualType type);
+
   /// \brief Returns true if the given type is the HLSL ByteAddressBufferType.
   static bool isByteAddressBuffer(QualType type);
 

+ 19 - 0
tools/clang/test/CodeGenSPIRV/method.append-structured-buffer.get-dimensions.hlsl

@@ -0,0 +1,19 @@
+// Run: %dxc -T vs_6_0 -E main
+
+struct S {
+    float a;
+    float3 b;
+    float2x3 c;
+};
+
+AppendStructuredBuffer<S> buffer;
+
+void main() {
+  uint numStructs, stride;
+  
+// CHECK:      [[buf:%\d+]] = OpLoad %type_AppendStructuredBuffer_S %buffer
+// CHECK-NEXT: [[len:%\d+]] = OpArrayLength %uint [[buf]] 0
+// CHECK-NEXT: OpStore %numStructs [[len]]
+// CHECK-NEXT: OpStore %stride %uint_64
+  buffer.GetDimensions(numStructs, stride);
+}

+ 19 - 0
tools/clang/test/CodeGenSPIRV/method.consume-structured-buffer.get-dimensions.hlsl

@@ -0,0 +1,19 @@
+// Run: %dxc -T vs_6_0 -E main
+
+struct S {
+    float a;
+    float3 b;
+    float2x3 c;
+};
+
+ConsumeStructuredBuffer<S> buffer;
+
+void main() {
+  uint numStructs, stride;
+  
+// CHECK:      [[buf:%\d+]] = OpLoad %type_ConsumeStructuredBuffer_S %buffer
+// CHECK-NEXT: [[len:%\d+]] = OpArrayLength %uint [[buf]] 0
+// CHECK-NEXT: OpStore %numStructs [[len]]
+// CHECK-NEXT: OpStore %stride %uint_64
+  buffer.GetDimensions(numStructs, stride);
+}

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

@@ -402,9 +402,15 @@ TEST_F(FileTest, StructuredBufferGetDimensions) {
 TEST_F(FileTest, AppendStructuredBufferAppend) {
   runFileTest("method.append-structured-buffer.append.hlsl");
 }
+TEST_F(FileTest, AppendStructuredBufferGetDimensions) {
+  runFileTest("method.append-structured-buffer.get-dimensions.hlsl");
+}
 TEST_F(FileTest, ConsumeStructuredBufferConsume) {
   runFileTest("method.consume-structured-buffer.consume.hlsl");
 }
+TEST_F(FileTest, ConsumeStructuredBufferGetDimensions) {
+  runFileTest("method.consume-structured-buffer.get-dimensions.hlsl");
+}
 
 // For ByteAddressBuffer methods
 TEST_F(FileTest, ByteAddressBufferLoad) {