mirror of
https://github.com/libretro/glslang.git
synced 2024-12-04 22:27:15 +00:00
Implement operator-based implicit type conversions.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@20724 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
ef8ae2e345
commit
4b67103b02
@ -11,7 +11,51 @@ out vec4 o;
|
||||
|
||||
uniform mat4x2 m;
|
||||
|
||||
struct s {
|
||||
float f;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
mat2x3 m23 = mat2x3(m);
|
||||
|
||||
int a;
|
||||
bool b;
|
||||
s sv = s(a);
|
||||
float[2] ia = float[2](3, i.y);
|
||||
float f1 = 1;
|
||||
float f = a;
|
||||
f = a;
|
||||
ivec3 iv3;
|
||||
vec3 v3 = iv3;
|
||||
f = f + a;
|
||||
f = a - f;
|
||||
f += a;
|
||||
f = a - f;
|
||||
v3 *= iv3;
|
||||
v3 = iv3 / 2.0;
|
||||
v3 = 3.0 * iv3;
|
||||
v3 = 2 * v3;
|
||||
v3 = v3 - 2;
|
||||
if (f < a ||
|
||||
a <= f ||
|
||||
f > a ||
|
||||
f >= a ||
|
||||
a == f ||
|
||||
f != a);
|
||||
f = b ? a : f;
|
||||
f = b ? f : a;
|
||||
f = b ? a : a;
|
||||
s news = sv;
|
||||
|
||||
i.xy + i.xyz; // ERROR
|
||||
m * i.xyz; // ERROR
|
||||
m + i; // ERROR
|
||||
int aoeu = 1.0; // ERROR
|
||||
f = b; // ERROR
|
||||
f = a + b; // ERROR
|
||||
f = b * a; // ERROR
|
||||
b = a; // ERROR
|
||||
b = b + f; // ERROR
|
||||
f |= b; // ERROR
|
||||
}
|
||||
|
@ -93,32 +93,24 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
|
||||
case EOpSub:
|
||||
case EOpDiv:
|
||||
case EOpMul:
|
||||
if (left->getType().getBasicType() == EbtStruct || left->getType().getBasicType() == EbtBool)
|
||||
if (left->getType().getBasicType() == EbtStruct || left->getType().getBasicType() == EbtBool || left->getType().isArray())
|
||||
return 0;
|
||||
default: break;
|
||||
}
|
||||
|
||||
//
|
||||
// First try converting the children to compatible types.
|
||||
//
|
||||
|
||||
if (!(left->getType().getStruct() && right->getType().getStruct())) {
|
||||
TIntermTyped* child = addConversion(op, left->getType(), right);
|
||||
TIntermTyped* child = addConversion(op, left->getType(), right);
|
||||
if (child)
|
||||
right = child;
|
||||
else {
|
||||
child = addConversion(op, right->getType(), left);
|
||||
if (child)
|
||||
right = child;
|
||||
else {
|
||||
child = addConversion(op, right->getType(), left);
|
||||
if (child)
|
||||
left = child;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (left->getType() != right->getType())
|
||||
left = child;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Need a new node holding things together then. Make
|
||||
// one and promote it to the right type.
|
||||
@ -228,21 +220,17 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
|
||||
case EOpNegative:
|
||||
if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
|
||||
return 0;
|
||||
default: break;
|
||||
}
|
||||
|
||||
//
|
||||
// Do we need to promote the operand?
|
||||
//
|
||||
// Note: Implicit promotions were removed from the language.
|
||||
//
|
||||
TBasicType newType = EbtVoid;
|
||||
switch (op) {
|
||||
case EOpConstructInt: newType = EbtInt; break;
|
||||
case EOpConstructBool: newType = EbtBool; break;
|
||||
case EOpConstructFloat: newType = EbtFloat; break;
|
||||
case EOpConstructDouble: newType = EbtDouble; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (newType != EbtVoid) {
|
||||
@ -261,8 +249,8 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
|
||||
case EOpConstructInt:
|
||||
case EOpConstructBool:
|
||||
case EOpConstructFloat:
|
||||
case EOpConstructDouble:
|
||||
return child;
|
||||
default: break;
|
||||
}
|
||||
|
||||
TIntermConstantUnion *childTempConstant = 0;
|
||||
@ -370,11 +358,14 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
|
||||
if (type.isArray() || node->getType().isArray())
|
||||
return 0;
|
||||
|
||||
// Note: callers are responsible for other aspects of shape,
|
||||
// like vector and matrix sizes.
|
||||
|
||||
TBasicType promoteTo;
|
||||
|
||||
switch (op) {
|
||||
//
|
||||
// Explicit conversions
|
||||
// Explicit conversions (unary operations)
|
||||
//
|
||||
case EOpConstructBool:
|
||||
promoteTo = EbtBool;
|
||||
@ -385,31 +376,83 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
|
||||
case EOpConstructInt:
|
||||
promoteTo = EbtInt;
|
||||
break;
|
||||
default:
|
||||
//
|
||||
// implicit conversions were removed from the language.
|
||||
//
|
||||
if (type.getBasicType() != node->getType().getBasicType())
|
||||
|
||||
//
|
||||
// List all the binary ops that can implicitly convert one operand to the other's type;
|
||||
// This implements the 'policy' for implicit type conversion.
|
||||
//
|
||||
case EOpLessThan:
|
||||
case EOpGreaterThan:
|
||||
case EOpLessThanEqual:
|
||||
case EOpGreaterThanEqual:
|
||||
case EOpEqual:
|
||||
case EOpNotEqual:
|
||||
|
||||
case EOpAdd:
|
||||
case EOpSub:
|
||||
case EOpMul:
|
||||
case EOpDiv:
|
||||
|
||||
case EOpVectorTimesScalar:
|
||||
case EOpVectorTimesMatrix:
|
||||
case EOpMatrixTimesVector:
|
||||
case EOpMatrixTimesScalar:
|
||||
|
||||
case EOpAssign:
|
||||
case EOpAddAssign:
|
||||
case EOpSubAssign:
|
||||
case EOpMulAssign:
|
||||
case EOpVectorTimesScalarAssign:
|
||||
case EOpMatrixTimesScalarAssign:
|
||||
case EOpDivAssign:
|
||||
case EOpModAssign:
|
||||
|
||||
case EOpSequence:
|
||||
case EOpConstructStruct:
|
||||
|
||||
if (type.getBasicType() == node->getType().getBasicType())
|
||||
return node;
|
||||
|
||||
if (canImplicitlyPromote(node->getType().getBasicType(), type.getBasicType()))
|
||||
promoteTo = type.getBasicType();
|
||||
else
|
||||
return 0;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// default is to require a match; all exceptions should have case statements above
|
||||
|
||||
if (type.getBasicType() == node->getType().getBasicType())
|
||||
return node;
|
||||
else
|
||||
return 0;
|
||||
//
|
||||
// Size and structure could still differ, but that's
|
||||
// handled by operator promotion.
|
||||
//
|
||||
return node;
|
||||
}
|
||||
|
||||
if (node->getAsConstantUnion()) {
|
||||
|
||||
return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
|
||||
} else {
|
||||
|
||||
} else {
|
||||
//
|
||||
// Add a new newNode for the conversion.
|
||||
//
|
||||
TIntermUnary* newNode = 0;
|
||||
|
||||
TOperator newOp = EOpNull;
|
||||
|
||||
// This is 'mechanism' here, it does any conversion told. The policy comes
|
||||
// from the shader or the above code.
|
||||
switch (promoteTo) {
|
||||
case EbtDouble:
|
||||
//switch (node->getBasicType()) {
|
||||
//case EbtInt: newOp = EOpConvIntToDouble; break;
|
||||
//case EbtBool: newOp = EOpConvBoolToDouble; break;
|
||||
//case EbtFloat: newOp = EOpConvFloatToDouble; break;
|
||||
//default:
|
||||
infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
|
||||
return 0;
|
||||
//}
|
||||
break;
|
||||
case EbtFloat:
|
||||
switch (node->getBasicType()) {
|
||||
case EbtInt: newOp = EOpConvIntToFloat; break;
|
||||
@ -451,6 +494,55 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// See if the 'from' type is allowed to be implicitly converted to the
|
||||
// 'to' type. This is not about vector/array/struct, only about basic type.
|
||||
//
|
||||
bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to)
|
||||
{
|
||||
if (profile == EEsProfile || version == 110)
|
||||
return 0;
|
||||
|
||||
switch (to) {
|
||||
case EbtDouble:
|
||||
switch (from) {
|
||||
case EbtInt:
|
||||
case EbtUint:
|
||||
case EbtFloat:
|
||||
case EbtDouble:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case EbtFloat:
|
||||
switch (from) {
|
||||
case EbtInt:
|
||||
case EbtUint:
|
||||
case EbtFloat:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case EbtUint:
|
||||
switch (from) {
|
||||
case EbtInt:
|
||||
case EbtUint:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case EbtInt:
|
||||
switch (from) {
|
||||
case EbtInt:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Safe way to combine two nodes into an aggregate. Works with null pointers,
|
||||
// a node that's not a aggregate yet, etc.
|
||||
|
@ -1326,11 +1326,12 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, T
|
||||
//
|
||||
TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset)
|
||||
{
|
||||
if (*type == node->getAsTyped()->getType()) {
|
||||
TIntermNode* converted = intermediate.addConversion(EOpConstructStruct, *type, node->getAsTyped());
|
||||
if (converted->getAsTyped()->getType() == *type) {
|
||||
if (subset)
|
||||
return node->getAsTyped();
|
||||
return converted->getAsTyped();
|
||||
else
|
||||
return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line);
|
||||
return intermediate.setAggregateOperator(converted->getAsTyped(), EOpConstructStruct, line);
|
||||
} else {
|
||||
error(line, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
|
||||
node->getAsTyped()->getType().getCompleteTypeString().c_str(), type->getCompleteTypeString().c_str());
|
||||
|
@ -89,7 +89,7 @@ TPoolAllocator* PerProcessGPA = 0;
|
||||
bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, int version, EProfile profile, EShLanguage language, TInfoSink& infoSink,
|
||||
const TBuiltInResource* resources, TSymbolTable* symbolTables)
|
||||
{
|
||||
TIntermediate intermediate(infoSink);
|
||||
TIntermediate intermediate(infoSink, version, profile);
|
||||
TSymbolTable* symbolTable;
|
||||
|
||||
if (resources)
|
||||
@ -509,7 +509,7 @@ int ShCompile(
|
||||
version = defaultVersion;
|
||||
bool goodProfile = DeduceProfile(compiler->infoSink, version, profile);
|
||||
|
||||
TIntermediate intermediate(compiler->infoSink);
|
||||
TIntermediate intermediate(compiler->infoSink, version, profile);
|
||||
|
||||
SetupBuiltinSymbolTable(version, profile);
|
||||
TSymbolTable symbolTable(*SharedSymbolTables[MapVersionToIndex(version)]
|
||||
|
@ -1073,9 +1073,6 @@ conditional_expression
|
||||
parseContext.recover();
|
||||
|
||||
$$ = parseContext.intermediate.addSelection($1, $3, $5, $2.line);
|
||||
if ($3->getType() != $5->getType())
|
||||
$$ = 0;
|
||||
|
||||
if ($$ == 0) {
|
||||
parseContext.binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString());
|
||||
parseContext.recover();
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "../Include/intermediate.h"
|
||||
#include "../Public/ShaderLang.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "Versions.h"
|
||||
|
||||
struct TVectorFields {
|
||||
int offsets[4];
|
||||
@ -52,13 +53,14 @@ class TIntermediate {
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
||||
|
||||
TIntermediate(TInfoSink& i) : infoSink(i) { }
|
||||
TIntermediate(TInfoSink& i, int v, EProfile p) : infoSink(i), version(v), profile(p) { }
|
||||
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
|
||||
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
|
||||
TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, TSymbolTable&);
|
||||
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
||||
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
|
||||
TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, TSourceLoc, TSymbolTable&);
|
||||
bool canImplicitlyPromote(TBasicType from, TBasicType to);
|
||||
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc);
|
||||
TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc);
|
||||
TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, TSourceLoc);
|
||||
@ -79,6 +81,8 @@ public:
|
||||
|
||||
protected:
|
||||
TInfoSink& infoSink;
|
||||
EProfile profile;
|
||||
int version;
|
||||
|
||||
private:
|
||||
void operator=(TIntermediate&); // prevent assignments
|
||||
|
Loading…
Reference in New Issue
Block a user