Update reflection offset consistently for structure members
authorbaldurk <baldurk@baldurk.org>
Tue, 29 Jan 2019 13:52:33 +0000 (13:52 +0000)
committerbaldurk <baldurk@baldurk.org>
Tue, 29 Jan 2019 17:00:53 +0000 (17:00 +0000)
* Previously the offset was only updated with EOpIndexDirectStruct, but we also
  need to update it for the other index types into arrays, and when expanding an
  aggregate reached after dereferencing.

Test/baseResults/hlsl.reflection.vert.out
Test/baseResults/reflection.vert.out
Test/reflection.vert
glslang/MachineIndependent/reflection.cpp

index ea8d869..3403bd3 100644 (file)
@@ -15,45 +15,45 @@ foo.n1.a: offset 0, type 1406, size 1, index 3, binding -1, stages 1
 foo.n2.b: offset 16, type 1406, size 1, index 3, binding -1, stages 1
 foo.n2.c: offset 20, type 1406, size 1, index 3, binding -1, stages 1
 foo.n2.d: offset 24, type 1406, size 1, index 3, binding -1, stages 1
-deepA.d2.d1[2].va: offset 376, type 8b50, size 2, index 1, binding -1, stages 1
+deepA.d2.d1[2].va: offset 440, type 8b50, size 2, index 1, binding -1, stages 1
 deepB.d2.d1.va: offset 984, type 8b50, size 2, index 1, binding -1, stages 1
 deepB.d2.d1[0].va: offset 984, type 8b50, size 2, index 1, binding -1, stages 1
-deepB.d2.d1[1].va: offset 984, type 8b50, size 2, index 1, binding -1, stages 1
-deepB.d2.d1[2].va: offset 984, type 8b50, size 2, index 1, binding -1, stages 1
-deepB.d2.d1[3].va: offset 984, type 8b50, size 2, index 1, binding -1, stages 1
+deepB.d2.d1[1].va: offset 1016, type 8b50, size 2, index 1, binding -1, stages 1
+deepB.d2.d1[2].va: offset 1048, type 8b50, size 2, index 1, binding -1, stages 1
+deepB.d2.d1[3].va: offset 1080, type 8b50, size 2, index 1, binding -1, stages 1
 deepC.iv4: offset 1568, type 8b52, size 1, index 1, binding -1, stages 1
-deepC.d2.i: offset 1568, type 1404, size 1, index 1, binding -1, stages 1
-deepC.d2.d1[0].va: offset 1568, type 8b50, size 3, index 1, binding -1, stages 1
-deepC.d2.d1[0].b: offset 1568, type 8b56, size 1, index 1, binding -1, stages 1
-deepC.d2.d1[1].va: offset 1568, type 8b50, size 3, index 1, binding -1, stages 1
-deepC.d2.d1[1].b: offset 1568, type 8b56, size 1, index 1, binding -1, stages 1
-deepC.d2.d1[2].va: offset 1568, type 8b50, size 3, index 1, binding -1, stages 1
-deepC.d2.d1[2].b: offset 1568, type 8b56, size 1, index 1, binding -1, stages 1
-deepC.d2.d1[3].va: offset 1568, type 8b50, size 3, index 1, binding -1, stages 1
-deepC.d2.d1[3].b: offset 1568, type 8b56, size 1, index 1, binding -1, stages 1
-deepC.v3: offset 1568, type 8b54, size 1, index 1, binding -1, stages 1
+deepC.d2.i: offset 1584, type 1404, size 1, index 1, binding -1, stages 1
+deepC.d2.d1[0].va: offset 1592, type 8b50, size 3, index 1, binding -1, stages 1
+deepC.d2.d1[0].b: offset 1616, type 8b56, size 1, index 1, binding -1, stages 1
+deepC.d2.d1[1].va: offset 1624, type 8b50, size 3, index 1, binding -1, stages 1
+deepC.d2.d1[1].b: offset 1648, type 8b56, size 1, index 1, binding -1, stages 1
+deepC.d2.d1[2].va: offset 1656, type 8b50, size 3, index 1, binding -1, stages 1
+deepC.d2.d1[2].b: offset 1680, type 8b56, size 1, index 1, binding -1, stages 1
+deepC.d2.d1[3].va: offset 1688, type 8b50, size 3, index 1, binding -1, stages 1
+deepC.d2.d1[3].b: offset 1712, type 8b56, size 1, index 1, binding -1, stages 1
+deepC.v3: offset 1728, type 8b54, size 1, index 1, binding -1, stages 1
 deepD[0].iv4: offset 2480, type 8b52, size 1, index 1, binding -1, stages 1
-deepD[0].d2.i: offset 2480, type 1404, size 1, index 1, binding -1, stages 1
-deepD[0].d2.d1[0].va: offset 2480, type 8b50, size 3, index 1, binding -1, stages 1
-deepD[0].d2.d1[0].b: offset 2480, type 8b56, size 1, index 1, binding -1, stages 1
-deepD[0].d2.d1[1].va: offset 2480, type 8b50, size 3, index 1, binding -1, stages 1
-deepD[0].d2.d1[1].b: offset 2480, type 8b56, size 1, index 1, binding -1, stages 1
-deepD[0].d2.d1[2].va: offset 2480, type 8b50, size 3, index 1, binding -1, stages 1
-deepD[0].d2.d1[2].b: offset 2480, type 8b56, size 1, index 1, binding -1, stages 1
-deepD[0].d2.d1[3].va: offset 2480, type 8b50, size 3, index 1, binding -1, stages 1
-deepD[0].d2.d1[3].b: offset 2480, type 8b56, size 1, index 1, binding -1, stages 1
-deepD[0].v3: offset 2480, type 8b54, size 1, index 1, binding -1, stages 1
-deepD[1].iv4: offset 2480, type 8b52, size 1, index 1, binding -1, stages 1
-deepD[1].d2.i: offset 2480, type 1404, size 1, index 1, binding -1, stages 1
-deepD[1].d2.d1[0].va: offset 2480, type 8b50, size 3, index 1, binding -1, stages 1
-deepD[1].d2.d1[0].b: offset 2480, type 8b56, size 1, index 1, binding -1, stages 1
-deepD[1].d2.d1[1].va: offset 2480, type 8b50, size 3, index 1, binding -1, stages 1
-deepD[1].d2.d1[1].b: offset 2480, type 8b56, size 1, index 1, binding -1, stages 1
-deepD[1].d2.d1[2].va: offset 2480, type 8b50, size 3, index 1, binding -1, stages 1
-deepD[1].d2.d1[2].b: offset 2480, type 8b56, size 1, index 1, binding -1, stages 1
-deepD[1].d2.d1[3].va: offset 2480, type 8b50, size 3, index 1, binding -1, stages 1
-deepD[1].d2.d1[3].b: offset 2480, type 8b56, size 1, index 1, binding -1, stages 1
-deepD[1].v3: offset 2480, type 8b54, size 1, index 1, binding -1, stages 1
+deepD[0].d2.i: offset 2496, type 1404, size 1, index 1, binding -1, stages 1
+deepD[0].d2.d1[0].va: offset 2504, type 8b50, size 3, index 1, binding -1, stages 1
+deepD[0].d2.d1[0].b: offset 2528, type 8b56, size 1, index 1, binding -1, stages 1
+deepD[0].d2.d1[1].va: offset 2536, type 8b50, size 3, index 1, binding -1, stages 1
+deepD[0].d2.d1[1].b: offset 2560, type 8b56, size 1, index 1, binding -1, stages 1
+deepD[0].d2.d1[2].va: offset 2568, type 8b50, size 3, index 1, binding -1, stages 1
+deepD[0].d2.d1[2].b: offset 2592, type 8b56, size 1, index 1, binding -1, stages 1
+deepD[0].d2.d1[3].va: offset 2600, type 8b50, size 3, index 1, binding -1, stages 1
+deepD[0].d2.d1[3].b: offset 2624, type 8b56, size 1, index 1, binding -1, stages 1
+deepD[0].v3: offset 2640, type 8b54, size 1, index 1, binding -1, stages 1
+deepD[1].iv4: offset 2784, type 8b52, size 1, index 1, binding -1, stages 1
+deepD[1].d2.i: offset 2800, type 1404, size 1, index 1, binding -1, stages 1
+deepD[1].d2.d1[0].va: offset 2808, type 8b50, size 3, index 1, binding -1, stages 1
+deepD[1].d2.d1[0].b: offset 2832, type 8b56, size 1, index 1, binding -1, stages 1
+deepD[1].d2.d1[1].va: offset 2840, type 8b50, size 3, index 1, binding -1, stages 1
+deepD[1].d2.d1[1].b: offset 2864, type 8b56, size 1, index 1, binding -1, stages 1
+deepD[1].d2.d1[2].va: offset 2872, type 8b50, size 3, index 1, binding -1, stages 1
+deepD[1].d2.d1[2].b: offset 2896, type 8b56, size 1, index 1, binding -1, stages 1
+deepD[1].d2.d1[3].va: offset 2904, type 8b50, size 3, index 1, binding -1, stages 1
+deepD[1].d2.d1[3].b: offset 2928, type 8b56, size 1, index 1, binding -1, stages 1
+deepD[1].v3: offset 2944, type 8b54, size 1, index 1, binding -1, stages 1
 foo1: offset 0, type 1406, size 1, index 4, binding -1, stages 1
 foo2: offset 0, type 1406, size 1, index 5, binding -1, stages 1
 anonMember1: offset 0, type 8b51, size 1, index 0, binding -1, stages 1
index 52e16e6..5d13523 100644 (file)
@@ -74,6 +74,16 @@ buf1.runtimeArray: offset 4, type 1406, size 4, index 12, binding -1, stages 1
 buf2.runtimeArray.c: offset 8, type 1406, size 1, index 13, binding -1, stages 1
 buf3.runtimeArray: offset 4, type 1406, size 0, index 14, binding -1, stages 1
 buf4.runtimeArray.c: offset 8, type 1406, size 1, index 15, binding -1, stages 1
+nested2.a.n1.a: offset 16, type 1406, size 1, index 16, binding -1, stages 1
+nested2.a.n2.b: offset 32, type 1406, size 1, index 16, binding -1, stages 1
+nested2.a.n2.c: offset 36, type 1406, size 1, index 16, binding -1, stages 1
+nested2.a.n2.d: offset 40, type 1406, size 1, index 16, binding -1, stages 1
+nested2.b[0].a: offset 48, type 1406, size 1, index 16, binding -1, stages 1
+nested2.b[1].a: offset 64, type 1406, size 1, index 16, binding -1, stages 1
+nested2.b[2].a: offset 80, type 1406, size 1, index 16, binding -1, stages 1
+nested2.b[3].a: offset 96, type 1406, size 1, index 16, binding -1, stages 1
+nested2.c.a: offset 112, type 1406, size 1, index 16, binding -1, stages 1
+nested2.d.a: offset 144, type 1406, size 1, index 16, binding -1, stages 1
 anonMember1: offset 0, type 8b51, size 1, index 0, binding -1, stages 1
 uf1: offset -1, type 1406, size 1, index -1, binding -1, stages 1
 uf2: offset -1, type 1406, size 1, index -1, binding -1, stages 1
@@ -96,6 +106,7 @@ buf1: offset -1, type ffffffff, size 4, index -1, binding -1, stages 0
 buf2: offset -1, type ffffffff, size 4, index -1, binding -1, stages 0
 buf3: offset -1, type ffffffff, size 4, index -1, binding -1, stages 0
 buf4: offset -1, type ffffffff, size 4, index -1, binding -1, stages 0
+nested2: offset -1, type ffffffff, size 208, index -1, binding -1, stages 0
 
 Vertex attribute reflection:
 attributeFloat: offset 0, type 1406, size 0, index 0, binding -1, stages 0
index 7549f08..9b3b45c 100644 (file)
@@ -60,6 +60,14 @@ layout(std140) uniform nested {
     N3 foo;\r
 } nest;\r
 \r
+layout(std140) uniform nested2 {\r
+    vec4 padding; // offset 0, size 16\r
+    N3 a;       // offset 16, size 32\r
+    N1 b[4];    // offset 48, size 64\r
+    N1 c[2];    // offset 112, size 32\r
+    N1 d[4];    // offset 144, size 64\r
+} nest2;\r
+\r
 struct TS {\r
     int a;\r
     int dead;\r
@@ -203,4 +211,9 @@ void main()
     f += buf2i.runtimeArray[3].c;\r
     f += buf3i.runtimeArray[gl_InstanceID];\r
     f += buf4i.runtimeArray[gl_InstanceID].c;\r
+\r
+    N3 n = nest2.a;\r
+    N1 b[4] = nest2.b;\r
+    f += nest2.c[1].a;\r
+    f += nest2.d[gl_InstanceID].a;\r
 }\r
index 8cfc2ac..0b6ed39 100644 (file)
@@ -113,6 +113,21 @@ public:
         }
     }
 
+    // shared calculation by getOffset and getOffsets
+    void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize)
+    {
+        int dummyStride;
+
+        // modify just the children's view of matrix layout, if there is one for this member
+        TLayoutMatrix subMatrixLayout = memberType.getQualifier().layoutMatrix;
+        int memberAlignment = intermediate.getMemberAlignment(memberType, memberSize, dummyStride,
+                                                              parentType.getQualifier().layoutPacking,
+                                                              subMatrixLayout != ElmNone
+                                                                  ? subMatrixLayout == ElmRowMajor
+                                                                  : parentType.getQualifier().layoutMatrix == ElmRowMajor);
+        RoundToPow2(offset, memberAlignment);
+    }
+
     // Lookup or calculate the offset of a block member, using the recursively
     // defined block offset rules.
     int getOffset(const TType& type, int index)
@@ -125,18 +140,11 @@ public:
         if (memberList[index].type->getQualifier().hasOffset())
             return memberList[index].type->getQualifier().layoutOffset;
 
-        int memberSize;
-        int dummyStride;
+        int memberSize = 0;
         int offset = 0;
         for (int m = 0; m <= index; ++m) {
-            // modify just the children's view of matrix layout, if there is one for this member
-            TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
-            int memberAlignment = intermediate.getMemberAlignment(*memberList[m].type, memberSize, dummyStride,
-                                                                  type.getQualifier().layoutPacking,
-                                                                  subMatrixLayout != ElmNone
-                                                                      ? subMatrixLayout == ElmRowMajor
-                                                                      : type.getQualifier().layoutMatrix == ElmRowMajor);
-            RoundToPow2(offset, memberAlignment);
+            updateOffset(type, *memberList[m].type, offset, memberSize);
+
             if (m < index)
                 offset += memberSize;
         }
@@ -144,6 +152,50 @@ public:
         return offset;
     }
 
+    // Lookup or calculate the offset of all block members at once, using the recursively
+    // defined block offset rules.
+    void getOffsets(const TType& type, TVector<int>& offsets)
+    {
+        const TTypeList& memberList = *type.getStruct();
+
+        int memberSize = 0;
+        int offset = 0;
+        for (size_t m = 0; m < offsets.size(); ++m) {
+            // if the user supplied an offset, snap to it now
+            if (memberList[m].type->getQualifier().hasOffset())
+                offset = memberList[m].type->getQualifier().layoutOffset;
+
+            // calculate the offset of the next member and align the current offset to this member
+            updateOffset(type, *memberList[m].type, offset, memberSize);
+
+            // save the offset of this member
+            offsets[m] = offset;
+
+            // update for the next member
+            offset += memberSize;
+        }
+    }
+
+    // Calculate the stride of an array type
+    int getArrayStride(const TType& baseType, const TType& type)
+    {
+        int dummySize;
+        int stride;
+
+        // consider blocks to have 0 stride, so that all offsets are relative to the start of their block
+        if (type.getBasicType() == EbtBlock)
+            return 0;
+
+        TLayoutMatrix subMatrixLayout = type.getQualifier().layoutMatrix;
+        intermediate.getMemberAlignment(type, dummySize, stride,
+                                        baseType.getQualifier().layoutPacking,
+                                        subMatrixLayout != ElmNone
+                                            ? subMatrixLayout == ElmRowMajor
+                                            : baseType.getQualifier().layoutMatrix == ElmRowMajor);
+
+        return stride;
+    }
+
     // Calculate the block data size.
     // Block arrayness is not taken into account, each element is backed by a separate buffer.
     int getBlockSize(const TType& blockType)
@@ -179,7 +231,9 @@ public:
             terminalType = &visitNode->getType();
             int index;
             switch (visitNode->getOp()) {
-            case EOpIndexIndirect:
+            case EOpIndexIndirect: {
+                int stride = getArrayStride(baseType, visitNode->getLeft()->getType());
+
                 // Visit all the indices of this array, and for each one add on the remaining dereferencing
                 for (int i = 0; i < std::max(visitNode->getLeft()->getType().getOuterArraySize(), 1); ++i) {
                     TString newBaseName = name;
@@ -189,14 +243,22 @@ public:
                     ++nextDeref;
                     TType derefType(*terminalType, 0);
                     blowUpActiveAggregate(derefType, newBaseName, derefs, nextDeref, offset, blockIndex, arraySize);
+
+                    if (offset >= 0)
+                      offset += stride;
                 }
 
                 // it was all completed in the recursive calls above
                 return;
+            }
             case EOpIndexDirect:
                 index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
-                if (baseType.getBasicType() != EbtBlock)
+                if (baseType.getBasicType() != EbtBlock) {
                     name.append(TString("[") + String(index) + "]");
+
+                    if (offset >= 0)
+                      offset += getArrayStride(baseType, visitNode->getLeft()->getType()) * index;
+                }
                 break;
             case EOpIndexDirectStruct:
                 index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
@@ -213,23 +275,43 @@ public:
 
         // if the terminalType is still too coarse a granularity, this is still an aggregate to expand, expand it...
         if (! isReflectionGranularity(*terminalType)) {
+            // the base offset of this node, that children are relative to
+            int baseOffset = offset;
+
             if (terminalType->isArray()) {
                 // Visit all the indices of this array, and for each one,
                 // fully explode the remaining aggregate to dereference
+
+                int stride = 0;
+                if (offset >= 0)
+                    stride = getArrayStride(baseType, *terminalType);
+
                 for (int i = 0; i < std::max(terminalType->getOuterArraySize(), 1); ++i) {
                     TString newBaseName = name;
                     newBaseName.append(TString("[") + String(i) + "]");
                     TType derefType(*terminalType, 0);
+                    if (offset >= 0)
+                        offset = baseOffset + stride * i;
                     blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0);
                 }
             } else {
                 // Visit all members of this aggregate, and for each one,
                 // fully explode the remaining aggregate to dereference
                 const TTypeList& typeList = *terminalType->getStruct();
+
+                TVector<int> memberOffsets;
+
+                if (baseOffset >= 0) {
+                    memberOffsets.resize(typeList.size());
+                    getOffsets(*terminalType, memberOffsets);
+                }
+
                 for (int i = 0; i < (int)typeList.size(); ++i) {
                     TString newBaseName = name;
                     newBaseName.append(TString(".") + typeList[i].type->getFieldName());
                     TType derefType(*terminalType, i);
+                    if (offset >= 0)
+                        offset = baseOffset + memberOffsets[i];
                     blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0);
                 }
             }