diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index ec63d63d..d9d3555e 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -1366,7 +1366,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt { // for scalar dot product, use multiply glslang::TIntermSequence& glslangOperands = node->getSequence(); - if (! glslangOperands[0]->getAsTyped()->isVector()) + if (glslangOperands[0]->getAsTyped()->getVectorSize() == 1) binOp = glslang::EOpMul; break; } @@ -2750,7 +2750,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv break; case glslang::EOpVectorTimesScalar: case glslang::EOpVectorTimesScalarAssign: - if (isFloat) { + if (isFloat && (builder.isVector(left) || builder.isVector(right))) { if (builder.isVector(right)) std::swap(left, right); assert(builder.isScalar(right)); @@ -4096,7 +4096,7 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla glslang::TVector::const_iterator iter; for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter) spvConsts.push_back(createSpvConstantFromConstUnionArray(*iter->type, consts, nextConst, false)); - } else if (glslangType.isVector()) { + } else if (glslangType.getVectorSize() > 1) { for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) { bool zero = nextConst >= consts.size(); switch (glslangType.getBasicType()) { diff --git a/Test/baseResults/hlsl.float1.frag.out b/Test/baseResults/hlsl.float1.frag.out new file mode 100755 index 00000000..ce6ea59e --- /dev/null +++ b/Test/baseResults/hlsl.float1.frag.out @@ -0,0 +1,100 @@ +hlsl.float1.frag +Shader version: 100 +gl_FragCoord origin is upper left +0:? Sequence +0:1 move second child to first child (temp 1-component vector of float) +0:1 'f1' (temp 1-component vector of float) +0:1 Constant: +0:1 1.000000 +0:2 move second child to first child (temp float) +0:2 'scalar' (temp float) +0:2 Constant: +0:2 2.000000 +0:8 Function Definition: ShaderFunction(vf1;f1; (temp 1-component vector of float) +0:5 Function Parameters: +0:5 'inFloat1' (temp 1-component vector of float) +0:5 'inScalar' (temp float) +0:? Sequence +0:6 Branch: Return with expression +0:6 add (temp 1-component vector of float) +0:6 vector-scale (temp 1-component vector of float) +0:6 'f1' (temp 1-component vector of float) +0:6 'scalar' (temp float) +0:6 vector-scale (temp 1-component vector of float) +0:6 'inFloat1' (temp 1-component vector of float) +0:6 'inScalar' (temp float) +0:? Linker Objects +0:? 'f1' (temp 1-component vector of float) +0:? 'scalar' (temp float) + + +Linked fragment stage: + + +Shader version: 100 +gl_FragCoord origin is upper left +0:? Sequence +0:1 move second child to first child (temp 1-component vector of float) +0:1 'f1' (temp 1-component vector of float) +0:1 Constant: +0:1 1.000000 +0:2 move second child to first child (temp float) +0:2 'scalar' (temp float) +0:2 Constant: +0:2 2.000000 +0:8 Function Definition: ShaderFunction(vf1;f1; (temp 1-component vector of float) +0:5 Function Parameters: +0:5 'inFloat1' (temp 1-component vector of float) +0:5 'inScalar' (temp float) +0:? Sequence +0:6 Branch: Return with expression +0:6 add (temp 1-component vector of float) +0:6 vector-scale (temp 1-component vector of float) +0:6 'f1' (temp 1-component vector of float) +0:6 'scalar' (temp float) +0:6 vector-scale (temp 1-component vector of float) +0:6 'inFloat1' (temp 1-component vector of float) +0:6 'inScalar' (temp float) +0:? Linker Objects +0:? 'f1' (temp 1-component vector of float) +0:? 'scalar' (temp float) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 24 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "PixelShaderFunction" + ExecutionMode 4 OriginUpperLeft + Source HLSL 100 + Name 4 "PixelShaderFunction" + Name 11 "ShaderFunction(vf1;f1;" + Name 9 "inFloat1" + Name 10 "inScalar" + Name 13 "f1" + Name 15 "scalar" + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypePointer Function 6(float) + 8: TypeFunction 6(float) 7(ptr) 7(ptr) +4(PixelShaderFunction): 2 Function None 3 + 5: Label + FunctionEnd +11(ShaderFunction(vf1;f1;): 6(float) Function None 8 + 9(inFloat1): 7(ptr) FunctionParameter + 10(inScalar): 7(ptr) FunctionParameter + 12: Label + 13(f1): 7(ptr) Variable Function + 15(scalar): 7(ptr) Variable Function + 14: 6(float) Load 13(f1) + 16: 6(float) Load 15(scalar) + 17: 6(float) IMul 14 16 + 18: 6(float) Load 9(inFloat1) + 19: 6(float) Load 10(inScalar) + 20: 6(float) IMul 18 19 + 21: 6(float) FAdd 17 20 + ReturnValue 21 + FunctionEnd diff --git a/Test/hlsl.float1.frag b/Test/hlsl.float1.frag new file mode 100644 index 00000000..5000dced --- /dev/null +++ b/Test/hlsl.float1.frag @@ -0,0 +1,7 @@ +float1 f1 = float1(1.0); +float scalar = 2.0; + +float1 ShaderFunction(float1 inFloat1, float inScalar) : COLOR0 +{ + return f1 * scalar + inFloat1 * inScalar; +} diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index d4a9d101..98de1646 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -1044,8 +1044,8 @@ public: // for "empty" type (no args) or simple scalar/vector/matrix explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0) : - basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), arraySizes(nullptr), - structure(nullptr), fieldName(nullptr), typeName(nullptr) + basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr) { sampler.clear(); qualifier.clear(); @@ -1053,8 +1053,8 @@ public: } // for explicit precision qualifier TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0) : - basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), arraySizes(nullptr), - structure(nullptr), fieldName(nullptr), typeName(nullptr) + basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr) { sampler.clear(); qualifier.clear(); @@ -1064,8 +1064,9 @@ public: } // for turning a TPublicType into a TType, using a shallow copy explicit TType(const TPublicType& p) : - basicType(p.basicType), vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), arraySizes(p.arraySizes), - structure(nullptr), fieldName(nullptr), typeName(nullptr) + basicType(p.basicType), + vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), + arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr) { if (basicType == EbtSampler) sampler = p.sampler; @@ -1100,19 +1101,25 @@ public: // do a vector/matrix dereference shallowCopy(type); if (matrixCols > 0) { + // dereference from matrix to vector if (rowMajor) vectorSize = matrixCols; else vectorSize = matrixRows; matrixCols = 0; matrixRows = 0; - } else if (vectorSize > 1) + if (vectorSize == 1) + vector1 = true; + } else if (isVector()) { + // dereference from vector to scalar vectorSize = 1; + vector1 = false; + } } } // for making structures, ... TType(TTypeList* userDef, const TString& n) : - basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), + basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), arraySizes(nullptr), structure(userDef), fieldName(nullptr) { sampler.clear(); @@ -1121,7 +1128,7 @@ public: } // For interface blocks TType(TTypeList* userDef, const TString& n, const TQualifier& q) : - basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), + basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr) { sampler.clear(); @@ -1140,6 +1147,7 @@ public: vectorSize = copyOf.vectorSize; matrixCols = copyOf.matrixCols; matrixRows = copyOf.matrixRows; + vector1 = copyOf.vector1; arraySizes = copyOf.arraySizes; // copying the pointer only, not the contents structure = copyOf.structure; fieldName = copyOf.fieldName; @@ -1180,6 +1188,8 @@ public: return newType; } + void makeVector() { vector1 = true; } + // Merge type from parent, where a parentType is at the beginning of a declaration, // establishing some characteristics for all subsequent names, while this type // is on the individual names. @@ -1190,6 +1200,7 @@ public: vectorSize = parentType.vectorSize; matrixCols = parentType.matrixCols; matrixRows = parentType.matrixRows; + vector1 = false; // TPublicType is only GLSL which so far has no vec1 qualifier = parentType.qualifier; sampler = parentType.sampler; if (parentType.arraySizes) @@ -1223,7 +1234,7 @@ public: virtual TQualifier& getQualifier() { return qualifier; } virtual const TQualifier& getQualifier() const { return qualifier; } - virtual int getVectorSize() const { return vectorSize; } + virtual int getVectorSize() const { return vectorSize; } // returns 1 for either scalar or vector of size 1, valid for both virtual int getMatrixCols() const { return matrixCols; } virtual int getMatrixRows() const { return matrixRows; } virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); } @@ -1234,8 +1245,8 @@ public: virtual const TArraySizes* getArraySizes() const { return arraySizes; } virtual TArraySizes& getArraySizes() { assert(arraySizes != nullptr); return *arraySizes; } - virtual bool isScalar() const { return vectorSize == 1 && ! isStruct() && ! isArray(); } - virtual bool isVector() const { return vectorSize > 1; } + virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); } + virtual bool isVector() const { return vectorSize > 1 || vector1; } virtual bool isMatrix() const { return matrixCols ? true : false; } virtual bool isArray() const { return arraySizes != nullptr; } virtual bool isExplicitlySizedArray() const { return isArray() && getOuterArraySize() != UnsizedArraySize; } @@ -1508,7 +1519,7 @@ public: if (qualifier.specConstant) p += snprintf(p, end - p, "specialization-constant "); p += snprintf(p, end - p, "%s ", getStorageQualifierString()); - if (arraySizes) { + if (isArray()) { for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) { int size = arraySizes->getDimSize(i); if (size == 0) @@ -1519,9 +1530,9 @@ public: } if (qualifier.precision != EpqNone) p += snprintf(p, end - p, "%s ", getPrecisionQualifierString()); - if (matrixCols > 0) + if (isMatrix()) p += snprintf(p, end - p, "%dX%d matrix of ", matrixCols, matrixRows); - else if (vectorSize > 1) + else if (isVector()) p += snprintf(p, end - p, "%d-component vector of ", vectorSize); *p = 0; @@ -1653,6 +1664,7 @@ public: vectorSize == right.vectorSize && matrixCols == right.matrixCols && matrixRows == right.matrixRows && + vector1 == right.vector1 && sameStructType(right); } @@ -1675,9 +1687,14 @@ protected: void buildMangledName(TString&); TBasicType basicType : 8; - int vectorSize : 4; + int vectorSize : 4; // 1 means either scalar or 1-component vector; see vector1 to disambiguate. int matrixCols : 4; int matrixRows : 4; + bool vector1 : 1; // Backward-compatible tracking of a 1-component vector distinguished from a scalar. + // GLSL 4.5 never has a 1-component vector; so this will always be false until such + // functionality is added. + // HLSL does have a 1-component vectors, so this will be true to disambiguate + // from a scalar. TSampler sampler; TQualifier qualifier; diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index d3aa5853..f8f9237b 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -1629,8 +1629,10 @@ bool TIntermBinary::promote() return false; if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize()) return false; - if (right->isVector() || right->isMatrix()) - setType(TType(basicType, EvqTemporary, right->getVectorSize(), right->getMatrixCols(), right->getMatrixRows())); + if (right->isVector() || right->isMatrix()) { + type.shallowCopy(right->getType()); + type.getQualifier().makeTemporary(); + } break; default: diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp index e5922bc1..90e13113 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -72,6 +72,7 @@ INSTANTIATE_TEST_CASE_P( ToSpirv, HlslCompileTest, ::testing::ValuesIn(std::vector{ {"hlsl.assoc.frag", "PixelShaderFunction"}, + {"hlsl.float1.frag", "PixelShaderFunction"}, {"hlsl.float4.frag", "PixelShaderFunction"}, {"hlsl.max.frag", "PixelShaderFunction"}, {"hlsl.precedence.frag", "PixelShaderFunction"}, diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index 9ab9f2c3..75f9818d 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -219,8 +219,12 @@ bool HlslGrammar::acceptType(TType& type) new(&type) TType(EbtInt); break; case EHTokFloat: + new(&type) TType(EbtFloat); + break; + case EHTokFloat1: new(&type) TType(EbtFloat); + type.makeVector(); break; case EHTokFloat2: diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 0d67a1d7..2cdaf0c0 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -1655,13 +1655,6 @@ void HlslParseContext::boolCheck(const TSourceLoc& loc, const TIntermTyped* type error(loc, "boolean expression expected", "", ""); } -// This function checks to see if the node (for the expression) contains a scalar boolean expression or not -void HlslParseContext::boolCheck(const TSourceLoc& loc, const TPublicType& pType) -{ - if (pType.basicType != EbtBool || pType.arraySizes || pType.matrixCols > 1 || (pType.vectorSize > 1)) - error(loc, "boolean expression expected", "", ""); -} - // // Fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level. // diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index ba5bcda3..7fa267ff 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -107,7 +107,6 @@ public: void arrayDimMerge(TType& type, const TArraySizes* sizes); bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType); void boolCheck(const TSourceLoc&, const TIntermTyped*); - void boolCheck(const TSourceLoc&, const TPublicType&); void globalQualifierFix(const TSourceLoc&, TQualifier&); bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType); void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);