Browse Source

[spirv] Support embedded struct definition in cbuffer/tbuffer (#953)

Fixes https://github.com/Microsoft/DirectXShaderCompiler/issues/952
Lei Zhang 7 năm trước cách đây
mục cha
commit
578b0df014

+ 7 - 1
tools/clang/lib/SPIRV/DeclResultIdMapper.cpp

@@ -379,7 +379,8 @@ uint32_t DeclResultIdMapper::createVarOfExplicitLayoutStruct(
   uint32_t fieldIndex = 0;
   for (const auto *subDecl : decl->decls()) {
     // Ignore implicit generated struct declarations/constructors/destructors.
-    if (subDecl->isImplicit())
+    // Ignore embedded struct/union/class/enum decls.
+    if (subDecl->isImplicit() || isa<TagDecl>(subDecl))
       continue;
 
     // The field can only be FieldDecl (for normal structs) or VarDecl (for
@@ -433,6 +434,11 @@ uint32_t DeclResultIdMapper::createCTBuffer(const HLSLBufferDecl *decl) {
   // OpAccessChain.
   int index = 0;
   for (const auto *subDecl : decl->decls()) {
+    // Ignore implicit generated struct declarations/constructors/destructors.
+    // Ignore embedded struct/union/class/enum decls.
+    if (subDecl->isImplicit() || isa<TagDecl>(subDecl))
+      continue;
+
     const auto *varDecl = cast<VarDecl>(subDecl);
     astDecls[varDecl] = {SpirvEvalInfo(bufferVar)
                              .setStorageClass(spv::StorageClass::Uniform)

+ 5 - 5
tools/clang/lib/SPIRV/TypeTranslator.cpp

@@ -626,7 +626,8 @@ TypeTranslator::getLayoutDecorations(const DeclContext *decl, LayoutRule rule) {
 
   for (const auto *field : decl->decls()) {
     // Ignore implicit generated struct declarations/constructors/destructors.
-    if (field->isImplicit())
+    // Ignore embedded struct/union/class/enum decls.
+    if (field->isImplicit() || isa<TagDecl>(field))
       continue;
 
     // The field can only be FieldDecl (for normal structs) or VarDecl (for
@@ -639,11 +640,10 @@ TypeTranslator::getLayoutDecorations(const DeclContext *decl, LayoutRule rule) {
         getAlignmentAndSize(fieldType, rule, isRowMajor, &stride);
 
     // Each structure-type member must have an Offset Decoration.
-    const auto *offsetAttr = field->getAttr<VKOffsetAttr>();
-    if (offsetAttr)
-        offset = offsetAttr->getOffset();
+    if (const auto *offsetAttr = field->getAttr<VKOffsetAttr>())
+      offset = offsetAttr->getOffset();
     else
-        roundToPow2(&offset, memberAlignment);
+      roundToPow2(&offset, memberAlignment);
     decorations.push_back(Decoration::getOffset(*spirvContext, offset, index));
     offset += memberSize;
 

+ 23 - 0
tools/clang/test/CodeGenSPIRV/type.struct.hlsl

@@ -12,6 +12,29 @@
 // CHECK-NEXT: OpMemberName %T 1 "y"
 // CHECK-NEXT: OpMemberName %T 2 "z"
 
+// CHECK:      %X = OpTypeStruct %v4float %v3float
+// CHECK:      %_struct_[[num:\d+]] = OpTypeStruct %v2float
+// CHECK:      %type_MyCBuffer = OpTypeStruct %X %_struct_[[num]]
+cbuffer MyCBuffer {
+  struct X {
+    float4 a;
+    float3 b;
+  } x1;
+
+  struct {
+    float2 c;
+  } y1;
+};
+
+// CHECK:      %type_MyTBuffer = OpTypeStruct %X %_struct_[[num]]
+tbuffer MyTBuffer {
+  X x2;
+
+  struct {
+    float2 c;
+  } y2;
+};
+
 // CHECK:      %N = OpTypeStruct
 struct N {};