Commit e2713125 by LoopDawg

HLSL: fix several issues in mat construction from scalars

This fixes: 1. A compilation error when assigning scalars to matricies 2. A semantic error in matrix construction from scalars. This was initializing the diagonal, where HLSL semantics require the scalar be replicated to every matrix element. 3. Functions accepting mats can be called with scalars, which will be shape-converted to the matrix type. This was previously failing to match the function signature. NOTE: this does not yet handle complex scalars (a function call, say) used to construct matricies. That'll be added when the node replicator service is available. For now, there's an assert. There's one new test (hlsl.scalar2matrix.frag). An existing test lsl.type.half.frag changes, because of (2) above, and a negative test error message changes due to (3) above. Fixes #923.
parent f7cd88a2
hlsl.intrinsics.negative.frag hlsl.intrinsics.negative.frag
ERROR: 0:10: 'determinant' : no matching overloaded function found ERROR: 0:10: 'determinant' : ambiguous best function under implicit type conversion
ERROR: 0:25: 'normalize' : ambiguous best function under implicit type conversion ERROR: 0:25: 'normalize' : ambiguous best function under implicit type conversion
ERROR: 0:26: 'reflect' : ambiguous best function under implicit type conversion ERROR: 0:26: 'reflect' : ambiguous best function under implicit type conversion
ERROR: 0:27: 'refract' : ambiguous best function under implicit type conversion ERROR: 0:27: 'refract' : ambiguous best function under implicit type conversion
ERROR: 0:28: 'refract' : no matching overloaded function found ERROR: 0:28: 'refract' : no matching overloaded function found
ERROR: 0:30: 'transpose' : no matching overloaded function found ERROR: 0:30: 'transpose' : ambiguous best function under implicit type conversion
ERROR: 0:39: 'GetRenderTargetSamplePosition' : no matching overloaded function found ERROR: 0:39: 'GetRenderTargetSamplePosition' : no matching overloaded function found
ERROR: 0:46: 'asdouble' : double2 conversion not implemented ERROR: 0:46: 'asdouble' : double2 conversion not implemented
ERROR: 0:47: 'CheckAccessFullyMapped' : no matching overloaded function found ERROR: 0:47: 'CheckAccessFullyMapped' : no matching overloaded function found
...@@ -104,8 +104,9 @@ ERROR: node is still EOpNull! ...@@ -104,8 +104,9 @@ ERROR: node is still EOpNull!
0:9 0 (const int) 0:9 0 (const int)
0:9 Constant: 0:9 Constant:
0:9 3 (const int) 0:9 3 (const int)
0:10 Constant: 0:10 determinant ( temp float)
0:10 0.000000 ERROR: node is still EOpNull!
0:10 'inF0' ( in float)
0:12 direct index ( temp float) 0:12 direct index ( temp float)
0:12 unpackHalf2x16 ( temp 2-component vector of float) 0:12 unpackHalf2x16 ( temp 2-component vector of float)
0:12 Convert float to uint ( temp uint) 0:12 Convert float to uint ( temp uint)
...@@ -150,8 +151,9 @@ ERROR: node is still EOpNull! ...@@ -150,8 +151,9 @@ ERROR: node is still EOpNull!
0:29 bitFieldReverse ( temp uint) 0:29 bitFieldReverse ( temp uint)
0:29 Convert float to uint ( temp uint) 0:29 Convert float to uint ( temp uint)
0:29 'inF0' ( in float) 0:29 'inF0' ( in float)
0:30 Constant: 0:30 transpose ( temp 1X1 matrix of float)
0:30 0.000000 ERROR: node is still EOpNull!
0:30 'inF0' ( in float)
0:32 Branch: Return with expression 0:32 Branch: Return with expression
0:32 Constant: 0:32 Constant:
0:32 0.000000 0:32 0.000000
...@@ -565,8 +567,9 @@ ERROR: node is still EOpNull! ...@@ -565,8 +567,9 @@ ERROR: node is still EOpNull!
0:9 0 (const int) 0:9 0 (const int)
0:9 Constant: 0:9 Constant:
0:9 3 (const int) 0:9 3 (const int)
0:10 Constant: 0:10 determinant ( temp float)
0:10 0.000000 ERROR: node is still EOpNull!
0:10 'inF0' ( in float)
0:12 direct index ( temp float) 0:12 direct index ( temp float)
0:12 unpackHalf2x16 ( temp 2-component vector of float) 0:12 unpackHalf2x16 ( temp 2-component vector of float)
0:12 Convert float to uint ( temp uint) 0:12 Convert float to uint ( temp uint)
...@@ -611,8 +614,9 @@ ERROR: node is still EOpNull! ...@@ -611,8 +614,9 @@ ERROR: node is still EOpNull!
0:29 bitFieldReverse ( temp uint) 0:29 bitFieldReverse ( temp uint)
0:29 Convert float to uint ( temp uint) 0:29 Convert float to uint ( temp uint)
0:29 'inF0' ( in float) 0:29 'inF0' ( in float)
0:30 Constant: 0:30 transpose ( temp 1X1 matrix of float)
0:30 0.000000 ERROR: node is still EOpNull!
0:30 'inF0' ( in float)
0:32 Branch: Return with expression 0:32 Branch: Return with expression
0:32 Constant: 0:32 Constant:
0:32 0.000000 0:32 0.000000
......
...@@ -49,11 +49,11 @@ gl_FragCoord origin is upper left ...@@ -49,11 +49,11 @@ gl_FragCoord origin is upper left
0:16 'h23' ( temp 2X3 matrix of float) 0:16 'h23' ( temp 2X3 matrix of float)
0:16 Constant: 0:16 Constant:
0:16 4.900000 0:16 4.900000
0:16 0.000000
0:16 0.000000
0:16 0.000000
0:16 4.900000 0:16 4.900000
0:16 0.000000 0:16 4.900000
0:16 4.900000
0:16 4.900000
0:16 4.900000
0:27 Branch: Return with expression 0:27 Branch: Return with expression
0:27 Construct vec4 ( temp 4-component vector of float) 0:27 Construct vec4 ( temp 4-component vector of float)
0:27 add ( temp float) 0:27 add ( temp float)
...@@ -133,11 +133,11 @@ gl_FragCoord origin is upper left ...@@ -133,11 +133,11 @@ gl_FragCoord origin is upper left
0:16 'h23' ( temp 2X3 matrix of float) 0:16 'h23' ( temp 2X3 matrix of float)
0:16 Constant: 0:16 Constant:
0:16 4.900000 0:16 4.900000
0:16 0.000000
0:16 0.000000
0:16 0.000000
0:16 4.900000 0:16 4.900000
0:16 0.000000 0:16 4.900000
0:16 4.900000
0:16 4.900000
0:16 4.900000
0:27 Branch: Return with expression 0:27 Branch: Return with expression
0:27 Construct vec4 ( temp 4-component vector of float) 0:27 Construct vec4 ( temp 4-component vector of float)
0:27 add ( temp float) 0:27 add ( temp float)
...@@ -165,12 +165,12 @@ gl_FragCoord origin is upper left ...@@ -165,12 +165,12 @@ gl_FragCoord origin is upper left
// Module Version 10000 // Module Version 10000
// Generated by (magic number): 80001 // Generated by (magic number): 80001
// Id's are bound by 61 // Id's are bound by 60
Capability Shader Capability Shader
1: ExtInstImport "GLSL.std.450" 1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450 MemoryModel Logical GLSL450
EntryPoint Fragment 4 "main" 59 EntryPoint Fragment 4 "main" 58
ExecutionMode 4 OriginUpperLeft ExecutionMode 4 OriginUpperLeft
Source HLSL 500 Source HLSL 500
Name 4 "main" Name 4 "main"
...@@ -182,8 +182,8 @@ gl_FragCoord origin is upper left ...@@ -182,8 +182,8 @@ gl_FragCoord origin is upper left
Name 27 "h4" Name 27 "h4"
Name 32 "h22" Name 32 "h22"
Name 38 "h23" Name 38 "h23"
Name 59 "@entryPointOutput" Name 58 "@entryPointOutput"
Decorate 59(@entryPointOutput) Location 0 Decorate 58(@entryPointOutput) Location 0
2: TypeVoid 2: TypeVoid
3: TypeFunction 2 3: TypeFunction 2
6: TypeFloat 32 6: TypeFloat 32
...@@ -211,20 +211,19 @@ gl_FragCoord origin is upper left ...@@ -211,20 +211,19 @@ gl_FragCoord origin is upper left
36: TypeMatrix 21(fvec3) 2 36: TypeMatrix 21(fvec3) 2
37: TypePointer Function 36 37: TypePointer Function 36
39: 6(float) Constant 1084017869 39: 6(float) Constant 1084017869
40: 21(fvec3) ConstantComposite 39 13 13 40: 21(fvec3) ConstantComposite 39 39 39
41: 21(fvec3) ConstantComposite 13 39 13 41: 36 ConstantComposite 40 40
42: 36 ConstantComposite 40 41 42: TypeInt 32 1
43: TypeInt 32 1 43: 42(int) Constant 0
44: 43(int) Constant 0 44: TypeInt 32 0
45: TypeInt 32 0 45: 44(int) Constant 0
46: 45(int) Constant 0 48: 44(int) Constant 1
49: 45(int) Constant 1 57: TypePointer Output 7(fvec4)
58: TypePointer Output 7(fvec4) 58(@entryPointOutput): 57(ptr) Variable Output
59(@entryPointOutput): 58(ptr) Variable Output
4(main): 2 Function None 3 4(main): 2 Function None 3
5: Label 5: Label
60: 7(fvec4) FunctionCall 9(@main() 59: 7(fvec4) FunctionCall 9(@main()
Store 59(@entryPointOutput) 60 Store 58(@entryPointOutput) 59
Return Return
FunctionEnd FunctionEnd
9(@main(): 7(fvec4) Function None 8 9(@main(): 7(fvec4) Function None 8
...@@ -242,14 +241,14 @@ gl_FragCoord origin is upper left ...@@ -242,14 +241,14 @@ gl_FragCoord origin is upper left
Store 23(h3) 25 Store 23(h3) 25
Store 27(h4) 29 Store 27(h4) 29
Store 32(h22) 35 Store 32(h22) 35
Store 38(h23) 42 Store 38(h23) 41
47: 11(ptr) AccessChain 38(h23) 44 46 46: 11(ptr) AccessChain 38(h23) 43 45
48: 6(float) Load 47 47: 6(float) Load 46
50: 11(ptr) AccessChain 27(h4) 49 49: 11(ptr) AccessChain 27(h4) 48
51: 6(float) Load 50 50: 6(float) Load 49
52: 6(float) FAdd 48 51 51: 6(float) FAdd 47 50
53: 6(float) Load 12(h0) 52: 6(float) Load 12(h0)
54: 6(float) FAdd 52 53 53: 6(float) FAdd 51 52
55: 7(fvec4) CompositeConstruct 54 54 54 54 54: 7(fvec4) CompositeConstruct 53 53 53 53
ReturnValue 55 ReturnValue 54
FunctionEnd FunctionEnd
void Fn1(float4x4 p) { }
float4 main() : SV_TARGET
{
const float4x4 mat1c = 0.20;
const float4x4 mat2c = {2, 2.1, 2.2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
const float4x4 mat3c = (float4x4)float1(0.1);
float4x4 mat1 = 0.25;
float4x4 mat2 = {3, 3.1, 3.2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
float4x4 mat3 = (float4x4)0.375;
// float4x4 mat5 = (float4x4)Fn2(); // TODO: enable when compex rvalue handling is in place
float4x4 mat4;
mat4 = 0.75;
mat4 = float4x4(4, 4.1, 4.2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
mat4 = (float4x4)0.5;
mat4 *= 0.75;
mat4 += 0.75;
mat4 -= 0.5;
mat4 /= 2.0;
Fn1(5.0); // test calling fn accepting matrix with scalar type
return mat1c[0] + mat3c[0] + mat1[1] + mat4[2];
}
...@@ -1043,6 +1043,32 @@ TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped* ...@@ -1043,6 +1043,32 @@ TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped*
// The new node that handles the conversion // The new node that handles the conversion
TOperator constructorOp = mapTypeToConstructorOp(type); TOperator constructorOp = mapTypeToConstructorOp(type);
// HLSL has custom semantics for scalar->mat shape conversions.
if (source == EShSourceHlsl) {
if (node->getType().isScalarOrVec1() && type.isMatrix()) {
// HLSL semantics: the scalar (or vec1) is replicated to every component of the matrix. Left to its
// own devices, the constructor from a scalar would populate the diagonal. This forces replication
// to every matrix element.
// Note that if the node is complex (e.g, a function call), we don't want to duplicate it here
// repeatedly, so we copy it to a temp, then use the temp.
const int matSize = type.getMatrixRows() * type.getMatrixCols();
TIntermAggregate* rhsAggregate = new TIntermAggregate();
const bool isSimple = (node->getAsSymbolNode() != nullptr) || (node->getAsConstantUnion() != nullptr);
if (!isSimple) {
assert(0); // TODO: use node replicator service when available.
}
for (int x=0; x<matSize; ++x)
rhsAggregate->getSequence().push_back(node);
return setAggregateOperator(rhsAggregate, constructorOp, type, node->getLoc());
}
}
// scalar -> vector or vec1 -> vector or // scalar -> vector or vec1 -> vector or
// vector -> scalar or // vector -> scalar or
// bigger vector -> smaller vector // bigger vector -> smaller vector
......
...@@ -285,6 +285,7 @@ INSTANTIATE_TEST_CASE_P( ...@@ -285,6 +285,7 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.max.frag", "PixelShaderFunction"}, {"hlsl.max.frag", "PixelShaderFunction"},
{"hlsl.precedence.frag", "PixelShaderFunction"}, {"hlsl.precedence.frag", "PixelShaderFunction"},
{"hlsl.precedence2.frag", "PixelShaderFunction"}, {"hlsl.precedence2.frag", "PixelShaderFunction"},
{"hlsl.scalar2matrix.frag", "main"},
{"hlsl.semantic.geom", "main"}, {"hlsl.semantic.geom", "main"},
{"hlsl.semantic.vert", "main"}, {"hlsl.semantic.vert", "main"},
{"hlsl.scope.frag", "PixelShaderFunction"}, {"hlsl.scope.frag", "PixelShaderFunction"},
......
...@@ -6616,6 +6616,7 @@ const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, TFunction ...@@ -6616,6 +6616,7 @@ const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, TFunction
// shapes have to be convertible // shapes have to be convertible
if ((from.isScalarOrVec1() && to.isScalarOrVec1()) || if ((from.isScalarOrVec1() && to.isScalarOrVec1()) ||
(from.isScalarOrVec1() && to.isVector()) || (from.isScalarOrVec1() && to.isVector()) ||
(from.isScalarOrVec1() && to.isMatrix()) ||
(from.isVector() && to.isVector() && from.getVectorSize() >= to.getVectorSize())) (from.isVector() && to.isVector() && from.getVectorSize() >= to.getVectorSize()))
return true; return true;
...@@ -7393,8 +7394,15 @@ TIntermTyped* HlslParseContext::addConstructor(const TSourceLoc& loc, TIntermTyp ...@@ -7393,8 +7394,15 @@ TIntermTyped* HlslParseContext::addConstructor(const TSourceLoc& loc, TIntermTyp
newNode = constructAggregate(node, elementType, 1, node->getLoc()); newNode = constructAggregate(node, elementType, 1, node->getLoc());
else if (op == EOpConstructStruct) else if (op == EOpConstructStruct)
newNode = constructAggregate(node, *(*memberTypes).type, 1, node->getLoc()); newNode = constructAggregate(node, *(*memberTypes).type, 1, node->getLoc());
else else {
// shape conversion for matrix constructor from scalar. HLSL semantics are: scalar
// is replicated into every element of the matrix (not just the diagnonal), so
// that is handled specially here.
if (type.isMatrix() && node->getType().isScalarOrVec1())
node = intermediate.addShapeConversion(type, node);
newNode = constructBuiltIn(type, op, node, node->getLoc(), false); newNode = constructBuiltIn(type, op, node, node->getLoc(), false);
}
if (newNode && (type.isArray() || op == EOpConstructStruct)) if (newNode && (type.isArray() || op == EOpConstructStruct))
newNode = intermediate.setAggregateOperator(newNode, EOpConstructStruct, type, loc); newNode = intermediate.setAggregateOperator(newNode, EOpConstructStruct, type, loc);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment