From 1da878f6d1fa5595a710db1029d9cf63028a6364 Mon Sep 17 00:00:00 2001 From: Rex Xu Date: Sun, 21 Feb 2016 20:59:01 +0800 Subject: [PATCH] SPV: Add support for memory qualifiers. --- SPIRV/GlslangToSpv.cpp | 39 ++++ Test/baseResults/spv.double.comp.out | 1 + Test/baseResults/spv.image.frag.out | 1 + Test/baseResults/spv.memoryQualifier.frag.out | 181 ++++++++++++++++++ Test/spv.memoryQualifier.frag | 38 ++++ Test/test-spirv-list | 1 + 6 files changed, 261 insertions(+) create mode 100644 Test/baseResults/spv.memoryQualifier.frag.out create mode 100644 Test/spv.memoryQualifier.frag diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 21a04b0e..cebc7478 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -265,6 +265,21 @@ spv::Decoration TranslateBlockDecoration(const glslang::TType& type) return (spv::Decoration)spv::BadValue; } +// Translate glslang type to SPIR-V memory decorations. +void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector& 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 @@ void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& pa 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 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty addMemberDecoration(spvType, member, TranslateInterpolationDecoration(subQualifier)); addMemberDecoration(spvType, member, TranslateInvariantDecoration(subQualifier)); + if (qualifier.storage == glslang::EvqBuffer) { + std::vector 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 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer); } + if (symbol->getType().isImage()) { + std::vector 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 fcd2f02b..766f839a 100755 --- a/Test/baseResults/spv.double.comp.out +++ b/Test/baseResults/spv.double.comp.out @@ -35,6 +35,7 @@ Linked compute stage: 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 9cb1ec4d..2bd26f79 100644 --- a/Test/baseResults/spv.image.frag.out +++ b/Test/baseResults/spv.image.frag.out @@ -79,6 +79,7 @@ Linked fragment stage: 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 00000000..e2bfb392 --- /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 00000000..85e71478 --- /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 51e2e8f3..f22d500e 100644 --- a/Test/test-spirv-list +++ b/Test/test-spirv-list @@ -60,6 +60,7 @@ spv.loopsArtificial.frag spv.matFun.vert spv.matrix.frag spv.matrix2.frag +spv.memoryQualifier.frag spv.merge-unreachable.frag spv.newTexture.frag spv.nonSquare.vert