diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index 4fce3ed2be90e26e87e178082fd33a1e5f0603f8..a797295e9345d5c1e960e10a63e688b0ca78eb4a 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -105,6 +105,7 @@ void GenerateResources(TBuiltInResource& resources) resources.maxVaryingVectors = 8; resources.maxFragmentUniformVectors = 16; resources.maxVertexOutputVectors = 16; + resources.maxFragmentInputVectors = 15; resources.minProgramTexelOffset = -8; resources.maxProgramTexelOffset = 7; } diff --git a/Test/300.vert b/Test/300.vert new file mode 100644 index 0000000000000000000000000000000000000000..96b55d0a0b8f9d72b9d9784fae165403894d1e45 --- /dev/null +++ b/Test/300.vert @@ -0,0 +1,31 @@ +#version 300 es + +uniform mat4x3 m43; +uniform mat3x3 m33; +uniform mat4x4 m44; + +in vec3 v3; +in vec2 v2; + +void main() +{ + int id = gl_VertexID + gl_InstanceID; + + int c0 = gl_MaxVertexAttribs; + int c1 = gl_MaxVertexUniformVectors; + int c2 = gl_MaxVertexOutputVectors; + int c3 = gl_MaxFragmentInputVectors; + int c4 = gl_MaxVertexTextureImageUnits; + int c5 = gl_MaxCombinedTextureImageUnits; + int c6 = gl_MaxTextureImageUnits; + int c7 = gl_MaxFragmentUniformVectors; + int c8 = gl_MaxDrawBuffers; + int c9 = gl_MinProgramTexelOffset; + int c10 = gl_MaxProgramTexelOffset; + + mat3x4 tm = transpose(m43); + highp float dm = determinant(m44); + mat3x3 im = inverse(m33); + + mat3x2 op = outerProduct(v2, v3); +} diff --git a/Test/testlist b/Test/testlist index 7a2be1bff7168d10c53eb55bc927c3ffd5233afb..fafa6bb58b4acc81ba125d300b6359ee5db9b5ed 100644 --- a/Test/testlist +++ b/Test/testlist @@ -20,3 +20,4 @@ pointCoord.frag array.frag array100.frag comment.frag +300.vert diff --git a/glslang/Include/ResourceLimits.h b/glslang/Include/ResourceLimits.h index faf61268111125c7b167277802441a1483badd19..bc60592ead211f5968128bd38d0f83d824696c66 100644 --- a/glslang/Include/ResourceLimits.h +++ b/glslang/Include/ResourceLimits.h @@ -54,6 +54,7 @@ struct TBuiltInResource { int maxVaryingVectors; int maxFragmentUniformVectors; int maxVertexOutputVectors; + int maxFragmentInputVectors; int minProgramTexelOffset; int maxProgramTexelOffset; }; diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h index 72825f2f31c32c97034017353f0f53f18185b665..7b9b981fb9affaa1d1b8a516966f11fdc42ff143 100644 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -169,6 +169,10 @@ enum TOperator { EOpFwidth, // Fragment only EOpMatrixTimesMatrix, + EOpOuterProduct, + EOpDeterminant, + EOpMatrixInverse, + EOpTranspose, EOpAny, EOpAll, diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp index 41b356f4f7b8bb102c390475b137528a8effd872..5dac7c1e9f4852087bd8644f987e12c08724b31a 100644 --- a/glslang/MachineIndependent/Initialize.cpp +++ b/glslang/MachineIndependent/Initialize.cpp @@ -283,6 +283,38 @@ void TBuiltIns::initialize(int version, EProfile profile) s.append(TString("mat3 matrixCompMult(mat3 x, mat3 y);")); s.append(TString("mat4 matrixCompMult(mat4 x, mat4 y);")); + if (version >= 120) { + s.append(TString("mat2 outerProduct(vec2 c, vec2 r);")); + s.append(TString("mat3 outerProduct(vec3 c, vec3 r);")); + s.append(TString("mat4 outerProduct(vec4 c, vec4 r);")); + s.append(TString("mat2x3 outerProduct(vec3 c, vec2 r);")); + s.append(TString("mat3x2 outerProduct(vec2 c, vec3 r);")); + s.append(TString("mat2x4 outerProduct(vec4 c, vec2 r);")); + s.append(TString("mat4x2 outerProduct(vec2 c, vec4 r);")); + s.append(TString("mat3x4 outerProduct(vec4 c, vec3 r);")); + s.append(TString("mat4x3 outerProduct(vec3 c, vec4 r);")); + + s.append(TString("mat2 transpose(mat2 m);")); + s.append(TString("mat3 transpose(mat3 m);")); + s.append(TString("mat4 transpose(mat4 m);")); + s.append(TString("mat2x3 transpose(mat3x2 m);")); + s.append(TString("mat3x2 transpose(mat2x3 m);")); + s.append(TString("mat2x4 transpose(mat4x2 m);")); + s.append(TString("mat4x2 transpose(mat2x4 m);")); + s.append(TString("mat3x4 transpose(mat4x3 m);")); + s.append(TString("mat4x3 transpose(mat3x4 m);")); + + if (version >= 150) { + s.append(TString("float determinant(mat2 m);")); + s.append(TString("float determinant(mat3 m);")); + s.append(TString("float determinant(mat4 m);")); + + s.append(TString("mat2 inverse(mat2 m);")); + s.append(TString("mat3 inverse(mat3 m);")); + s.append(TString("mat4 inverse(mat4 m);")); + } + } + // // Vector relational functions. // @@ -795,6 +827,9 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexOutputVectors = %d;", resources.maxVertexOutputVectors); s.append(TString(builtInConstant)); + snprintf(builtInConstant, maxSize, "const mediump int gl_MaxFragmentInputVectors = %d;", resources.maxFragmentInputVectors); + s.append(TString(builtInConstant)); + snprintf(builtInConstant, maxSize, "const mediump int gl_MinProgramTexelOffset = %d;", resources.minProgramTexelOffset); s.append(TString(builtInConstant)); @@ -964,6 +999,15 @@ void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymb symbolTable.relateToOperator("not", EOpVectorLogicalNot); symbolTable.relateToOperator("matrixCompMult", EOpMul); + if (version >= 120) { + symbolTable.relateToOperator("outerProduct", EOpOuterProduct); + symbolTable.relateToOperator("transpose", EOpTranspose); + if (version >= 150) { + symbolTable.relateToOperator("determinant", EOpDeterminant); + symbolTable.relateToOperator("inverse", EOpMatrixInverse); + } + } + symbolTable.relateToOperator("mod", EOpMod); symbolTable.relateToOperator("equal", EOpVectorEqual); diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index d13f09948d5554f8d48676225315c5cdd4a4a260..551454c5e50c8d99757371e09c34910e82d6bcb9 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -1202,6 +1202,18 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod } returnType = TType(getType().getBasicType(), EvqConst, 0, getMatrixRows(), node->getMatrixCols()); break; + case EOpOuterProduct: + // TODO: functionality >= 120 + break; + case EOpDeterminant: + // TODO: functionality >= 150 + break; + case EOpMatrixInverse: + // TODO: functionality >= 150 + break; + case EOpTranspose: + // TODO: functionality >= 120 + break; case EOpDiv: tempConstArray = new constUnion[objectSize]; for (int i = 0; i < objectSize; i++) { diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp index 0d4fc27f27e8492ab96afc00923b35d20f434413..556c0ac5738c94e49065ce7316cb3112faa24507 100644 --- a/glslang/MachineIndependent/intermOut.cpp +++ b/glslang/MachineIndependent/intermOut.cpp @@ -46,7 +46,7 @@ // // -// Use this class to carry along data from node to node in +// Use this class to carry along data from node to node in // the traversal // class TOutputTraverser : public TIntermTraverser { @@ -80,7 +80,7 @@ TString TType::getCompleteString() const snprintf(p, end - p, "%s", getBasicString()); return TString(buf); -} +} // // Helper functions for printing, not part of traversing. @@ -91,7 +91,7 @@ void OutputTreeText(TInfoSink& infoSink, TIntermNode* node, const int depth) int i; infoSink.debug << FormatSourceLoc(node->getLine()); - + for (i = 0; i < depth; ++i) infoSink.debug << " "; } @@ -135,7 +135,7 @@ bool OutputBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it case EOpVectorTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break; case EOpVectorTimesScalarAssign: out.debug << "vector scale second child into first child"; break; case EOpMatrixTimesScalarAssign: out.debug << "matrix scale second child into first child"; break; - case EOpMatrixTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break; + case EOpMatrixTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break; case EOpDivAssign: out.debug << "divide second child into first child"; break; case EOpModAssign: out.debug << "mod second child into first child"; break; case EOpAndAssign: out.debug << "and second child into first child"; break; @@ -192,7 +192,7 @@ bool OutputUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it) OutputTreeText(out, node, oit->depth); - switch (node->getOp()) { + switch (node->getOp()) { case EOpNegative: out.debug << "Negate value"; break; case EOpVectorLogicalNot: case EOpLogicalNot: out.debug << "Negate conditional"; break; @@ -234,10 +234,13 @@ bool OutputUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it) case EOpLength: out.debug << "length"; break; case EOpNormalize: out.debug << "normalize"; break; - case EOpDPdx: out.debug << "dPdx"; break; - case EOpDPdy: out.debug << "dPdy"; break; - case EOpFwidth: out.debug << "fwidth"; break; - + case EOpDPdx: out.debug << "dPdx"; break; + case EOpDPdy: out.debug << "dPdy"; break; + case EOpFwidth: out.debug << "fwidth"; break; + case EOpDeterminant: out.debug << "determinant"; break; + case EOpMatrixInverse: out.debug << "inverse"; break; + case EOpTranspose: out.debug << "transpose"; break; + case EOpAny: out.debug << "any"; break; case EOpAll: out.debug << "all"; break; @@ -269,7 +272,7 @@ bool OutputAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTravers case EOpFunction: out.debug << "Function Definition: " << node->getName(); break; case EOpFunctionCall: out.debug << "Function Call: " << node->getName(); break; case EOpParameters: out.debug << "Function Parameters: "; break; - + case EOpConstructFloat: out.debug << "Construct float"; break; case EOpConstructVec2: out.debug << "Construct vec2"; break; case EOpConstructVec3: out.debug << "Construct vec3"; break; @@ -301,7 +304,7 @@ bool OutputAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTravers case EOpConstructDMat4x3: out.debug << "Construct dmat4x3"; break; case EOpConstructDMat4x4: out.debug << "Construct dmat4"; break; case EOpConstructStruct: out.debug << "Construct structure"; break; - + case EOpLessThan: out.debug << "Compare Less Than"; break; case EOpGreaterThan: out.debug << "Compare Greater Than"; break; case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break; @@ -328,13 +331,14 @@ bool OutputAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTravers case EOpReflect: out.debug << "reflect"; break; case EOpRefract: out.debug << "refract"; break; case EOpMul: out.debug << "component-wise multiply"; break; + case EOpOuterProduct: out.debug << "outer product"; break; default: out.debug.message(EPrefixError, "Bad aggregation op"); } if (node->getOp() != EOpSequence && node->getOp() != EOpParameters) out.debug << " (" << node->getCompleteString() << ")"; - + out.debug << "\n"; return true; @@ -349,9 +353,9 @@ bool OutputSelection(bool /* preVisit */, TIntermSelection* node, TIntermTravers out.debug << "Test condition and select"; out.debug << " (" << node->getCompleteString() << ")\n"; - + ++oit->depth; - + OutputTreeText(oit->infoSink, node, oit->depth); out.debug << "Condition\n"; node->getCondition()->traverse(it); @@ -362,13 +366,13 @@ bool OutputSelection(bool /* preVisit */, TIntermSelection* node, TIntermTravers node->getTrueBlock()->traverse(it); } else out.debug << "true case is null\n"; - + if (node->getFalseBlock()) { OutputTreeText(oit->infoSink, node, oit->depth); out.debug << "false case\n"; node->getFalseBlock()->traverse(it); } - + --oit->depth; return false; @@ -378,7 +382,7 @@ void OutputConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it) { TOutputTraverser* oit = static_cast<TOutputTraverser*>(it); TInfoSink& out = oit->infoSink; - + int size = node->getType().getObjectSize(); for (int i = 0; i < size; i++) { @@ -400,7 +404,7 @@ void OutputConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it) char buf[maxSize]; snprintf(buf, maxSize, "%f (%s)", node->getUnionArrayPointer()[i].getFConst(), "const float"); - out.debug << buf << "\n"; + out.debug << buf << "\n"; } break; case EbtDouble: @@ -409,7 +413,7 @@ void OutputConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it) char buf[maxSize]; snprintf(buf, maxSize, "%f (%s)", node->getUnionArrayPointer()[i].getDConst(), "const double"); - out.debug << buf << "\n"; + out.debug << buf << "\n"; } break; case EbtInt: @@ -421,7 +425,7 @@ void OutputConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it) out.debug << buf << "\n"; } break; - default: + default: out.info.message(EPrefixInternalError, "Unknown constant", node->getLine()); break; } @@ -434,21 +438,21 @@ bool OutputLoop(bool /* preVisit */, TIntermLoop* node, TIntermTraverser* it) TInfoSink& out = oit->infoSink; OutputTreeText(out, node, oit->depth); - + out.debug << "Loop with condition "; if (! node->testFirst()) out.debug << "not "; out.debug << "tested first\n"; - + ++oit->depth; - + OutputTreeText(oit->infoSink, node, oit->depth); if (node->getTest()) { out.debug << "Loop Condition\n"; node->getTest()->traverse(it); } else out.debug << "No loop condition\n"; - + OutputTreeText(oit->infoSink, node, oit->depth); if (node->getBody()) { out.debug << "Loop Body\n";