From fad62972069d1f20528b2e4520ec8b737a7b1d3e Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Tue, 18 Jul 2017 02:35:46 -0600 Subject: [PATCH 1/2] SPV: Non-functional: support lists of decorations per parameter. --- SPIRV/GlslangToSpv.cpp | 17 +++++++++++++---- SPIRV/SpvBuilder.cpp | 12 +++++++----- SPIRV/SpvBuilder.h | 2 +- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 2899a741..fe51ae1d 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -2914,6 +2914,12 @@ bool TGlslangToSpvTraverser::isShaderEntryPoint(const glslang::TIntermAggregate* // Make all the functions, skeletally, without actually visiting their bodies. void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslFunctions) { + const auto getParamDecorations = [](std::vector& decorations, const glslang::TType& type) { + spv::Decoration paramPrecision = TranslatePrecisionDecoration(type); + if (paramPrecision != spv::NoPrecision) + decorations.push_back(paramPrecision); + }; + for (int f = 0; f < (int)glslFunctions.size(); ++f) { glslang::TIntermAggregate* glslFunction = glslFunctions[f]->getAsAggregate(); if (! glslFunction || glslFunction->getOp() != glslang::EOpFunction || isShaderEntryPoint(glslFunction)) @@ -2934,11 +2940,13 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF // GLSL has copy-in/copy-out semantics. They can be handled though with a pointer to a copy. std::vector paramTypes; - std::vector paramPrecisions; + std::vector> paramDecorations; // list of decorations per parameter glslang::TIntermSequence& parameters = glslFunction->getSequence()[0]->getAsAggregate()->getSequence(); - bool implicitThis = (int)parameters.size() > 0 && parameters[0]->getAsSymbolNode()->getName() == glslangIntermediate->implicitThisName; + bool implicitThis = (int)parameters.size() > 0 && parameters[0]->getAsSymbolNode()->getName() == + glslangIntermediate->implicitThisName; + paramDecorations.resize(parameters.size()); for (int p = 0; p < (int)parameters.size(); ++p) { const glslang::TType& paramType = parameters[p]->getAsTyped()->getType(); spv::Id typeId = convertGlslangToSpvType(paramType); @@ -2952,14 +2960,15 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF typeId = builder.makePointer(spv::StorageClassFunction, typeId); else rValueParameters.insert(parameters[p]->getAsSymbolNode()->getId()); - paramPrecisions.push_back(TranslatePrecisionDecoration(paramType)); + getParamDecorations(paramDecorations[p], paramType); paramTypes.push_back(typeId); } spv::Block* functionBlock; spv::Function *function = builder.makeFunctionEntry(TranslatePrecisionDecoration(glslFunction->getType()), convertGlslangToSpvType(glslFunction->getType()), - glslFunction->getName().c_str(), paramTypes, paramPrecisions, &functionBlock); + glslFunction->getName().c_str(), paramTypes, + paramDecorations, &functionBlock); if (implicitThis) function->setImplicitThis(); diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index 11e9fe60..d472eb53 100644 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -983,16 +983,16 @@ Function* Builder::makeEntryPoint(const char* entryPoint) Block* entry; std::vector params; - std::vector precisions; + std::vector> decorations; - entryPointFunction = makeFunctionEntry(NoPrecision, makeVoidType(), entryPoint, params, precisions, &entry); + entryPointFunction = makeFunctionEntry(NoPrecision, makeVoidType(), entryPoint, params, decorations, &entry); return entryPointFunction; } // Comments in header Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name, - const std::vector& paramTypes, const std::vector& precisions, Block **entry) + const std::vector& paramTypes, const std::vector>& decorations, Block **entry) { // Make the function and initial instructions in it Id typeId = makeFunctionType(returnType, paramTypes); @@ -1001,8 +1001,10 @@ Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const // Set up the precisions setPrecision(function->getId(), precision); - for (unsigned p = 0; p < (unsigned)precisions.size(); ++p) - setPrecision(firstParamId + p, precisions[p]); + for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) { + for (int d = 0; d < (int)decorations[p].size(); ++d) + addDecoration(firstParamId + p, decorations[p][d]); + } // CFG if (entry) { diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h index 2b17ba60..3a949190 100755 --- a/SPIRV/SpvBuilder.h +++ b/SPIRV/SpvBuilder.h @@ -247,7 +247,7 @@ public: // Return the function, pass back the entry. // The returned pointer is only valid for the lifetime of this builder. Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, const std::vector& paramTypes, - const std::vector& precisions, Block **entry = 0); + const std::vector>& precisions, Block **entry = 0); // Create a return. An 'implicit' return is one not appearing in the source // code. In the case of an implicit return, no post-return block is inserted. From 961cd35b7337b2137ba9d96859c093871cd3a7ef Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Tue, 18 Jul 2017 02:58:06 -0600 Subject: [PATCH 2/2] SPV: Fix #995: Include memory decorations on parameters. --- SPIRV/GlslangToSpv.cpp | 1 + .../baseResults/hlsl.structbuffer.fn.frag.out | 1 + .../hlsl.structbuffer.fn2.comp.out | 1 + Test/baseResults/spv.paramMemory.frag.out | 137 ++++++++++++++++++ Test/spv.paramMemory.frag | 30 ++++ gtests/Spv.FromFile.cpp | 1 + 6 files changed, 171 insertions(+) create mode 100755 Test/baseResults/spv.paramMemory.frag.out create mode 100644 Test/spv.paramMemory.frag diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index fe51ae1d..b65d6ed6 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -2918,6 +2918,7 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF spv::Decoration paramPrecision = TranslatePrecisionDecoration(type); if (paramPrecision != spv::NoPrecision) decorations.push_back(paramPrecision); + TranslateMemoryDecoration(type.getQualifier(), decorations); }; for (int f = 0; f < (int)glslFunctions.size(); ++f) { diff --git a/Test/baseResults/hlsl.structbuffer.fn.frag.out b/Test/baseResults/hlsl.structbuffer.fn.frag.out index 63aaa625..2e2a44fb 100644 --- a/Test/baseResults/hlsl.structbuffer.fn.frag.out +++ b/Test/baseResults/hlsl.structbuffer.fn.frag.out @@ -184,6 +184,7 @@ gl_FragCoord origin is upper left MemberDecorate 9 0 NonWritable MemberDecorate 9 0 Offset 0 Decorate 9 BufferBlock + Decorate 13(sb) NonWritable Decorate 17 ArrayStride 16 MemberDecorate 18 0 Offset 0 Decorate 18 BufferBlock diff --git a/Test/baseResults/hlsl.structbuffer.fn2.comp.out b/Test/baseResults/hlsl.structbuffer.fn2.comp.out index 686a0a2b..cb12ba5d 100644 --- a/Test/baseResults/hlsl.structbuffer.fn2.comp.out +++ b/Test/baseResults/hlsl.structbuffer.fn2.comp.out @@ -166,6 +166,7 @@ local_size = (256, 1, 1) MemberDecorate 9 0 NonWritable MemberDecorate 9 0 Offset 0 Decorate 9 BufferBlock + Decorate 14(buffer) NonWritable Decorate 44(g_input) DescriptorSet 0 Decorate 44(g_input) Binding 0 Decorate 50(g_output) DescriptorSet 0 diff --git a/Test/baseResults/spv.paramMemory.frag.out b/Test/baseResults/spv.paramMemory.frag.out new file mode 100755 index 00000000..8b98b49c --- /dev/null +++ b/Test/baseResults/spv.paramMemory.frag.out @@ -0,0 +1,137 @@ +spv.paramMemory.frag +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 69 + + Capability Shader + Capability StorageImageReadWithoutFormat + Capability StorageImageWriteWithoutFormat + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 27 66 + ExecutionMode 4 OriginUpperLeft + Source ESSL 310 + Name 4 "main" + Name 16 "image_load(I21;vi2;" + Name 14 "image" + Name 15 "coords" + Name 23 "image_store(I21;vi2;vf4;" + Name 20 "image" + Name 21 "coords" + Name 22 "data" + Name 27 "in_coords" + Name 35 "read1" + Name 38 "image1" + Name 39 "param" + Name 42 "read2" + Name 45 "image2" + Name 46 "param" + Name 49 "image3" + Name 53 "param" + Name 55 "param" + Name 57 "image4" + Name 61 "param" + Name 63 "param" + Name 66 "out_color" + Decorate 14(image) Coherent + Decorate 14(image) NonWritable + Decorate 20(image) Coherent + Decorate 20(image) NonReadable + Decorate 27(in_coords) Flat + Decorate 27(in_coords) Location 0 + Decorate 38(image1) DescriptorSet 0 + Decorate 38(image1) Binding 0 + Decorate 38(image1) Coherent + Decorate 38(image1) NonWritable + Decorate 45(image2) DescriptorSet 0 + Decorate 45(image2) Binding 2 + Decorate 45(image2) NonWritable + Decorate 49(image3) DescriptorSet 0 + Decorate 49(image3) Binding 1 + Decorate 49(image3) Coherent + Decorate 49(image3) NonReadable + Decorate 57(image4) DescriptorSet 0 + Decorate 57(image4) Binding 3 + Decorate 57(image4) NonReadable + Decorate 66(out_color) Location 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeImage 6(float) 2D nonsampled format:Unknown + 8: TypePointer UniformConstant 7 + 9: TypeInt 32 1 + 10: TypeVector 9(int) 2 + 11: TypePointer Function 10(ivec2) + 12: TypeVector 6(float) 4 + 13: TypeFunction 12(fvec4) 8(ptr) 11(ptr) + 18: TypePointer Function 12(fvec4) + 19: TypeFunction 2 8(ptr) 11(ptr) 18(ptr) + 26: TypePointer Input 10(ivec2) + 27(in_coords): 26(ptr) Variable Input + 36: TypeImage 6(float) 2D nonsampled format:Rgba32f + 37: TypePointer UniformConstant 36 + 38(image1): 37(ptr) Variable UniformConstant + 43: TypeImage 6(float) 2D nonsampled format:Rgba16f + 44: TypePointer UniformConstant 43 + 45(image2): 44(ptr) Variable UniformConstant + 49(image3): 37(ptr) Variable UniformConstant + 51: 6(float) Constant 1056964608 + 57(image4): 44(ptr) Variable UniformConstant + 59: 6(float) Constant 1073741824 + 65: TypePointer Output 12(fvec4) + 66(out_color): 65(ptr) Variable Output + 67: 6(float) Constant 0 + 68: 12(fvec4) ConstantComposite 67 67 67 67 + 4(main): 2 Function None 3 + 5: Label + 35(read1): 18(ptr) Variable Function + 39(param): 11(ptr) Variable Function + 42(read2): 18(ptr) Variable Function + 46(param): 11(ptr) Variable Function + 53(param): 11(ptr) Variable Function + 55(param): 18(ptr) Variable Function + 61(param): 11(ptr) Variable Function + 63(param): 18(ptr) Variable Function + 40: 10(ivec2) Load 27(in_coords) + Store 39(param) 40 + 41: 12(fvec4) FunctionCall 16(image_load(I21;vi2;) 38(image1) 39(param) + Store 35(read1) 41 + 47: 10(ivec2) Load 27(in_coords) + Store 46(param) 47 + 48: 12(fvec4) FunctionCall 16(image_load(I21;vi2;) 45(image2) 46(param) + Store 42(read2) 48 + 50: 12(fvec4) Load 35(read1) + 52: 12(fvec4) VectorTimesScalar 50 51 + 54: 10(ivec2) Load 27(in_coords) + Store 53(param) 54 + Store 55(param) 52 + 56: 2 FunctionCall 23(image_store(I21;vi2;vf4;) 49(image3) 53(param) 55(param) + 58: 12(fvec4) Load 42(read2) + 60: 12(fvec4) VectorTimesScalar 58 59 + 62: 10(ivec2) Load 27(in_coords) + Store 61(param) 62 + Store 63(param) 60 + 64: 2 FunctionCall 23(image_store(I21;vi2;vf4;) 57(image4) 61(param) 63(param) + Store 66(out_color) 68 + Return + FunctionEnd +16(image_load(I21;vi2;): 12(fvec4) Function None 13 + 14(image): 8(ptr) FunctionParameter + 15(coords): 11(ptr) FunctionParameter + 17: Label + 25: 7 Load 14(image) + 28: 10(ivec2) Load 27(in_coords) + 29: 12(fvec4) ImageRead 25 28 + ReturnValue 29 + FunctionEnd +23(image_store(I21;vi2;vf4;): 2 Function None 19 + 20(image): 8(ptr) FunctionParameter + 21(coords): 11(ptr) FunctionParameter + 22(data): 18(ptr) FunctionParameter + 24: Label + 32: 7 Load 20(image) + 33: 10(ivec2) Load 27(in_coords) + 34: 12(fvec4) Load 22(data) + ImageWrite 32 33 34 + Return + FunctionEnd diff --git a/Test/spv.paramMemory.frag b/Test/spv.paramMemory.frag new file mode 100644 index 00000000..79d2fe57 --- /dev/null +++ b/Test/spv.paramMemory.frag @@ -0,0 +1,30 @@ +#version 310 es + +readonly coherent uniform layout(set = 0, binding = 0, rgba32f) highp image2D image1; +readonly uniform layout(set = 0, binding = 2, rgba16f) highp image2D image2; +writeonly coherent uniform layout(set = 0, binding = 1, rgba32f) highp image2D image3; +writeonly uniform layout(set = 0, binding = 3, rgba16f) highp image2D image4; + +flat in layout(location = 0) highp ivec2 in_coords; +out layout(location = 0) highp vec4 out_color; + +highp vec4 image_load(readonly coherent highp image2D image, highp ivec2 coords) +{ + return imageLoad(image, in_coords); +} + +void image_store(writeonly coherent highp image2D image, highp ivec2 coords, highp vec4 data) +{ + imageStore(image, in_coords, data); +} + +void main() +{ + highp vec4 read1 = image_load(image1, in_coords); + highp vec4 read2 = image_load(image2, in_coords); + + image_store(image3, in_coords, read1*0.5); + image_store(image4, in_coords, read2*2.0); + + out_color = vec4(0.0); +} diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp index 268aa0b7..dfad30c7 100644 --- a/gtests/Spv.FromFile.cpp +++ b/gtests/Spv.FromFile.cpp @@ -275,6 +275,7 @@ INSTANTIATE_TEST_CASE_P( "spv.noWorkgroup.comp", "spv.offsets.frag", "spv.Operations.frag", + "spv.paramMemory.frag", "spv.precision.frag", "spv.prepost.frag", "spv.qualifiers.vert",