From 08d182470be9f41e11d21a4054f7eb0bdcd253d9 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Fri, 20 Dec 2013 18:36:27 +0000 Subject: [PATCH] Add array sizing/checking/overlapping semantics for tessellation inputs. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24594 e7fa87d3-cd2b-0410-9028-fcbf551c1848 --- Test/400.tesc | 17 +++++- Test/400.tese | 29 +++++++++- Test/baseResults/150.tesc.out | 60 ++++++++++++++++++++- Test/runtests | 1 + glslang/Include/revision.h | 4 +- glslang/MachineIndependent/ParseHelper.cpp | 46 ++++++++++++---- glslang/MachineIndependent/ParseHelper.h | 1 + glslang/MachineIndependent/linkValidate.cpp | 15 ++++-- 8 files changed, 152 insertions(+), 21 deletions(-) diff --git a/Test/400.tesc b/Test/400.tesc index e4463acd..b7aea869 100644 --- a/Test/400.tesc +++ b/Test/400.tesc @@ -42,4 +42,19 @@ layout(vertices = 5) out; // ERROR void foo() { gl_out[4].gl_PointSize; // ERROR -} \ No newline at end of file +} + +in vec2 ina; // ERROR, not array +in vec2 inb[]; +in vec2 inc[18]; // ERROR, wrong size +in vec2 ind[gl_MaxPatchVertices]; + +#extension GL_ARB_separate_shader_objects : enable + +layout(location = 3) in vec4 ivla[]; +layout(location = 4) in vec4 ivlb[]; +layout(location = 4) in vec4 ivlc[]; // ERROR + +layout(location = 3) out vec4 ovla[]; +layout(location = 4) out vec4 ovlb[]; +layout(location = 4) out vec4 ovlc[]; // ERROR diff --git a/Test/400.tese b/Test/400.tese index 2933493b..42e3c4ca 100644 --- a/Test/400.tese +++ b/Test/400.tese @@ -59,7 +59,7 @@ float gl_ClipDistance[1]; in gl_PerVertex { float gl_ClipDistance[1]; -} gl_in[gl_MaxPatchVertices]; +} gl_in[]; layout(quads, cw) out; // ERROR layout(triangles) out; // ERROR @@ -70,3 +70,30 @@ layout(equal_spacing) out; // ERROR layout(fractional_even_spacing) out; // ERROR layout(point_mode) out; // ERROR +in vec2 ina; // ERROR, not array +in vec2 inb[]; +in vec2 inc[18]; // ERROR, wrong size +in vec2 ind[gl_MaxPatchVertices]; + +in testbla { + int f; +} bla; // ERROR, not array + +in testblb { + int f; +} blb[]; + +in testblc { + int f; +} blc[18]; // ERROR wrong size + +in testbld { + int f; +} bld[gl_MaxPatchVertices]; + +layout(location = 23) in vec4 ivla[]; +layout(location = 24) in vec4 ivlb[]; +layout(location = 24) in vec4 ivlc[]; // ERROR + +layout(location = 23) out vec4 ovla[2]; +layout(location = 24) out vec4 ovlb[2]; // ERROR diff --git a/Test/baseResults/150.tesc.out b/Test/baseResults/150.tesc.out index b7fbe274..1f4c8913 100644 --- a/Test/baseResults/150.tesc.out +++ b/Test/baseResults/150.tesc.out @@ -219,7 +219,11 @@ ERROR: 0:10: 'patch' : can only use on output in tessellation-control shader ERROR: 0:39: 'vertices' : can only apply to 'out' ERROR: 0:40: 'vertices' : cannot change previously set layout value ERROR: 0:44: '[' : array index out of range '4' -ERROR: 7 compilation errors. No code generated. +ERROR: 0:47: 'in' : type must be an array: ina +ERROR: 0:49: '[]' : tessellation input array size must be gl_MaxPatchVertices or unsized +ERROR: 0:56: 'location' : repeated use of location 4 +ERROR: 0:60: 'location' : repeated use of location 4 +ERROR: 11 compilation errors. No code generated. vertices = 4 @@ -337,6 +341,16 @@ ERROR: node is still EOpNull! 0:? 'patchIn' (patch in 4-component vector of float) 0:? 'patchOut' (patch out 4-component vector of float) 0:? 'gl_out' (out 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance}) +0:? 'ina' (in 2-component vector of float) +0:? 'inb' (in 32-element array of 2-component vector of float) +0:? 'inc' (in 32-element array of 2-component vector of float) +0:? 'ind' (in 32-element array of 2-component vector of float) +0:? 'ivla' (layout(location=3 ) in 32-element array of 4-component vector of float) +0:? 'ivlb' (layout(location=4 ) in 32-element array of 4-component vector of float) +0:? 'ivlc' (layout(location=4 ) in 32-element array of 4-component vector of float) +0:? 'ovla' (layout(location=3 ) out 4-element array of 4-component vector of float) +0:? 'ovlb' (layout(location=4 ) out 4-element array of 4-component vector of float) +0:? 'ovlc' (layout(location=4 ) out 4-element array of 4-component vector of float) 400.tese Warning, version 400 is not yet complete; some version-specific features are present, but many are missing. @@ -363,7 +377,13 @@ ERROR: 0:68: 'fractional_odd_spacing' : can only apply to 'in' ERROR: 0:69: 'equal_spacing' : can only apply to 'in' ERROR: 0:70: 'fractional_even_spacing' : can only apply to 'in' ERROR: 0:71: 'point_mode' : can only apply to 'in' -ERROR: 23 compilation errors. No code generated. +ERROR: 0:73: 'in' : type must be an array: ina +ERROR: 0:75: '[]' : tessellation input array size must be gl_MaxPatchVertices or unsized +ERROR: 0:78: 'in' : type must be an array: bla +ERROR: 0:86: '[]' : tessellation input array size must be gl_MaxPatchVertices or unsized +ERROR: 0:96: 'location' : repeated use of location 24 +ERROR: 0:99: 'location' : repeated use of location 24 +ERROR: 29 compilation errors. No code generated. input primitive = quads @@ -469,6 +489,19 @@ ERROR: node is still EOpNull! 0:? 'badp3' (noperspective patch in 4-component vector of float) 0:? 'badp4' (patch sample in 3-component vector of float) 0:? 'gl_in' (in 32-element array of block{gl_ClipDistance}) +0:? 'ina' (in 2-component vector of float) +0:? 'inb' (in 32-element array of 2-component vector of float) +0:? 'inc' (in 32-element array of 2-component vector of float) +0:? 'ind' (in 32-element array of 2-component vector of float) +0:? 'bla' (in block{f}) +0:? 'blb' (in 32-element array of block{f}) +0:? 'blc' (in 32-element array of block{f}) +0:? 'bld' (in 32-element array of block{f}) +0:? 'ivla' (layout(location=23 ) in 32-element array of 4-component vector of float) +0:? 'ivlb' (layout(location=24 ) in 32-element array of 4-component vector of float) +0:? 'ivlc' (layout(location=24 ) in 32-element array of 4-component vector of float) +0:? 'ovla' (layout(location=23 ) out 2-element array of 4-component vector of float) +0:? 'ovlb' (layout(location=24 ) out 2-element array of 4-component vector of float) 410.tesc Warning, version 400 is not yet complete; some version-specific features are present, but many are missing. @@ -1036,6 +1069,16 @@ vertices = 4 0:? 'patchOut' (patch out 4-component vector of float) 0:? 'gl_out' (out 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance}) 0:? 'patchIn' (patch in 4-component vector of float) +0:? 'ina' (in 2-component vector of float) +0:? 'inb' (in 32-element array of 2-component vector of float) +0:? 'inc' (in 32-element array of 2-component vector of float) +0:? 'ind' (in 32-element array of 2-component vector of float) +0:? 'ivla' (layout(location=3 ) in 32-element array of 4-component vector of float) +0:? 'ivlb' (layout(location=4 ) in 32-element array of 4-component vector of float) +0:? 'ivlc' (layout(location=4 ) in 32-element array of 4-component vector of float) +0:? 'ovla' (layout(location=3 ) out 4-element array of 4-component vector of float) +0:? 'ovlb' (layout(location=4 ) out 4-element array of 4-component vector of float) +0:? 'ovlc' (layout(location=4 ) out 4-element array of 4-component vector of float) 0:? 'a' (out 3-element array of int) 0:? 'outb' (out 5-element array of int) 0:? 'outc' (out 4-element array of int) @@ -1307,6 +1350,19 @@ ERROR: node is still EOpNull! 0:? 'badp3' (noperspective patch in 4-component vector of float) 0:? 'badp4' (patch sample in 3-component vector of float) 0:? 'gl_in' (in 32-element array of block{gl_ClipDistance}) +0:? 'ina' (in 2-component vector of float) +0:? 'inb' (in 32-element array of 2-component vector of float) +0:? 'inc' (in 32-element array of 2-component vector of float) +0:? 'ind' (in 32-element array of 2-component vector of float) +0:? 'bla' (in block{f}) +0:? 'blb' (in 32-element array of block{f}) +0:? 'blc' (in 32-element array of block{f}) +0:? 'bld' (in 32-element array of block{f}) +0:? 'ivla' (layout(location=23 ) in 32-element array of 4-component vector of float) +0:? 'ivlb' (layout(location=24 ) in 32-element array of 4-component vector of float) +0:? 'ivlc' (layout(location=24 ) in 32-element array of 4-component vector of float) +0:? 'ovla' (layout(location=23 ) out 2-element array of 4-component vector of float) +0:? 'ovlb' (layout(location=24 ) out 2-element array of 4-component vector of float) 0:? 'a' (const 2X2 matrix of float) 0:? 1.000000 0:? 0.000000 diff --git a/Test/runtests b/Test/runtests index 5604bbb4..ab800e7d 100755 --- a/Test/runtests +++ b/Test/runtests @@ -3,6 +3,7 @@ TARGETDIR=localResults BASEDIR=baseResults EXE=./glslangValidator.exe +mkdir -p localResults # # configuration file tests diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index 579257d7..8a78e7f7 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -9,5 +9,5 @@ // source have to figure out how to create revision.h just to get a build // going. However, if it is not updated, it can be a version behind. -#define GLSLANG_REVISION "24551" -#define GLSLANG_DATE "2013/12/17 20:06:24" +#define GLSLANG_REVISION "24569" +#define GLSLANG_DATE "2013/12/18 11:47:12" diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index c13c1da5..52d898c0 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -518,9 +518,9 @@ void TParseContext::handleIndexLimits(TSourceLoc loc, TIntermTyped* base, TInter (! limits.generalAttributeMatrixVectorIndexing && base->getQualifier().isPipeInput() && language == EShLangVertex && (base->getType().isMatrix() || base->getType().isVector())) || (! limits.generalConstantMatrixVectorIndexing && base->getAsConstantUnion()) || (! limits.generalVariableIndexing && ! base->getType().getQualifier().isUniform() && - ! base->getType().getQualifier().isPipeInput() && - ! base->getType().getQualifier().isPipeOutput() && - base->getType().getQualifier().storage != EvqConst) || + ! base->getType().getQualifier().isPipeInput() && + ! base->getType().getQualifier().isPipeOutput() && + base->getType().getQualifier().storage != EvqConst) || (! limits.generalVaryingIndexing && (base->getType().getQualifier().isPipeInput() || base->getType().getQualifier().isPipeOutput()))) { // it's too early to know what the inductive variables are, save it for post processing @@ -536,14 +536,35 @@ bool TParseContext::isIoResizeArray(const TType& type) const (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut && ! type.getQualifier().patch)); } +// If an array is not isIoResizeArray() but is an io array, make sure it has the right size +void TParseContext::fixIoArraySize(TSourceLoc loc, TType& type) +{ + if (! type.isArray() || type.getQualifier().patch || symbolTable.atBuiltInLevel()) + return; + + assert(! isIoResizeArray(type)); + + if (type.getQualifier().storage != EvqVaryingIn || type.getQualifier().patch) + return; + + if (language == EShLangTessControl || language == EShLangTessEvaluation) { + if (type.getArraySize() != resources.maxPatchVertices) { + if (type.getArraySize() != 0) + error(loc, "tessellation input array size must be gl_MaxPatchVertices or unsized", "[]", ""); + type.changeArraySize(resources.maxPatchVertices); + } + } +} + // Issue any errors if the non-array object is missing arrayness WRT // shader I/O that has array requirements. // All arrayness checking is handled in array paths, this is for void TParseContext::ioArrayCheck(TSourceLoc loc, const TType& type, const TString& identifier) { if (! type.isArray() && ! symbolTable.atBuiltInLevel()) { - if ((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) || - (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut && ! type.getQualifier().patch)) + if ((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) || + (language == EShLangTessControl && (type.getQualifier().storage == EvqVaryingOut || type.getQualifier().storage == EvqVaryingIn) && ! type.getQualifier().patch) || + (language == EShLangTessEvaluation && type.getQualifier().storage == EvqVaryingIn && ! type.getQualifier().patch)) error(loc, "type must be an array:", type.getStorageQualifierString(), identifier.c_str()); } } @@ -2067,9 +2088,12 @@ void TParseContext::declareArray(TSourceLoc loc, TString& identifier, const TTyp symbolTable.insert(*symbol); newDeclaration = true; - if (! symbolTable.atBuiltInLevel() && isIoResizeArray(type)) { - ioArraySymbolResizeList.push_back(symbol); - checkIoArraysConsistency(loc, true); + if (! symbolTable.atBuiltInLevel()) { + if (isIoResizeArray(type)) { + ioArraySymbolResizeList.push_back(symbol); + checkIoArraysConsistency(loc, true); + } else + fixIoArraySize(loc, symbol->getWritableType()); } return; @@ -2410,7 +2434,8 @@ void TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& newTypeList if (isIoResizeArray(block->getType())) { ioArraySymbolResizeList.push_back(block); checkIoArraysConsistency(loc, true); - } + } else if (block->getType().isArray()) + fixIoArraySize(loc, block->getWritableType()); // Save it in the AST for linker use. intermediate.addSymbolLinkageNode(linkage, *block); @@ -3754,7 +3779,8 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr if (isIoResizeArray(blockType)) { ioArraySymbolResizeList.push_back(&variable); checkIoArraysConsistency(loc, true); - } + } else + fixIoArraySize(loc, variable.getWritableType()); // Save it in the AST for linker use. intermediate.addSymbolLinkageNode(linkage, variable); diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 50acbcfb..5978251e 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -86,6 +86,7 @@ public: void handleIndexLimits(TSourceLoc, TIntermTyped* base, TIntermTyped* index); bool isIoResizeArray(const TType&) const; + void fixIoArraySize(TSourceLoc, TType&); void ioArrayCheck(TSourceLoc, const TType&, const TString& identifier); void handleIoResizeArrayAccess(TSourceLoc, TIntermTyped* base); void checkIoArraysConsistency(TSourceLoc, bool tailOnly = false); diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp index 3e4b1fd4..a7b4298a 100644 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -500,9 +500,10 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ else size = 1; } else { - if (type.isArray() && - (language == EShLangGeometry && qualifier.isPipeInput() || - (language == EShLangTessControl && qualifier.isPipeOutput() && ! qualifier.patch))) { + if (type.isArray() && ! qualifier.patch && + (language == EShLangGeometry && qualifier.isPipeInput()) || + language == EShLangTessControl || + (language == EShLangTessEvaluation && qualifier.isPipeInput())) { TType elementType(type, 0); size = computeTypeLocationSize(elementType); } else @@ -534,8 +535,12 @@ int TIntermediate::computeTypeLocationSize(const TType& type) // "If the declared input is an array of size n and each element takes m locations, it will be assigned m * n // consecutive locations..." if (type.isArray()) { - TType elementType(type, 0); - return type.getArraySize() * computeTypeLocationSize(elementType); + TType elementType(type, 0); + if (type.getArraySize() == 0) { + // TODO: are there valid cases of having an unsized array with a location? If so, running this code too early. + return computeTypeLocationSize(elementType); + } else + return type.getArraySize() * computeTypeLocationSize(elementType); } // "The locations consumed by block and structure members are determined by applying the rules above