Commit 32d47971 by Ben Clayton

SpirvShader: Implement OpGroupNonUniformElect

The only elect function we'll need to implement for Pastel 1.0. Used by memory barrier tests, but not tested on its own. Bug: b/131667233 Change-Id: I5309fa6b49c49091226fbaaca4e46363f6dff534 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30208 Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Presubmit-Ready: Ben Clayton <bclayton@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com>
parent 2e043583
...@@ -862,6 +862,7 @@ namespace sw ...@@ -862,6 +862,7 @@ namespace sw
case spv::OpImageQuerySize: case spv::OpImageQuerySize:
case spv::OpImageRead: case spv::OpImageRead:
case spv::OpImageTexelPointer: case spv::OpImageTexelPointer:
case spv::OpGroupNonUniformElect:
// Instructions that yield an intermediate value or divergent pointer // Instructions that yield an intermediate value or divergent pointer
DefineResult(insn); DefineResult(insn);
break; break;
...@@ -2447,6 +2448,9 @@ namespace sw ...@@ -2447,6 +2448,9 @@ namespace sw
case spv::OpCopyMemory: case spv::OpCopyMemory:
return EmitCopyMemory(insn, state); return EmitCopyMemory(insn, state);
case spv::OpGroupNonUniformElect:
return EmitGroupNonUniform(insn, state);
default: default:
UNREACHABLE("%s", OpcodeName(opcode).c_str()); UNREACHABLE("%s", OpcodeName(opcode).c_str());
break; break;
...@@ -5321,6 +5325,43 @@ namespace sw ...@@ -5321,6 +5325,43 @@ namespace sw
return EmitResult::Continue; return EmitResult::Continue;
} }
SpirvShader::EmitResult SpirvShader::EmitGroupNonUniform(InsnIterator insn, EmitState *state) const
{
auto &type = getType(Type::ID(insn.word(1)));
Object::ID resultId = insn.word(2);
auto scope = GetScope(insn.word(3));
ASSERT_MSG(scope == spv::ScopeSubgroup, "Scope for Non Uniform Group Operations must be Subgroup for Vulkan 1.1");
auto &dst = state->routine->createIntermediate(resultId, type.sizeInComponents);
switch (insn.opcode())
{
case spv::OpGroupNonUniformElect:
{
// Result is true only in the active invocation with the lowest id
// in the group, otherwise result is false.
SIMD::Int active = state->activeLaneMask();
// TODO: Would be nice if we could write this as:
// elect = active & ~(active.Oxyz | active.OOxy | active.OOOx)
auto v0111 = SIMD::Int(0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
auto elect = active & ~(v0111 & (active.xxyz | active.xxxy | active.xxxx));
dst.move(0, elect);
break;
}
default:
UNIMPLEMENTED("EmitGroupNonUniform op: %s", OpcodeName(type.opcode()).c_str());
}
return EmitResult::Continue;
}
spv::Scope SpirvShader::GetScope(Object::ID id) const
{
auto &scopeObj = getObject(id);
ASSERT(scopeObj.kind == Object::Kind::Constant);
ASSERT(getType(scopeObj.type).sizeInComponents == 1);
return spv::Scope(scopeObj.constantValue[0]);
}
void SpirvShader::emitEpilog(SpirvRoutine *routine) const void SpirvShader::emitEpilog(SpirvRoutine *routine) const
{ {
for (auto insn : *this) for (auto insn : *this)
......
...@@ -906,8 +906,10 @@ namespace sw ...@@ -906,8 +906,10 @@ namespace sw
EmitResult EmitAtomicCompareExchange(InsnIterator insn, EmitState *state) const; EmitResult EmitAtomicCompareExchange(InsnIterator insn, EmitState *state) const;
EmitResult EmitSampledImageCombineOrSplit(InsnIterator insn, EmitState *state) const; EmitResult EmitSampledImageCombineOrSplit(InsnIterator insn, EmitState *state) const;
EmitResult EmitCopyMemory(InsnIterator insn, EmitState *state) const; EmitResult EmitCopyMemory(InsnIterator insn, EmitState *state) const;
EmitResult EmitGroupNonUniform(InsnIterator insn, EmitState *state) const;
SIMD::Pointer GetTexelAddress(SpirvRoutine const * routine, SIMD::Pointer base, GenericValue const & coordinate, Type const & imageType, Pointer<Byte> descriptor, int texelSize) const; SIMD::Pointer GetTexelAddress(SpirvRoutine const * routine, SIMD::Pointer base, GenericValue const & coordinate, Type const & imageType, Pointer<Byte> descriptor, int texelSize) const;
spv::Scope GetScope(Object::ID id) const;
// OpcodeName() returns the name of the opcode op. // OpcodeName() returns the name of the opcode op.
// If NDEBUG is defined, then OpcodeName() will only return the numerical code. // If NDEBUG is defined, then OpcodeName() will only return the numerical code.
......
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