SPV: Plumb through XFB buffer and stride information.
Also, only emit this XFB information where the SPIR-V spec says
it should be emitted: essentially, on objects.
This and the previous commit together fix #1185.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 4ae5286..745021f 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -2661,13 +2661,6 @@
builder.addCapability(spv::CapabilityGeometryStreams);
builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream);
}
- if (glslangIntermediate->getXfbMode()) {
- builder.addCapability(spv::CapabilityTransformFeedback);
- if (type.getQualifier().hasXfbStride())
- builder.addDecoration(spvType, spv::DecorationXfbStride, type.getQualifier().layoutXfbStride);
- if (type.getQualifier().hasXfbBuffer())
- builder.addDecoration(spvType, spv::DecorationXfbBuffer, type.getQualifier().layoutXfbBuffer);
- }
}
// Turn the expression forming the array size into an id.
@@ -5508,15 +5501,6 @@
builder.addDecoration(id, spv::DecorationIndex, symbol->getQualifier().layoutIndex);
if (symbol->getQualifier().hasComponent())
builder.addDecoration(id, spv::DecorationComponent, symbol->getQualifier().layoutComponent);
- if (glslangIntermediate->getXfbMode()) {
- builder.addCapability(spv::CapabilityTransformFeedback);
- if (symbol->getQualifier().hasXfbStride())
- builder.addDecoration(id, spv::DecorationXfbStride, symbol->getQualifier().layoutXfbStride);
- if (symbol->getQualifier().hasXfbBuffer())
- builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer);
- if (symbol->getQualifier().hasXfbOffset())
- builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutXfbOffset);
- }
// atomic counters use this:
if (symbol->getQualifier().hasOffset())
builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutOffset);
@@ -5543,8 +5527,14 @@
builder.addCapability(spv::CapabilityTransformFeedback);
if (symbol->getQualifier().hasXfbStride())
builder.addDecoration(id, spv::DecorationXfbStride, symbol->getQualifier().layoutXfbStride);
- if (symbol->getQualifier().hasXfbBuffer())
+ if (symbol->getQualifier().hasXfbBuffer()) {
builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer);
+ unsigned stride = glslangIntermediate->getXfbStride(symbol->getQualifier().layoutXfbBuffer);
+ if (stride != glslang::TQualifier::layoutXfbStrideEnd)
+ builder.addDecoration(id, spv::DecorationXfbStride, stride);
+ }
+ if (symbol->getQualifier().hasXfbOffset())
+ builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutXfbOffset);
}
if (symbol->getType().isImage()) {
diff --git a/Test/baseResults/spv.builtInXFB.vert.out b/Test/baseResults/spv.builtInXFB.vert.out
index 741030e..f13dfe1 100755
--- a/Test/baseResults/spv.builtInXFB.vert.out
+++ b/Test/baseResults/spv.builtInXFB.vert.out
@@ -20,8 +20,8 @@
MemberDecorate 8(gl_PerVertex) 1 Offset 16
MemberDecorate 8(gl_PerVertex) 1 BuiltIn PointSize
Decorate 8(gl_PerVertex) Block
- Decorate 8(gl_PerVertex) XfbBuffer 0
- Decorate 10 XfbBuffer 0
+ Decorate 10 XfbBuffer 1
+ Decorate 10 XfbStride 64
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
diff --git a/Test/baseResults/spv.xfb.vert.out b/Test/baseResults/spv.xfb.vert.out
new file mode 100755
index 0000000..f609826
--- /dev/null
+++ b/Test/baseResults/spv.xfb.vert.out
@@ -0,0 +1,55 @@
+spv.xfb.vert
+// Module Version 10000
+// Generated by (magic number): 80002
+// Id's are bound by 16
+
+ Capability Shader
+ Capability TransformFeedback
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Vertex 4 "main" 8 11 14 15
+ ExecutionMode 4 Xfb
+ Source GLSL 450
+ Name 4 "main"
+ Name 8 "out1"
+ Name 9 "outXfb"
+ MemberName 9(outXfb) 0 "out2"
+ Name 11 ""
+ Name 12 "outXfb2"
+ MemberName 12(outXfb2) 0 "out3"
+ Name 14 ""
+ Name 15 "out4"
+ Decorate 8(out1) Location 0
+ Decorate 8(out1) XfbBuffer 3
+ Decorate 8(out1) XfbStride 48
+ Decorate 8(out1) Offset 12
+ MemberDecorate 9(outXfb) 0 Offset 8
+ Decorate 9(outXfb) Block
+ Decorate 11 Location 1
+ Decorate 11 XfbBuffer 2
+ Decorate 11 XfbStride 32
+ MemberDecorate 12(outXfb2) 0 Offset 60
+ Decorate 12(outXfb2) Block
+ Decorate 14 Location 3
+ Decorate 14 XfbBuffer 1
+ Decorate 14 XfbStride 64
+ Decorate 15(out4) Location 4
+ Decorate 15(out4) XfbBuffer 0
+ Decorate 15(out4) XfbStride 8
+ Decorate 15(out4) Offset 4
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeFloat 32
+ 7: TypePointer Output 6(float)
+ 8(out1): 7(ptr) Variable Output
+ 9(outXfb): TypeStruct 6(float)
+ 10: TypePointer Output 9(outXfb)
+ 11: 10(ptr) Variable Output
+ 12(outXfb2): TypeStruct 6(float)
+ 13: TypePointer Output 12(outXfb2)
+ 14: 13(ptr) Variable Output
+ 15(out4): 7(ptr) Variable Output
+ 4(main): 2 Function None 3
+ 5: Label
+ Return
+ FunctionEnd
diff --git a/Test/spv.xfb.vert b/Test/spv.xfb.vert
new file mode 100644
index 0000000..ad762bc
--- /dev/null
+++ b/Test/spv.xfb.vert
@@ -0,0 +1,20 @@
+#version 450
+
+layout(xfb_buffer = 3) out;
+layout(xfb_stride = 48) out;
+layout(xfb_offset = 12, location = 0) out float out1;
+
+layout(xfb_buffer = 2) out;
+layout(location=1) out outXfb {
+ layout(xfb_buffer = 2, xfb_stride = 32, xfb_offset = 8) float out2;
+};
+
+layout(xfb_buffer = 1, location=3) out outXfb2 {
+ layout(xfb_stride = 64, xfb_offset = 60) float out3;
+};
+
+layout(location = 4, xfb_buffer = 0, xfb_offset = 4) out float out4;
+
+void main()
+{
+}
\ No newline at end of file
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 80471c4..78a5d8e 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -3550,7 +3550,8 @@
oldType.getQualifier().flat = newType.getQualifier().flat;
oldType.getQualifier().nopersp = newType.getQualifier().nopersp;
oldType.getQualifier().layoutXfbOffset = newType.getQualifier().layoutXfbOffset;
-
+ if (oldType.getQualifier().layoutXfbOffset != TQualifier::layoutXfbBufferEnd)
+ type.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer;
if (oldType.isImplicitlySizedArray() && newType.isExplicitlySizedArray())
oldType.changeOuterArraySize(newType.getOuterArraySize());
diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h
index 8665176..4d48c68 100644
--- a/glslang/MachineIndependent/localintermediate.h
+++ b/glslang/MachineIndependent/localintermediate.h
@@ -583,6 +583,7 @@
xfbBuffers[buffer].stride = stride;
return true;
}
+ unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; }
int addXfbBufferOffset(const TType&);
unsigned int computeTypeXfbSize(const TType&, bool& containsDouble) const;
static int getBaseAlignmentScalar(const TType&, int& size);
diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp
index 9a44fa4..da80b11 100644
--- a/gtests/Spv.FromFile.cpp
+++ b/gtests/Spv.FromFile.cpp
@@ -329,6 +329,7 @@
"spv.storageBuffer.vert",
"spv.precise.tese",
"spv.precise.tesc",
+ "spv.xfb.vert",
})),
FileNameAsCustomTestSuffix
);