Start support for OpExtInst
- OpExtInstImport now enforces correct instruction set
- OpExtInst dispatch done
- Implemented FAbs, SAbs
Bug: b/127804400
Change-Id: I41b9755afeeb9a61c8294beb610f5e6c77080fa5
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/26408
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Chris Forbes <chrisforbes@google.com>
Presubmit-Ready: Chris Forbes <chrisforbes@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 0e2a6f8..610d088 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -13,6 +13,7 @@
// limitations under the License.
#include <spirv/unified1/spirv.hpp>
+#include <spirv/unified1/GLSL.std.450.h>
#include "SpirvShader.hpp"
#include "System/Math.hpp"
#include "Vulkan/VkBuffer.hpp"
@@ -235,6 +236,11 @@
case spv::OpExtInstImport:
// We will only support the GLSL 450 extended instruction set, so no point in tracking the ID we assign it.
// Valid shaders will not attempt to import any other instruction sets.
+ if (0 != strcmp("GLSL.std.450", reinterpret_cast<char const *>(insn.wordPointer(2))))
+ {
+ UNIMPLEMENTED("Only GLSL extended instruction set is supported");
+ }
+ break;
case spv::OpName:
case spv::OpMemberName:
case spv::OpSource:
@@ -319,6 +325,7 @@
case spv::OpConvertUToF:
case spv::OpBitcast:
case spv::OpSelect:
+ case spv::OpExtInst:
// Instructions that yield an intermediate value
{
TypeID typeId = insn.word(1);
@@ -1051,6 +1058,10 @@
EmitSelect(insn, routine);
break;
+ case spv::OpExtInst:
+ EmitExtendedInstruction(insn, routine);
+ break;
+
default:
UNIMPLEMENTED(OpcodeName(insn.opcode()).c_str());
break;
@@ -1595,6 +1606,37 @@
}
}
+ void SpirvShader::EmitExtendedInstruction(InsnIterator insn, SpirvRoutine *routine) const
+ {
+ auto &type = getType(insn.word(1));
+ auto &dst = routine->createIntermediate(insn.word(2), type.sizeInComponents);
+ auto extInstIndex = static_cast<GLSLstd450>(insn.word(4));
+
+ switch (extInstIndex)
+ {
+ case GLSLstd450FAbs:
+ {
+ auto src = GenericValue(this, routine, insn.word(5));
+ for (auto i = 0u; i < type.sizeInComponents; i++)
+ {
+ dst.emplace(i, Abs(src[i]));
+ }
+ break;
+ }
+ case GLSLstd450SAbs:
+ {
+ auto src = GenericValue(this, routine, insn.word(5));
+ for (auto i = 0u; i < type.sizeInComponents; i++)
+ {
+ dst.emplace(i, As<SIMD::Float>(Abs(As<SIMD::Int>(src[i]))));
+ }
+ break;
+ }
+ default:
+ UNIMPLEMENTED("Unhandled ExtInst %d", extInstIndex);
+ }
+ }
+
void SpirvShader::emitEpilog(SpirvRoutine *routine) const
{
for (auto insn : *this)
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 4bfdc4a..e4d13e2 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -440,6 +440,7 @@
void EmitBinaryOp(InsnIterator insn, SpirvRoutine *routine) const;
void EmitDot(InsnIterator insn, SpirvRoutine *routine) const;
void EmitSelect(InsnIterator insn, SpirvRoutine *routine) const;
+ void EmitExtendedInstruction(InsnIterator insn, SpirvRoutine *routine) const;
// OpcodeName returns the name of the opcode op.
// If NDEBUG is defined, then OpcodeName will only return the numerical code.