HLSL: matrix swizzle (_12, _m23) syntax, partial semantics.
This partially addressess issue #670, for when the matrix swizzle degenerates to a component or column: m[c], m[c][r] (where HLSL swaps rows and columns for user's view). An error message is given for the arbitrary cases not covered. These cases will work for arbitrary use of l-values. Future work will handle more arbitrary swizzles, which might not work as arbitrary l-values.
This commit is contained in:
parent
913e3b686a
commit
001dfa1c5c
148
Test/baseResults/hlsl.matrixSwizzle.vert.out
Executable file
148
Test/baseResults/hlsl.matrixSwizzle.vert.out
Executable file
@ -0,0 +1,148 @@
|
||||
hlsl.matrixSwizzle.vert
|
||||
Shader version: 450
|
||||
0:? Sequence
|
||||
0:2 Function Definition: ShaderFunction(f1; (temp void)
|
||||
0:2 Function Parameters:
|
||||
0:2 'inf' (layout(location=0 ) in float)
|
||||
0:? Sequence
|
||||
0:5 move second child to first child (temp float)
|
||||
0:5 direct index (temp float)
|
||||
0:5 direct index (temp 4-component vector of float)
|
||||
0:5 'm' (temp 3X4 matrix of float)
|
||||
0:5 Constant:
|
||||
0:5 2 (const int)
|
||||
0:5 Constant:
|
||||
0:5 3 (const int)
|
||||
0:5 Constant:
|
||||
0:5 1.000000
|
||||
0:6 move second child to first child (temp float)
|
||||
0:6 direct index (temp float)
|
||||
0:6 direct index (temp 4-component vector of float)
|
||||
0:6 'm' (temp 3X4 matrix of float)
|
||||
0:6 Constant:
|
||||
0:6 2 (const int)
|
||||
0:6 Constant:
|
||||
0:6 3 (const int)
|
||||
0:6 Constant:
|
||||
0:6 2.000000
|
||||
0:8 move second child to first child (temp 4-component vector of float)
|
||||
0:8 direct index (temp 4-component vector of float)
|
||||
0:8 'm' (temp 3X4 matrix of float)
|
||||
0:8 Constant:
|
||||
0:8 0 (const int)
|
||||
0:8 Constant:
|
||||
0:8 3.000000
|
||||
0:8 3.000000
|
||||
0:8 3.000000
|
||||
0:8 3.000000
|
||||
0:9 move second child to first child (temp 4-component vector of float)
|
||||
0:9 direct index (temp 4-component vector of float)
|
||||
0:9 'm' (temp 3X4 matrix of float)
|
||||
0:9 Constant:
|
||||
0:9 1 (const int)
|
||||
0:9 Constant:
|
||||
0:9 3.000000
|
||||
0:9 3.000000
|
||||
0:9 3.000000
|
||||
0:9 3.000000
|
||||
0:? Linker Objects
|
||||
0:? 'inf' (layout(location=0 ) in float)
|
||||
|
||||
|
||||
Linked vertex stage:
|
||||
|
||||
|
||||
Shader version: 450
|
||||
0:? Sequence
|
||||
0:2 Function Definition: ShaderFunction(f1; (temp void)
|
||||
0:2 Function Parameters:
|
||||
0:2 'inf' (layout(location=0 ) in float)
|
||||
0:? Sequence
|
||||
0:5 move second child to first child (temp float)
|
||||
0:5 direct index (temp float)
|
||||
0:5 direct index (temp 4-component vector of float)
|
||||
0:5 'm' (temp 3X4 matrix of float)
|
||||
0:5 Constant:
|
||||
0:5 2 (const int)
|
||||
0:5 Constant:
|
||||
0:5 3 (const int)
|
||||
0:5 Constant:
|
||||
0:5 1.000000
|
||||
0:6 move second child to first child (temp float)
|
||||
0:6 direct index (temp float)
|
||||
0:6 direct index (temp 4-component vector of float)
|
||||
0:6 'm' (temp 3X4 matrix of float)
|
||||
0:6 Constant:
|
||||
0:6 2 (const int)
|
||||
0:6 Constant:
|
||||
0:6 3 (const int)
|
||||
0:6 Constant:
|
||||
0:6 2.000000
|
||||
0:8 move second child to first child (temp 4-component vector of float)
|
||||
0:8 direct index (temp 4-component vector of float)
|
||||
0:8 'm' (temp 3X4 matrix of float)
|
||||
0:8 Constant:
|
||||
0:8 0 (const int)
|
||||
0:8 Constant:
|
||||
0:8 3.000000
|
||||
0:8 3.000000
|
||||
0:8 3.000000
|
||||
0:8 3.000000
|
||||
0:9 move second child to first child (temp 4-component vector of float)
|
||||
0:9 direct index (temp 4-component vector of float)
|
||||
0:9 'm' (temp 3X4 matrix of float)
|
||||
0:9 Constant:
|
||||
0:9 1 (const int)
|
||||
0:9 Constant:
|
||||
0:9 3.000000
|
||||
0:9 3.000000
|
||||
0:9 3.000000
|
||||
0:9 3.000000
|
||||
0:? Linker Objects
|
||||
0:? 'inf' (layout(location=0 ) in float)
|
||||
|
||||
// Module Version 10000
|
||||
// Generated by (magic number): 80001
|
||||
// Id's are bound by 29
|
||||
|
||||
Capability Shader
|
||||
1: ExtInstImport "GLSL.std.450"
|
||||
MemoryModel Logical GLSL450
|
||||
EntryPoint Vertex 4 "ShaderFunction" 28
|
||||
Name 4 "ShaderFunction"
|
||||
Name 10 "m"
|
||||
Name 28 "inf"
|
||||
Decorate 28(inf) Location 0
|
||||
2: TypeVoid
|
||||
3: TypeFunction 2
|
||||
6: TypeFloat 32
|
||||
7: TypeVector 6(float) 4
|
||||
8: TypeMatrix 7(fvec4) 3
|
||||
9: TypePointer Function 8
|
||||
11: TypeInt 32 1
|
||||
12: 11(int) Constant 2
|
||||
13: 6(float) Constant 1065353216
|
||||
14: TypeInt 32 0
|
||||
15: 14(int) Constant 3
|
||||
16: TypePointer Function 6(float)
|
||||
18: 6(float) Constant 1073741824
|
||||
20: 11(int) Constant 0
|
||||
21: 6(float) Constant 1077936128
|
||||
22: 7(fvec4) ConstantComposite 21 21 21 21
|
||||
23: TypePointer Function 7(fvec4)
|
||||
25: 11(int) Constant 1
|
||||
27: TypePointer Input 6(float)
|
||||
28(inf): 27(ptr) Variable Input
|
||||
4(ShaderFunction): 2 Function None 3
|
||||
5: Label
|
||||
10(m): 9(ptr) Variable Function
|
||||
17: 16(ptr) AccessChain 10(m) 12 15
|
||||
Store 17 13
|
||||
19: 16(ptr) AccessChain 10(m) 12 15
|
||||
Store 19 18
|
||||
24: 23(ptr) AccessChain 10(m) 20
|
||||
Store 24 22
|
||||
26: 23(ptr) AccessChain 10(m) 25
|
||||
Store 26 22
|
||||
Return
|
||||
FunctionEnd
|
10
Test/hlsl.matrixSwizzle.vert
Normal file
10
Test/hlsl.matrixSwizzle.vert
Normal file
@ -0,0 +1,10 @@
|
||||
void ShaderFunction(float inf) : COLOR0
|
||||
{
|
||||
float3x4 m;
|
||||
|
||||
m._34 = 1.0; // AST should have a normal component select
|
||||
m._m23 = 2.0; // same code
|
||||
|
||||
m._11_12_13_14 = float4(3.0); // AST should have normal column selection (first row)
|
||||
m._m10_m11_m12_m13 = float4(3.0); // AST should have normal column selection (second row)
|
||||
}
|
@ -62,6 +62,32 @@ struct TVectorFields {
|
||||
int num;
|
||||
};
|
||||
|
||||
class TMatrixComponents {
|
||||
public:
|
||||
static const int maxMatrixComponents = 4;
|
||||
struct tMatrixComponent {
|
||||
int coord1; // stay agnostic about column/row; this is parse order
|
||||
int coord2;
|
||||
};
|
||||
|
||||
TMatrixComponents() : size_(0) { }
|
||||
void push_back(tMatrixComponent comp)
|
||||
{
|
||||
if (size_ < maxMatrixComponents)
|
||||
components[size_++] = comp;
|
||||
}
|
||||
int size() const { return size_; }
|
||||
tMatrixComponent get(int i) const
|
||||
{
|
||||
assert(i < maxMatrixComponents);
|
||||
return components[i];
|
||||
}
|
||||
|
||||
private:
|
||||
int size_;
|
||||
tMatrixComponent components[4];
|
||||
};
|
||||
|
||||
//
|
||||
// Some helper structures for TIntermediate. Their contents are encapsulated
|
||||
// by TIntermediate.
|
||||
|
@ -154,6 +154,7 @@ INSTANTIATE_TEST_CASE_P(
|
||||
{"hlsl.logical.binary.frag", "main"},
|
||||
{"hlsl.logical.binary.vec.frag", "main"},
|
||||
{"hlsl.matNx1.frag", "main"},
|
||||
{"hlsl.matrixSwizzle.vert", "ShaderFunction"},
|
||||
{"hlsl.mintypes.frag", "main"},
|
||||
{"hlsl.multiEntry.vert", "RealEntrypoint"},
|
||||
{"hlsl.multiReturn.frag", "main"},
|
||||
|
@ -521,78 +521,162 @@ bool HlslParseContext::parseVectorFields(const TSourceLoc& loc, const TString& c
|
||||
estpq,
|
||||
} fieldSet[4];
|
||||
|
||||
for (int i = 0; i < fields.num; ++i) {
|
||||
switch (compString[i]) {
|
||||
case 'x':
|
||||
fields.offsets[i] = 0;
|
||||
fieldSet[i] = exyzw;
|
||||
break;
|
||||
case 'r':
|
||||
fields.offsets[i] = 0;
|
||||
fieldSet[i] = ergba;
|
||||
break;
|
||||
case 's':
|
||||
fields.offsets[i] = 0;
|
||||
fieldSet[i] = estpq;
|
||||
break;
|
||||
case 'y':
|
||||
fields.offsets[i] = 1;
|
||||
fieldSet[i] = exyzw;
|
||||
break;
|
||||
case 'g':
|
||||
fields.offsets[i] = 1;
|
||||
fieldSet[i] = ergba;
|
||||
break;
|
||||
case 't':
|
||||
fields.offsets[i] = 1;
|
||||
fieldSet[i] = estpq;
|
||||
break;
|
||||
case 'z':
|
||||
fields.offsets[i] = 2;
|
||||
fieldSet[i] = exyzw;
|
||||
break;
|
||||
case 'b':
|
||||
fields.offsets[i] = 2;
|
||||
fieldSet[i] = ergba;
|
||||
break;
|
||||
case 'p':
|
||||
fields.offsets[i] = 2;
|
||||
fieldSet[i] = estpq;
|
||||
break;
|
||||
for (int i = 0; i < fields.num; ++i) {
|
||||
switch (compString[i]) {
|
||||
case 'x':
|
||||
fields.offsets[i] = 0;
|
||||
fieldSet[i] = exyzw;
|
||||
break;
|
||||
case 'r':
|
||||
fields.offsets[i] = 0;
|
||||
fieldSet[i] = ergba;
|
||||
break;
|
||||
case 's':
|
||||
fields.offsets[i] = 0;
|
||||
fieldSet[i] = estpq;
|
||||
break;
|
||||
case 'y':
|
||||
fields.offsets[i] = 1;
|
||||
fieldSet[i] = exyzw;
|
||||
break;
|
||||
case 'g':
|
||||
fields.offsets[i] = 1;
|
||||
fieldSet[i] = ergba;
|
||||
break;
|
||||
case 't':
|
||||
fields.offsets[i] = 1;
|
||||
fieldSet[i] = estpq;
|
||||
break;
|
||||
case 'z':
|
||||
fields.offsets[i] = 2;
|
||||
fieldSet[i] = exyzw;
|
||||
break;
|
||||
case 'b':
|
||||
fields.offsets[i] = 2;
|
||||
fieldSet[i] = ergba;
|
||||
break;
|
||||
case 'p':
|
||||
fields.offsets[i] = 2;
|
||||
fieldSet[i] = estpq;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
fields.offsets[i] = 3;
|
||||
fieldSet[i] = exyzw;
|
||||
break;
|
||||
case 'a':
|
||||
fields.offsets[i] = 3;
|
||||
fieldSet[i] = ergba;
|
||||
break;
|
||||
case 'q':
|
||||
fields.offsets[i] = 3;
|
||||
fieldSet[i] = estpq;
|
||||
break;
|
||||
default:
|
||||
error(loc, "illegal vector field selection", compString.c_str(), "");
|
||||
case 'w':
|
||||
fields.offsets[i] = 3;
|
||||
fieldSet[i] = exyzw;
|
||||
break;
|
||||
case 'a':
|
||||
fields.offsets[i] = 3;
|
||||
fieldSet[i] = ergba;
|
||||
break;
|
||||
case 'q':
|
||||
fields.offsets[i] = 3;
|
||||
fieldSet[i] = estpq;
|
||||
break;
|
||||
default:
|
||||
error(loc, "illegal vector field selection", compString.c_str(), "");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < fields.num; ++i) {
|
||||
if (fields.offsets[i] >= vecSize) {
|
||||
error(loc, "vector field selection out of range", compString.c_str(), "");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
if (fieldSet[i] != fieldSet[i - 1]) {
|
||||
error(loc, "illegal - vector component fields not from the same set", compString.c_str(), "");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < fields.num; ++i) {
|
||||
if (fields.offsets[i] >= vecSize) {
|
||||
error(loc, "vector field selection out of range", compString.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Look at a '.' field selector string and change it into components
|
||||
// for a matrix. There are two types:
|
||||
//
|
||||
// _21 second row, first column (one based)
|
||||
// _m21 third row, second column (zero based)
|
||||
//
|
||||
// Returns true if there is no error.
|
||||
//
|
||||
bool HlslParseContext::parseMatrixComponents(const TSourceLoc& loc, const TString& fields, int cols, int rows,
|
||||
TMatrixComponents& components)
|
||||
{
|
||||
int startPos[TMatrixComponents::maxMatrixComponents];
|
||||
int numComps = 0;
|
||||
TString compString = fields;
|
||||
|
||||
// Find where each component starts,
|
||||
// recording the first character position after the '_'.
|
||||
for (size_t c = 0; c < compString.size(); ++c) {
|
||||
if (compString[c] == '_') {
|
||||
if (numComps >= TMatrixComponents::maxMatrixComponents) {
|
||||
error(loc, "matrix component swizzle has too many components", compString.c_str(), "");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
if (fieldSet[i] != fieldSet[i - 1]) {
|
||||
error(loc, "illegal - vector component fields not from the same set", compString.c_str(), "");
|
||||
return false;
|
||||
}
|
||||
if (c > compString.size() - 3 ||
|
||||
((compString[c+1] == 'm' || compString[c+1] == 'M') && c > compString.size() - 4)) {
|
||||
error(loc, "matrix component swizzle missing", compString.c_str(), "");
|
||||
return false;
|
||||
}
|
||||
startPos[numComps++] = c + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
// Process each component
|
||||
for (int i = 0; i < numComps; ++i) {
|
||||
int pos = startPos[i];
|
||||
int bias = -1;
|
||||
if (compString[pos] == 'm' || compString[pos] == 'M') {
|
||||
bias = 0;
|
||||
++pos;
|
||||
}
|
||||
TMatrixComponents::tMatrixComponent comp;
|
||||
comp.coord1 = compString[pos+0] - '0' + bias;
|
||||
comp.coord2 = compString[pos+1] - '0' + bias;
|
||||
if (comp.coord1 < 0 || comp.coord1 >= cols) {
|
||||
error(loc, "matrix row component out of range", compString.c_str(), "");
|
||||
return false;
|
||||
}
|
||||
if (comp.coord2 < 0 || comp.coord2 >= rows) {
|
||||
error(loc, "matrix column component out of range", compString.c_str(), "");
|
||||
return false;
|
||||
}
|
||||
components.push_back(comp);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the 'comps' express a column of a matrix,
|
||||
// return the column. Column means the first coords all match.
|
||||
//
|
||||
// Otherwise, return -1.
|
||||
//
|
||||
int HlslParseContext::getMatrixComponentsColumn(int rows, const TMatrixComponents& comps)
|
||||
{
|
||||
int col = -1;
|
||||
|
||||
// right number of comps?
|
||||
if (comps.size() != rows)
|
||||
return -1;
|
||||
|
||||
// all comps in the same column?
|
||||
// rows in order?
|
||||
col = comps.get(0).coord1;
|
||||
for (int i = 0; i < rows; ++i) {
|
||||
if (col != comps.get(i).coord1)
|
||||
return -1;
|
||||
if (i != comps.get(i).coord2)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
//
|
||||
@ -888,6 +972,40 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt
|
||||
result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, (int)vectorString.size()));
|
||||
}
|
||||
}
|
||||
} else if (base->isMatrix()) {
|
||||
TMatrixComponents comps;
|
||||
if (! parseMatrixComponents(loc, field, base->getMatrixCols(), base->getMatrixRows(), comps))
|
||||
return result;
|
||||
|
||||
if (comps.size() == 1) {
|
||||
// Representable by m[c][r]
|
||||
if (base->getType().getQualifier().storage == EvqConst) {
|
||||
result = intermediate.foldDereference(base, comps.get(0).coord1, loc);
|
||||
result = intermediate.foldDereference(result, comps.get(1).coord2, loc);
|
||||
} else {
|
||||
result = intermediate.addIndex(EOpIndexDirect, base, intermediate.addConstantUnion(comps.get(0).coord1, loc), loc);
|
||||
TType dereferencedCol(base->getType(), 0);
|
||||
result->setType(dereferencedCol);
|
||||
result = intermediate.addIndex(EOpIndexDirect, result, intermediate.addConstantUnion(comps.get(0).coord2, loc), loc);
|
||||
TType dereferenced(dereferencedCol, 0);
|
||||
result->setType(dereferenced);
|
||||
}
|
||||
} else {
|
||||
int column = getMatrixComponentsColumn(base->getMatrixRows(), comps);
|
||||
if (column >= 0) {
|
||||
// Representable by m[c]
|
||||
if (base->getType().getQualifier().storage == EvqConst)
|
||||
result = intermediate.foldDereference(base, column, loc);
|
||||
else {
|
||||
result = intermediate.addIndex(EOpIndexDirect, base, intermediate.addConstantUnion(column, loc), loc);
|
||||
TType dereferenced(base->getType(), 0);
|
||||
result->setType(dereferenced);
|
||||
}
|
||||
} else {
|
||||
// general case, not a column, not a single component
|
||||
error(loc, "arbitrary matrix component selection not supported", field.c_str(), "");
|
||||
}
|
||||
}
|
||||
} else if (base->getBasicType() == EbtStruct || base->getBasicType() == EbtBlock) {
|
||||
const TTypeList* fields = base->getType().getStruct();
|
||||
bool fieldFound = false;
|
||||
|
@ -97,6 +97,8 @@ public:
|
||||
TIntermAggregate* handleSamplerTextureCombine(const TSourceLoc& loc, TIntermTyped* argTex, TIntermTyped* argSampler);
|
||||
|
||||
bool parseVectorFields(const TSourceLoc&, const TString&, int vecSize, TVectorFields&);
|
||||
bool parseMatrixComponents(const TSourceLoc&, const TString&, int cols, int rows, TMatrixComponents&);
|
||||
int getMatrixComponentsColumn(int rows, const TMatrixComponents&);
|
||||
void assignError(const TSourceLoc&, const char* op, TString left, TString right);
|
||||
void unaryOpError(const TSourceLoc&, const char* op, TString operand);
|
||||
void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
|
||||
|
Loading…
x
Reference in New Issue
Block a user