Add support for OpMatrixTimesMatrix
Bug: b/126873455
Test: dEQP-VK.glsl.matrix.*
Change-Id: I3070690017263b3bf766a329ef7729206f285e45
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/28228
Tested-by: Chris Forbes <chrisforbes@google.com>
Presubmit-Ready: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 9383517..c54c4cb 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -361,6 +361,7 @@
case spv::OpMatrixTimesScalar:
case spv::OpMatrixTimesVector:
case spv::OpVectorTimesMatrix:
+ case spv::OpMatrixTimesMatrix:
case spv::OpVectorExtractDynamic:
case spv::OpVectorInsertDynamic:
case spv::OpNot: // Unary ops
@@ -1480,6 +1481,9 @@
case spv::OpVectorTimesMatrix:
return EmitVectorTimesMatrix(insn, state);
+ case spv::OpMatrixTimesMatrix:
+ return EmitMatrixTimesMatrix(insn, state);
+
case spv::OpNot:
case spv::OpSNegate:
case spv::OpFNegate:
@@ -2105,6 +2109,34 @@
return EmitResult::Continue;
}
+ SpirvShader::EmitResult SpirvShader::EmitMatrixTimesMatrix(InsnIterator insn, EmitState *state) const
+ {
+ auto routine = state->routine;
+ auto &type = getType(insn.word(1));
+ auto &dst = routine->createIntermediate(insn.word(2), type.sizeInComponents);
+ auto lhs = GenericValue(this, routine, insn.word(3));
+ auto rhs = GenericValue(this, routine, insn.word(4));
+
+ auto numColumns = type.definition.word(3);
+ auto numRows = getType(type.definition.word(2)).definition.word(3);
+ auto numAdds = getType(getObject(insn.word(3)).type).definition.word(3);
+
+ for (auto row = 0u; row < numRows; row++)
+ {
+ for (auto col = 0u; col < numColumns; col++)
+ {
+ SIMD::Float v = SIMD::Float(0);
+ for (auto i = 0u; i < numAdds; i++)
+ {
+ v += lhs.Float(i * numRows + row) * rhs.Float(col * numAdds + i);
+ }
+ dst.move(numRows * col + row, v);
+ }
+ }
+
+ return EmitResult::Continue;
+ }
+
SpirvShader::EmitResult SpirvShader::EmitUnaryOp(InsnIterator insn, EmitState *state) const
{
auto routine = state->routine;
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 3410dc1..498c547 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -598,6 +598,7 @@
EmitResult EmitVectorTimesScalar(InsnIterator insn, EmitState *state) const;
EmitResult EmitMatrixTimesVector(InsnIterator insn, EmitState *state) const;
EmitResult EmitVectorTimesMatrix(InsnIterator insn, EmitState *state) const;
+ EmitResult EmitMatrixTimesMatrix(InsnIterator insn, EmitState *state) const;
EmitResult EmitVectorExtractDynamic(InsnIterator insn, EmitState *state) const;
EmitResult EmitVectorInsertDynamic(InsnIterator insn, EmitState *state) const;
EmitResult EmitUnaryOp(InsnIterator insn, EmitState *state) const;