diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 1e03909b..aae3f491 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -2728,7 +2728,23 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& /*structTy int memberSize; int dummyStride; int memberAlignment = glslangIntermediate->getBaseAlignment(memberType, memberSize, dummyStride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor); + + // Adjust alignment for HLSL rules + if (glslangIntermediate->usingHlslOFfsets() && + ! memberType.isArray() && memberType.isVector()) { + int dummySize; + int componentAlignment = glslangIntermediate->getBaseAlignmentScalar(memberType, dummySize); + if (componentAlignment <= 4) + memberAlignment = componentAlignment; + } + + // Bump up to member alignment glslang::RoundToPow2(currentOffset, memberAlignment); + + // Bump up to vec4 if there is a bad straddle + if (glslangIntermediate->improperStraddle(memberType, memberSize, currentOffset)) + glslang::RoundToPow2(currentOffset, 16); + nextOffset = currentOffset + memberSize; } diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index 56d66194..60dbc4da 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -86,6 +86,7 @@ enum TOptions { EOptionFlattenUniformArrays = (1 << 20), EOptionNoStorageFormat = (1 << 21), EOptionKeepUncalled = (1 << 22), + EOptionHlslOffsets = (1 << 23), }; // @@ -311,8 +312,7 @@ void ProcessArguments(std::vector>& workItem } else Error("no provided for --variable-name"); break; - } - else if (lowerword == "source-entrypoint" || // synonyms + } else if (lowerword == "source-entrypoint" || // synonyms lowerword == "sep") { sourceEntryPointName = argv[1]; if (argc > 0) { @@ -324,6 +324,8 @@ void ProcessArguments(std::vector>& workItem } else if (lowerword == "keep-uncalled" || // synonyms lowerword == "ku") { Options |= EOptionKeepUncalled; + } else if (lowerword == "hlsl-offsets") { + Options |= EOptionHlslOffsets; } else { usage(); } @@ -471,6 +473,8 @@ void SetMessageOptions(EShMessages& messages) messages = (EShMessages)(messages | EShMsgCascadingErrors); if (Options & EOptionKeepUncalled) messages = (EShMessages)(messages | EShMsgKeepUncalled); + if (Options & EOptionHlslOffsets) + messages = (EShMessages)(messages | EShMsgHlslOffsets); } // @@ -998,8 +1002,13 @@ void usage() "\n" " --keep-uncalled don't eliminate uncalled functions when linking\n" " --ku synonym for --keep-uncalled\n" - " --variable-name Creates a C header file that contains a uint32_t array named initialized with the shader binary code.\n" - " --vn synonym for --variable-name .\n" + "\n" + " --variable-name Creates a C header file that contains a uint32_t array named \n" + " initialized with the shader binary code.\n" + " --vn synonym for --variable-name \n" + "\n" + " --hlsl-offsets Allow block offsets to follow HLSL rules instead of GLSL rules.\n" + " Works independently of source language.\n" ); exit(EFailUsage); diff --git a/Test/baseResults/hlsl.hlslOffset.vert.out b/Test/baseResults/hlsl.hlslOffset.vert.out new file mode 100644 index 00000000..380a0861 --- /dev/null +++ b/Test/baseResults/hlsl.hlslOffset.vert.out @@ -0,0 +1,84 @@ +hlsl.hlslOffset.vert +Shader version: 450 +0:? Sequence +0:20 Function Definition: @main( ( temp void) +0:20 Function Parameters: +0:20 Function Definition: main( ( temp void) +0:20 Function Parameters: +0:? Sequence +0:20 Function Call: @main( ( temp void) +0:? Linker Objects +0:? 'anon@0' (layout( row_major std140) uniform block{layout( row_major std140) uniform float m0, layout( row_major std140) uniform 3-component vector of float m4, layout( row_major std140) uniform float m16, layout( row_major std140 offset=20) uniform 3-component vector of float m20, layout( row_major std140 offset=36) uniform 3-component vector of float m36, layout( row_major std140 offset=56) uniform 2-component vector of float m56, layout( row_major std140) uniform float m64, layout( row_major std140) uniform 2-component vector of float m68, layout( row_major std140) uniform float m76, layout( row_major std140) uniform float m80, layout( row_major std140) uniform 1-element array of 2-component vector of float m96}) + + +Linked vertex stage: + + +Shader version: 450 +0:? Sequence +0:20 Function Definition: @main( ( temp void) +0:20 Function Parameters: +0:20 Function Definition: main( ( temp void) +0:20 Function Parameters: +0:? Sequence +0:20 Function Call: @main( ( temp void) +0:? Linker Objects +0:? 'anon@0' (layout( row_major std140) uniform block{layout( row_major std140) uniform float m0, layout( row_major std140) uniform 3-component vector of float m4, layout( row_major std140) uniform float m16, layout( row_major std140 offset=20) uniform 3-component vector of float m20, layout( row_major std140 offset=36) uniform 3-component vector of float m36, layout( row_major std140 offset=56) uniform 2-component vector of float m56, layout( row_major std140) uniform float m64, layout( row_major std140) uniform 2-component vector of float m68, layout( row_major std140) uniform float m76, layout( row_major std140) uniform float m80, layout( row_major std140) uniform 1-element array of 2-component vector of float m96}) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 18 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" + Name 4 "main" + Name 6 "@main(" + Name 15 "b" + MemberName 15(b) 0 "m0" + MemberName 15(b) 1 "m4" + MemberName 15(b) 2 "m16" + MemberName 15(b) 3 "m20" + MemberName 15(b) 4 "m36" + MemberName 15(b) 5 "m56" + MemberName 15(b) 6 "m64" + MemberName 15(b) 7 "m68" + MemberName 15(b) 8 "m76" + MemberName 15(b) 9 "m80" + MemberName 15(b) 10 "m96" + Name 17 "" + Decorate 14 ArrayStride 16 + MemberDecorate 15(b) 0 Offset 0 + MemberDecorate 15(b) 1 Offset 4 + MemberDecorate 15(b) 2 Offset 16 + MemberDecorate 15(b) 3 Offset 20 + MemberDecorate 15(b) 4 Offset 36 + MemberDecorate 15(b) 5 Offset 56 + MemberDecorate 15(b) 6 Offset 64 + MemberDecorate 15(b) 7 Offset 68 + MemberDecorate 15(b) 8 Offset 76 + MemberDecorate 15(b) 9 Offset 80 + MemberDecorate 15(b) 10 Offset 96 + Decorate 15(b) Block + Decorate 17 DescriptorSet 0 + 2: TypeVoid + 3: TypeFunction 2 + 9: TypeFloat 32 + 10: TypeVector 9(float) 3 + 11: TypeVector 9(float) 2 + 12: TypeInt 32 0 + 13: 12(int) Constant 1 + 14: TypeArray 11(fvec2) 13 + 15(b): TypeStruct 9(float) 10(fvec3) 9(float) 10(fvec3) 10(fvec3) 11(fvec2) 9(float) 11(fvec2) 9(float) 9(float) 14 + 16: TypePointer Uniform 15(b) + 17: 16(ptr) Variable Uniform + 4(main): 2 Function None 3 + 5: Label + 8: 2 FunctionCall 6(@main() + Return + FunctionEnd + 6(@main(): 2 Function None 3 + 7: Label + Return + FunctionEnd diff --git a/Test/baseResults/spv.hlslOffsets.vert.out b/Test/baseResults/spv.hlslOffsets.vert.out new file mode 100644 index 00000000..c1f6cb25 --- /dev/null +++ b/Test/baseResults/spv.hlslOffsets.vert.out @@ -0,0 +1,78 @@ +spv.hlslOffsets.vert +Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. + +Shader version: 450 +0:? Sequence +0:27 Function Definition: main( ( global void) +0:27 Function Parameters: +0:? Linker Objects +0:? 'anon@0' (layout( column_major std430) buffer block{layout( column_major std430) buffer highp float m0, layout( column_major std430) buffer highp 3-component vector of float m4, layout( column_major std430) buffer highp float m16, layout( column_major std430 offset=20) buffer highp 3-component vector of float m20, layout( column_major std430) buffer highp 3-component vector of float m32, layout( column_major std430) buffer highp 2-component vector of float m48, layout( column_major std430) buffer highp 2-component vector of float m56, layout( column_major std430) buffer highp float m64, layout( column_major std430) buffer highp 2-component vector of float m68, layout( column_major std430) buffer highp float m76, layout( column_major std430) buffer highp float m80, layout( column_major std430 offset=88) buffer highp 2-component vector of float m88, layout( column_major std430) buffer highp 2-component vector of float m96, layout( column_major std430) buffer 2-component vector of double m112}) + + +Linked vertex stage: + + +Shader version: 450 +0:? Sequence +0:27 Function Definition: main( ( global void) +0:27 Function Parameters: +0:? Linker Objects +0:? 'anon@0' (layout( column_major std430) buffer block{layout( column_major std430) buffer highp float m0, layout( column_major std430) buffer highp 3-component vector of float m4, layout( column_major std430) buffer highp float m16, layout( column_major std430 offset=20) buffer highp 3-component vector of float m20, layout( column_major std430) buffer highp 3-component vector of float m32, layout( column_major std430) buffer highp 2-component vector of float m48, layout( column_major std430) buffer highp 2-component vector of float m56, layout( column_major std430) buffer highp float m64, layout( column_major std430) buffer highp 2-component vector of float m68, layout( column_major std430) buffer highp float m76, layout( column_major std430) buffer highp float m80, layout( column_major std430 offset=88) buffer highp 2-component vector of float m88, layout( column_major std430) buffer highp 2-component vector of float m96, layout( column_major std430) buffer 2-component vector of double m112}) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 14 + + Capability Shader + Capability Float64 + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" + Source GLSL 450 + Name 4 "main" + Name 11 "block" + MemberName 11(block) 0 "m0" + MemberName 11(block) 1 "m4" + MemberName 11(block) 2 "m16" + MemberName 11(block) 3 "m20" + MemberName 11(block) 4 "m32" + MemberName 11(block) 5 "m48" + MemberName 11(block) 6 "m56" + MemberName 11(block) 7 "m64" + MemberName 11(block) 8 "m68" + MemberName 11(block) 9 "m76" + MemberName 11(block) 10 "m80" + MemberName 11(block) 11 "m88" + MemberName 11(block) 12 "m96" + MemberName 11(block) 13 "m112" + Name 13 "" + MemberDecorate 11(block) 0 Offset 0 + MemberDecorate 11(block) 1 Offset 4 + MemberDecorate 11(block) 2 Offset 16 + MemberDecorate 11(block) 3 Offset 20 + MemberDecorate 11(block) 4 Offset 32 + MemberDecorate 11(block) 5 Offset 48 + MemberDecorate 11(block) 6 Offset 56 + MemberDecorate 11(block) 7 Offset 64 + MemberDecorate 11(block) 8 Offset 68 + MemberDecorate 11(block) 9 Offset 76 + MemberDecorate 11(block) 10 Offset 80 + MemberDecorate 11(block) 11 Offset 88 + MemberDecorate 11(block) 12 Offset 96 + MemberDecorate 11(block) 13 Offset 112 + Decorate 11(block) BufferBlock + Decorate 13 DescriptorSet 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 3 + 8: TypeVector 6(float) 2 + 9: TypeFloat 64 + 10: TypeVector 9(float) 2 + 11(block): TypeStruct 6(float) 7(fvec3) 6(float) 7(fvec3) 7(fvec3) 8(fvec2) 8(fvec2) 6(float) 8(fvec2) 6(float) 6(float) 8(fvec2) 8(fvec2) 10(fvec2) + 12: TypePointer Uniform 11(block) + 13: 12(ptr) Variable Uniform + 4(main): 2 Function None 3 + 5: Label + Return + FunctionEnd diff --git a/Test/hlsl.hlslOffset.vert b/Test/hlsl.hlslOffset.vert new file mode 100755 index 00000000..aa95f6a3 --- /dev/null +++ b/Test/hlsl.hlslOffset.vert @@ -0,0 +1,20 @@ +cbuffer b { + float m0; + float3 m4; + ////// + float m16; + float3 m20 : packoffset(c1.y); + ///// + float3 m36 : packoffset(c2.y); + ///// + float2 m56 : packoffset(c3.z); + ///// + float m64; + float2 m68; + float m76; + ////// + float m80; + float2 m96[1]; +}; + +void main() {} diff --git a/Test/runtests b/Test/runtests index 86ffef34..efc449d9 100755 --- a/Test/runtests +++ b/Test/runtests @@ -73,6 +73,20 @@ echo Running explicit stage test $EXE -i -S vert nosuffix > $TARGETDIR/nosuffix.out diff -b $BASEDIR/nosuffix.out $TARGETDIR/nosuffix.out || HASERROR=1 +# +# Testing --hlsl-offsets +# +echo Running hlsl offsets +$EXE -i --hlsl-offsets -H spv.hlslOffsets.vert > $TARGETDIR/spv.hlslOffsets.vert.out +diff -b $BASEDIR/spv.hlslOffsets.vert.out $TARGETDIR/spv.hlslOffsets.vert.out || HASERROR=1 + +echo Running hlsl offsets +$EXE -i --hlsl-offsets -D -e main -H hlsl.hlslOffset.vert > $TARGETDIR/hlsl.hlslOffset.vert.out +diff -b $BASEDIR/hlsl.hlslOffset.vert.out $TARGETDIR/hlsl.hlslOffset.vert.out || HASERROR=1 + +# +# Final checking +# if [ $HASERROR -eq 0 ] then echo Tests Succeeded. diff --git a/Test/spv.hlslOffsets.vert b/Test/spv.hlslOffsets.vert new file mode 100755 index 00000000..87e32a72 --- /dev/null +++ b/Test/spv.hlslOffsets.vert @@ -0,0 +1,27 @@ +#version 450 + +buffer block { + float m0; + vec3 m4; + ////// + float m16; + layout(offset=20) vec3 m20; + ///// + vec3 m32; + ///// + vec2 m48; + vec2 m56; + //// + float m64; + vec2 m68; + float m76; + ////// + float m80; + layout(offset=88) vec2 m88; + ////// + vec2 m96; + /////// + dvec2 m112; +}; + +void main() {} \ No newline at end of file diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index 2704df3a..8632beaf 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -2,5 +2,5 @@ // For the version, it uses the latest git tag followed by the number of commits. // For the date, it uses the current date (when then script is run). -#define GLSLANG_REVISION "Overload400-PrecQual.1974" -#define GLSLANG_DATE "04-Apr-2017" +#define GLSLANG_REVISION "Overload400-PrecQual.1978" +#define GLSLANG_DATE "05-Apr-2017" diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index 5a8f679d..f7596d9f 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -726,6 +726,8 @@ bool ProcessDeferred( intermediate.setSpv(spvVersion); if (spvVersion.vulkan >= 100) intermediate.setOriginUpperLeft(); + if (messages & EShMsgHlslOffsets) // source-language independent + intermediate.setHlslOffsets(); SetupBuiltinSymbolTable(version, profile, spvVersion, source); TSymbolTable* cachedTable = SharedSymbolTables[MapVersionToIndex(version)] diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp index 0328009d..4bb29510 100644 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -1047,9 +1047,9 @@ unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains const int baseAlignmentVec4Std140 = 16; -// Return the size and alignment of a scalar. +// Return the size and alignment of a component of the given type. // The size is returned in the 'size' parameter -// Return value is the alignment of the type. +// Return value is the alignment.. int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size) { switch (type.getBasicType()) { @@ -1219,4 +1219,14 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, b return baseAlignmentVec4Std140; } +// To aid the basic HLSL rule about crossing vec4 boundaries. +bool TIntermediate::improperStraddle(const TType& type, int size, int offset) +{ + if (! type.isVector() || type.isArray()) + return false; + + return size <= 16 ? offset / 16 != (offset + size - 1) / 16 + : offset % 16 != 0; +} + } // end namespace glslang diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 5460dd5f..2cd912b0 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -177,7 +177,8 @@ public: shiftSsboBinding(0), autoMapBindings(false), flattenUniformArrays(false), - useUnknownFormat(false) + useUnknownFormat(false), + hlslOffsets(false) { localSize[0] = 1; localSize[1] = 1; @@ -216,6 +217,8 @@ public: bool getFlattenUniformArrays() const { return flattenUniformArrays; } void setNoStorageFormat(bool b) { useUnknownFormat = b; } bool getNoStorageFormat() const { return useUnknownFormat; } + void setHlslOffsets() { hlslOffsets = true; } + bool usingHlslOFfsets() const { return hlslOffsets; } void setVersion(int v) { version = v; } int getVersion() const { return version; } @@ -413,7 +416,9 @@ public: } int addXfbBufferOffset(const TType&); unsigned int computeTypeXfbSize(const TType&, bool& containsDouble) const; + static int getBaseAlignmentScalar(const TType&, int& size); static int getBaseAlignment(const TType&, int& size, int& stride, bool std140, bool rowMajor); + static bool improperStraddle(const TType& type, int size, int offset); bool promote(TIntermOperator*); #ifdef NV_EXTENSIONS @@ -443,7 +448,6 @@ protected: void inOutLocationCheck(TInfoSink&); TIntermSequence& findLinkerObjects() const; bool userOutputUsed() const; - static int getBaseAlignmentScalar(const TType&, int& size); bool isSpecializationOperation(const TIntermOperator&) const; bool promoteUnary(TIntermUnary&); bool promoteBinary(TIntermBinary&); @@ -499,6 +503,7 @@ protected: bool autoMapBindings; bool flattenUniformArrays; bool useUnknownFormat; + bool hlslOffsets; typedef std::list TGraph; TGraph callGraph; diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index 8d8abd77..ace20cbc 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -147,6 +147,7 @@ enum EShMessages { EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics EShMsgCascadingErrors = (1 << 7), // get cascading errors; risks error-recovery issues, instead of an early exit EShMsgKeepUncalled = (1 << 8), // for testing, don't eliminate uncalled functions + EShMsgHlslOffsets = (1 << 9), // allow block offsets to follow HLSL rules instead of GLSL rules }; //