SPV: Add support for memory qualifiers.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 21a04b0..cebc747 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -265,6 +265,21 @@
return (spv::Decoration)spv::BadValue;
}
+// Translate glslang type to SPIR-V memory decorations.
+void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector<spv::Decoration>& memory)
+{
+ if (qualifier.coherent)
+ memory.push_back(spv::DecorationCoherent);
+ if (qualifier.volatil)
+ memory.push_back(spv::DecorationVolatile);
+ if (qualifier.restrict)
+ memory.push_back(spv::DecorationRestrict);
+ if (qualifier.readonly)
+ memory.push_back(spv::DecorationNonWritable);
+ if (qualifier.writeonly)
+ memory.push_back(spv::DecorationNonReadable);
+}
+
// Translate glslang type to SPIR-V layout decorations.
spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::TLayoutMatrix matrixLayout)
{
@@ -535,6 +550,16 @@
child.patch = true;
if (parent.sample)
child.sample = true;
+ if (parent.coherent)
+ child.coherent = true;
+ if (parent.volatil)
+ child.volatil = true;
+ if (parent.restrict)
+ child.restrict = true;
+ if (parent.readonly)
+ child.readonly = true;
+ if (parent.writeonly)
+ child.writeonly = true;
}
bool HasNonLayoutQualifiers(const glslang::TQualifier& qualifier)
@@ -1759,6 +1784,13 @@
addMemberDecoration(spvType, member, TranslateInterpolationDecoration(subQualifier));
addMemberDecoration(spvType, member, TranslateInvariantDecoration(subQualifier));
+ if (qualifier.storage == glslang::EvqBuffer) {
+ std::vector<spv::Decoration> memory;
+ TranslateMemoryDecoration(subQualifier, memory);
+ for (unsigned int i = 0; i < memory.size(); ++i)
+ addMemberDecoration(spvType, member, memory[i]);
+ }
+
// compute location decoration; tricky based on whether inheritance is at play
// TODO: This algorithm (and it's cousin above doing almost the same thing) should
// probably move to the linker stage of the front end proper, and just have the
@@ -3575,6 +3607,13 @@
builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer);
}
+ if (symbol->getType().isImage()) {
+ std::vector<spv::Decoration> memory;
+ TranslateMemoryDecoration(symbol->getType().getQualifier(), memory);
+ for (unsigned int i = 0; i < memory.size(); ++i)
+ addDecoration(id, memory[i]);
+ }
+
// built-in variable decorations
spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn);
if (builtIn != spv::BadValue)
diff --git a/Test/baseResults/spv.double.comp.out b/Test/baseResults/spv.double.comp.out
index fcd2f02..766f839 100755
--- a/Test/baseResults/spv.double.comp.out
+++ b/Test/baseResults/spv.double.comp.out
@@ -35,6 +35,7 @@
Decorate 26(gl_GlobalInvocationID) BuiltIn GlobalInvocationId
Decorate 33(gl_LocalInvocationID) BuiltIn LocalInvocationId
Decorate 59(destTex) DescriptorSet 0
+ Decorate 59(destTex) NonReadable
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
diff --git a/Test/baseResults/spv.image.frag.out b/Test/baseResults/spv.image.frag.out
index 9cb1ec4..2bd26f7 100644
--- a/Test/baseResults/spv.image.frag.out
+++ b/Test/baseResults/spv.image.frag.out
@@ -79,6 +79,7 @@
Decorate 248(value) Flat
Decorate 357(wo2D) DescriptorSet 0
Decorate 357(wo2D) Binding 1
+ Decorate 357(wo2D) NonReadable
Decorate 377(ic4D) Flat
2: TypeVoid
3: TypeFunction 2
diff --git a/Test/baseResults/spv.memoryQualifier.frag.out b/Test/baseResults/spv.memoryQualifier.frag.out
new file mode 100644
index 0000000..e2bfb39
--- /dev/null
+++ b/Test/baseResults/spv.memoryQualifier.frag.out
@@ -0,0 +1,181 @@
+spv.memoryQualifier.frag
+Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
+
+
+Linked fragment stage:
+
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 97
+
+ Capability Shader
+ Capability SampledRect
+ Capability Sampled1D
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Fragment 4 "main"
+ ExecutionMode 4 OriginUpperLeft
+ Source GLSL 450
+ Name 4 "main"
+ Name 9 "texel"
+ Name 12 "i1D"
+ Name 19 "i2D"
+ Name 28 "i2DRect"
+ Name 35 "i3D"
+ Name 44 "iCube"
+ Name 49 "Data"
+ MemberName 49(Data) 0 "f1"
+ MemberName 49(Data) 1 "f2"
+ Name 50 "Buffer"
+ MemberName 50(Buffer) 0 "f1"
+ MemberName 50(Buffer) 1 "f2"
+ MemberName 50(Buffer) 2 "f3"
+ MemberName 50(Buffer) 3 "f4"
+ MemberName 50(Buffer) 4 "i1"
+ MemberName 50(Buffer) 5 "data"
+ Name 52 ""
+ Decorate 12(i1D) DescriptorSet 0
+ Decorate 12(i1D) Binding 0
+ Decorate 12(i1D) Coherent
+ Decorate 19(i2D) DescriptorSet 0
+ Decorate 19(i2D) Binding 1
+ Decorate 19(i2D) Volatile
+ Decorate 28(i2DRect) DescriptorSet 0
+ Decorate 28(i2DRect) Binding 2
+ Decorate 28(i2DRect) Restrict
+ Decorate 35(i3D) DescriptorSet 0
+ Decorate 35(i3D) Binding 3
+ Decorate 35(i3D) NonWritable
+ Decorate 44(iCube) DescriptorSet 0
+ Decorate 44(iCube) Binding 3
+ Decorate 44(iCube) NonReadable
+ MemberDecorate 49(Data) 0 Coherent
+ MemberDecorate 49(Data) 0 Offset 0
+ MemberDecorate 49(Data) 1 Coherent
+ MemberDecorate 49(Data) 1 Offset 8
+ MemberDecorate 50(Buffer) 0 Coherent
+ MemberDecorate 50(Buffer) 0 Volatile
+ MemberDecorate 50(Buffer) 0 Offset 0
+ MemberDecorate 50(Buffer) 1 Coherent
+ MemberDecorate 50(Buffer) 1 Restrict
+ MemberDecorate 50(Buffer) 1 Offset 8
+ MemberDecorate 50(Buffer) 2 Coherent
+ MemberDecorate 50(Buffer) 2 NonWritable
+ MemberDecorate 50(Buffer) 2 Offset 16
+ MemberDecorate 50(Buffer) 3 Coherent
+ MemberDecorate 50(Buffer) 3 NonReadable
+ MemberDecorate 50(Buffer) 3 Offset 32
+ MemberDecorate 50(Buffer) 4 Coherent
+ MemberDecorate 50(Buffer) 4 Offset 48
+ MemberDecorate 50(Buffer) 5 Coherent
+ MemberDecorate 50(Buffer) 5 Offset 56
+ Decorate 50(Buffer) BufferBlock
+ Decorate 52 DescriptorSet 0
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeFloat 32
+ 7: TypeVector 6(float) 4
+ 8: TypePointer Function 7(fvec4)
+ 10: TypeImage 6(float) 1D nonsampled format:R32f
+ 11: TypePointer UniformConstant 10
+ 12(i1D): 11(ptr) Variable UniformConstant
+ 14: TypeInt 32 1
+ 15: 14(int) Constant 1
+ 17: TypeImage 6(float) 2D nonsampled format:R32f
+ 18: TypePointer UniformConstant 17
+ 19(i2D): 18(ptr) Variable UniformConstant
+ 21: TypeVector 14(int) 2
+ 22: 21(ivec2) ConstantComposite 15 15
+ 26: TypeImage 6(float) Rect nonsampled format:R32f
+ 27: TypePointer UniformConstant 26
+ 28(i2DRect): 27(ptr) Variable UniformConstant
+ 33: TypeImage 6(float) 3D nonsampled format:R32f
+ 34: TypePointer UniformConstant 33
+ 35(i3D): 34(ptr) Variable UniformConstant
+ 37: TypeVector 14(int) 3
+ 38: 37(ivec3) ConstantComposite 15 15 15
+ 42: TypeImage 6(float) Cube nonsampled format:R32f
+ 43: TypePointer UniformConstant 42
+ 44(iCube): 43(ptr) Variable UniformConstant
+ 47: TypeVector 6(float) 2
+ 48: TypeVector 6(float) 3
+ 49(Data): TypeStruct 6(float) 47(fvec2)
+ 50(Buffer): TypeStruct 6(float) 47(fvec2) 48(fvec3) 7(fvec4) 14(int) 49(Data)
+ 51: TypePointer Uniform 50(Buffer)
+ 52: 51(ptr) Variable Uniform
+ 53: 14(int) Constant 4
+ 54: TypePointer Uniform 14(int)
+ 57: 14(int) Constant 0
+ 58: TypePointer Uniform 6(float)
+ 61: TypePointer Function 6(float)
+ 63: TypePointer Uniform 47(fvec2)
+ 71: 14(int) Constant 2
+ 72: TypePointer Uniform 48(fvec3)
+ 80: 14(int) Constant 5
+ 83: TypeInt 32 0
+ 84: 83(int) Constant 1
+ 88: 83(int) Constant 3
+ 93: 14(int) Constant 3
+ 95: TypePointer Uniform 7(fvec4)
+ 4(main): 2 Function None 3
+ 5: Label
+ 9(texel): 8(ptr) Variable Function
+ 13: 10 Load 12(i1D)
+ 16: 7(fvec4) ImageRead 13 15
+ Store 9(texel) 16
+ 20: 17 Load 19(i2D)
+ 23: 7(fvec4) ImageRead 20 22
+ 24: 7(fvec4) Load 9(texel)
+ 25: 7(fvec4) FAdd 24 23
+ Store 9(texel) 25
+ 29: 26 Load 28(i2DRect)
+ 30: 7(fvec4) ImageRead 29 22
+ 31: 7(fvec4) Load 9(texel)
+ 32: 7(fvec4) FAdd 31 30
+ Store 9(texel) 32
+ 36: 33 Load 35(i3D)
+ 39: 7(fvec4) ImageRead 36 38
+ 40: 7(fvec4) Load 9(texel)
+ 41: 7(fvec4) FAdd 40 39
+ Store 9(texel) 41
+ 45: 42 Load 44(iCube)
+ 46: 7(fvec4) Load 9(texel)
+ ImageWrite 45 38 46
+ 55: 54(ptr) AccessChain 52 53
+ 56: 14(int) Load 55
+ 59: 58(ptr) AccessChain 52 57
+ 60: 6(float) Load 59
+ 62: 61(ptr) AccessChain 9(texel) 56
+ Store 62 60
+ 64: 63(ptr) AccessChain 52 15
+ 65: 47(fvec2) Load 64
+ 66: 7(fvec4) Load 9(texel)
+ 67: 47(fvec2) VectorShuffle 66 66 0 1
+ 68: 47(fvec2) FAdd 67 65
+ 69: 7(fvec4) Load 9(texel)
+ 70: 7(fvec4) VectorShuffle 69 68 4 5 2 3
+ Store 9(texel) 70
+ 73: 72(ptr) AccessChain 52 71
+ 74: 48(fvec3) Load 73
+ 75: 7(fvec4) Load 9(texel)
+ 76: 48(fvec3) VectorShuffle 75 75 0 1 2
+ 77: 48(fvec3) FSub 76 74
+ 78: 7(fvec4) Load 9(texel)
+ 79: 7(fvec4) VectorShuffle 78 77 4 5 6 3
+ Store 9(texel) 79
+ 81: 58(ptr) AccessChain 52 80 57
+ 82: 6(float) Load 81
+ 85: 58(ptr) AccessChain 52 80 15 84
+ 86: 6(float) Load 85
+ 87: 6(float) FAdd 82 86
+ 89: 61(ptr) AccessChain 9(texel) 88
+ 90: 6(float) Load 89
+ 91: 6(float) FAdd 90 87
+ 92: 61(ptr) AccessChain 9(texel) 88
+ Store 92 91
+ 94: 7(fvec4) Load 9(texel)
+ 96: 95(ptr) AccessChain 52 93
+ Store 96 94
+ Return
+ FunctionEnd
diff --git a/Test/spv.memoryQualifier.frag b/Test/spv.memoryQualifier.frag
new file mode 100644
index 0000000..85e7147
--- /dev/null
+++ b/Test/spv.memoryQualifier.frag
@@ -0,0 +1,38 @@
+#version 450
+
+layout(binding = 0, r32f) uniform coherent image1D i1D;
+layout(binding = 1, r32f) uniform volatile image2D i2D;
+layout(binding = 2, r32f) uniform restrict image2DRect i2DRect;
+layout(binding = 3, r32f) uniform readonly image3D i3D;
+layout(binding = 3, r32f) uniform writeonly imageCube iCube;
+
+struct Data
+{
+ float f1;
+ vec2 f2;
+};
+
+coherent buffer Buffer
+{
+ volatile float f1;
+ restrict vec2 f2;
+ readonly vec3 f3;
+ writeonly vec4 f4;
+ int i1;
+ Data data;
+};
+
+void main()
+{
+ vec4 texel = imageLoad(i1D, 1);
+ texel += imageLoad(i2D, ivec2(1));
+ texel += imageLoad(i2DRect, ivec2(1));
+ texel += imageLoad(i3D, ivec3(1));
+ imageStore(iCube, ivec3(1), texel);
+
+ texel[i1] = f1;
+ texel.xy += f2;
+ texel.xyz -= f3;
+ texel.w += data.f1 + data.f2[1];
+ f4 = texel;
+}
\ No newline at end of file
diff --git a/Test/test-spirv-list b/Test/test-spirv-list
index 51e2e8f..f22d500 100644
--- a/Test/test-spirv-list
+++ b/Test/test-spirv-list
@@ -60,6 +60,7 @@
spv.matFun.vert
spv.matrix.frag
spv.matrix2.frag
+spv.memoryQualifier.frag
spv.merge-unreachable.frag
spv.newTexture.frag
spv.nonSquare.vert