Commit 04bb8a01 by John Kessenich

SPV: Implement all matrix operators {+,-,*,/} for {matrix,scalar,vector}.

parent 494a02a2
...@@ -108,6 +108,7 @@ protected: ...@@ -108,6 +108,7 @@ protected:
spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*); spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*);
spv::Id createBinaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id left, spv::Id right, glslang::TBasicType typeProxy, bool reduceComparison = true); spv::Id createBinaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id left, spv::Id right, glslang::TBasicType typeProxy, bool reduceComparison = true);
spv::Id createBinaryMatrixOperation(spv::Op, spv::Decoration precision, spv::Id typeId, spv::Id left, spv::Id right);
spv::Id createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy); spv::Id createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy);
spv::Id createConversion(glslang::TOperator op, spv::Decoration precision, spv::Id destTypeId, spv::Id operand); spv::Id createConversion(glslang::TOperator op, spv::Decoration precision, spv::Id destTypeId, spv::Id operand);
spv::Id makeSmearedConstant(spv::Id constant, int vectorSize); spv::Id makeSmearedConstant(spv::Id constant, int vectorSize);
...@@ -2122,26 +2123,17 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv ...@@ -2122,26 +2123,17 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
break; break;
case glslang::EOpVectorTimesMatrix: case glslang::EOpVectorTimesMatrix:
case glslang::EOpVectorTimesMatrixAssign: case glslang::EOpVectorTimesMatrixAssign:
assert(builder.isVector(left));
assert(builder.isMatrix(right));
binOp = spv::OpVectorTimesMatrix; binOp = spv::OpVectorTimesMatrix;
break; break;
case glslang::EOpMatrixTimesVector: case glslang::EOpMatrixTimesVector:
assert(builder.isMatrix(left));
assert(builder.isVector(right));
binOp = spv::OpMatrixTimesVector; binOp = spv::OpMatrixTimesVector;
break; break;
case glslang::EOpMatrixTimesScalar: case glslang::EOpMatrixTimesScalar:
case glslang::EOpMatrixTimesScalarAssign: case glslang::EOpMatrixTimesScalarAssign:
if (builder.isMatrix(right))
std::swap(left, right);
assert(builder.isScalar(right));
binOp = spv::OpMatrixTimesScalar; binOp = spv::OpMatrixTimesScalar;
break; break;
case glslang::EOpMatrixTimesMatrix: case glslang::EOpMatrixTimesMatrix:
case glslang::EOpMatrixTimesMatrixAssign: case glslang::EOpMatrixTimesMatrixAssign:
assert(builder.isMatrix(left));
assert(builder.isMatrix(right));
binOp = spv::OpMatrixTimesMatrix; binOp = spv::OpMatrixTimesMatrix;
break; break;
case glslang::EOpOuterProduct: case glslang::EOpOuterProduct:
...@@ -2220,29 +2212,8 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv ...@@ -2220,29 +2212,8 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
// handle mapped binary operations (should be non-comparison) // handle mapped binary operations (should be non-comparison)
if (binOp != spv::OpNop) { if (binOp != spv::OpNop) {
assert(comparison == false); assert(comparison == false);
if (builder.isMatrix(left) || builder.isMatrix(right)) { if (builder.isMatrix(left) || builder.isMatrix(right))
switch (binOp) { return createBinaryMatrixOperation(binOp, precision, typeId, left, right);
case spv::OpMatrixTimesScalar:
case spv::OpVectorTimesMatrix:
case spv::OpMatrixTimesVector:
case spv::OpMatrixTimesMatrix:
break;
case spv::OpFDiv:
// turn it into a multiply...
assert(builder.isMatrix(left) && builder.isScalar(right));
right = builder.createBinOp(spv::OpFDiv, builder.getTypeId(right), builder.makeFloatConstant(1.0F), right);
binOp = spv::OpFMul;
break;
default:
spv::MissingFunctionality("binary operation on matrix");
break;
}
spv::Id id = builder.createBinOp(binOp, typeId, left, right);
builder.setPrecision(id, precision);
return id;
}
// No matrix involved; make both operands be the same number of components, if needed // No matrix involved; make both operands be the same number of components, if needed
if (needMatchingVectors) if (needMatchingVectors)
...@@ -2326,6 +2297,111 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv ...@@ -2326,6 +2297,111 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
return 0; return 0;
} }
//
// Translate AST matrix operation to SPV operation, already having SPV-based operands/types.
// These can be any of:
//
// matrix * scalar
// scalar * matrix
// matrix * matrix linear algebraic
// matrix * vector
// vector * matrix
// matrix * matrix componentwise
// matrix op matrix op in {+, -, /}
// matrix op scalar op in {+, -, /}
// scalar op matrix op in {+, -, /}
//
spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Id typeId, spv::Id left, spv::Id right)
{
bool firstClass = true;
// First, handle first-class matrix operations (* and matrix/scalar)
switch (op) {
case spv::OpFDiv:
if (builder.isMatrix(left) && builder.isScalar(right)) {
// turn matrix / scalar into a multiply...
right = builder.createBinOp(spv::OpFDiv, builder.getTypeId(right), builder.makeFloatConstant(1.0F), right);
op = spv::OpMatrixTimesScalar;
} else
firstClass = false;
break;
case spv::OpMatrixTimesScalar:
if (builder.isMatrix(right))
std::swap(left, right);
assert(builder.isScalar(right));
break;
case spv::OpVectorTimesMatrix:
assert(builder.isVector(left));
assert(builder.isMatrix(right));
break;
case spv::OpMatrixTimesVector:
assert(builder.isMatrix(left));
assert(builder.isVector(right));
break;
case spv::OpMatrixTimesMatrix:
assert(builder.isMatrix(left));
assert(builder.isMatrix(right));
break;
default:
firstClass = false;
break;
}
if (firstClass) {
spv::Id id = builder.createBinOp(op, typeId, left, right);
builder.setPrecision(id, precision);
return id;
}
// Handle component-wise +, -, *, and / for all combinations of type.
// The result type of all of them is the same type as the (a) matrix operand.
// The algorithm is to:
// - break the matrix(es) into vectors
// - smear any scalar to a vector
// - do vector operations
// - make a matrix out the vector results
switch (op) {
case spv::OpFAdd:
case spv::OpFSub:
case spv::OpFDiv:
case spv::OpFMul:
{
// one time set up...
bool leftMat = builder.isMatrix(left);
bool rightMat = builder.isMatrix(right);
unsigned int numCols = leftMat ? builder.getNumColumns(left) : builder.getNumColumns(right);
int numRows = leftMat ? builder.getNumRows(left) : builder.getNumRows(right);
spv::Id scalarType = builder.getScalarTypeId(typeId);
spv::Id vecType = builder.makeVectorType(scalarType, numRows);
std::vector<spv::Id> results;
spv::Id smearVec = spv::NoResult;
if (builder.isScalar(left))
smearVec = builder.smearScalar(precision, left, vecType);
else if (builder.isScalar(right))
smearVec = builder.smearScalar(precision, right, vecType);
// do each vector op
for (unsigned int c = 0; c < numCols; ++c) {
std::vector<unsigned int> indexes;
indexes.push_back(c);
spv::Id leftVec = leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec;
spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec;
results.push_back(builder.createBinOp(op, vecType, leftVec, rightVec));
builder.setPrecision(results.back(), precision);
}
// put the pieces together
spv::Id id = builder.createCompositeConstruct(typeId, results);
builder.setPrecision(id, precision);
return id;
}
default:
assert(0);
return spv::NoResult;
}
}
spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id operand, glslang::TBasicType typeProxy) spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id operand, glslang::TBasicType typeProxy)
{ {
spv::Op unaryOp = spv::OpNop; spv::Op unaryOp = spv::OpNop;
......
...@@ -7,7 +7,7 @@ out vec4 pos; ...@@ -7,7 +7,7 @@ out vec4 pos;
out vec3 color; out vec3 color;
flat out int iout; flat out int iout;
layout(shared, column_major, row_major) uniform; // default is now shared and row_major layout(row_major) uniform; // default is now row_major
layout(std140) uniform Transform { // layout of this block is std140 layout(std140) uniform Transform { // layout of this block is std140
mat4 M1; // row_major mat4 M1; // row_major
......
#version 130 #version 130
uniform mat3 colorTransform; in mat3x4 m1;
in vec3 Color; in mat3x4 m2;
uniform mat4 m, n; in float f;
in vec3 v3;
in vec4 v4;
uniform mat4x3 um43; out vec4 color;
uniform mat3x4 un34;
in vec4 v;
in vec3 u;
void main() void main()
{ {
gl_FragColor = vec4(un34[1]); mat3x4 sum34;
gl_FragColor += vec4(Color * colorTransform, 1.0); vec3 sum3;
vec4 sum4;
if (m != n)
gl_FragColor += v; sum34 = m1 - m2;
else { sum34 += m1 * f;
gl_FragColor += m * v; sum34 += f * m1;
gl_FragColor += v * (m - n); sum34 /= matrixCompMult(m1, m2);
} sum34 += m1 / f;
sum34 += f / m1;
mat3x4 m34 = outerProduct(v, u); sum34 += f;
m34 += mat3x4(v.x); sum34 -= f;
m34 += mat3x4(u, u.x, u, u.x, u, u.x);
sum3 = v4 * m2;
if (m34 == un34) sum4 = m2 * v3;
gl_FragColor += m34 * u;
else mat4x3 m43 = transpose(sum34);
gl_FragColor += (un34 * um43) * v; mat4 m4 = m1 * m43;
sum4 = v4 * m4;
color = sum4;
//spv if (m1 != sum34)
++sum34;
// else
--sum34;
sum34 += mat3x4(f);
sum34 += mat3x4(v3, f, v3, f, v3, f);
color += sum3 * m43 + sum4;
} }
#version 150 #version 150
uniform mat3 colorTransform; in mat3 colorTransform;
varying vec3 Color; in vec3 Color;
uniform mat4 m, n; in mat4 m, n;
uniform mat4x3 um43; in mat4x3 um43;
uniform mat3x4 un34; in mat3x4 un34;
uniform mat2 um2; in mat2 um2;
uniform mat3 um3; in mat3 um3;
uniform mat4 um4; in mat4 um4;
varying vec4 v; in vec4 v;
varying vec3 u; in vec3 u;
out vec4 FragColor; out vec4 FragColor;
......
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
// For the date, it uses the current date (when then script is run). // For the date, it uses the current date (when then script is run).
#define GLSLANG_REVISION "SPIRV99.841" #define GLSLANG_REVISION "SPIRV99.841"
#define GLSLANG_DATE "11-Dec-2015" #define GLSLANG_DATE "12-Dec-2015"
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