Commit dfc0f3b7 by Ben Clayton Committed by Ben Clayton

SpirvShader: Move emit() instructions to their own functions

These are only going to grow. Bug: b/126126820 Change-Id: I03a2b214e9968c31dabc4814b505c1f8c22349ae Reviewed-on: https://swiftshader-review.googlesource.com/c/25552 Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com>
parent d4e4c66b
......@@ -836,251 +836,291 @@ namespace sw
break;
case spv::OpVariable:
{
ObjectID resultId = insn.word(2);
auto &object = getObject(resultId);
auto &objectTy = getType(object.type);
if (object.kind == Object::Kind::InterfaceVariable && objectTy.storageClass == spv::StorageClassInput)
{
auto &dst = routine->getValue(resultId);
int offset = 0;
VisitInterface(resultId,
[&](Decorations const &d, AttribType type) {
auto scalarSlot = d.Location << 2 | d.Component;
dst[offset++] = routine->inputs[scalarSlot];
});
}
EmitVariable(insn, routine);
break;
}
case spv::OpLoad:
{
ObjectID objectId = insn.word(2);
ObjectID pointerId = insn.word(3);
auto &object = getObject(objectId);
auto &objectTy = getType(object.type);
auto &pointer = getObject(pointerId);
auto &pointerBase = getObject(pointer.pointerBase);
auto &pointerBaseTy = getType(pointerBase.type);
EmitLoad(insn, routine);
break;
ASSERT(getType(pointer.type).element == object.type);
ASSERT(TypeID(insn.word(1)) == object.type);
case spv::OpStore:
EmitStore(insn, routine);
break;
if (pointerBaseTy.storageClass == spv::StorageClassImage ||
pointerBaseTy.storageClass == spv::StorageClassUniform ||
pointerBaseTy.storageClass == spv::StorageClassUniformConstant)
{
UNIMPLEMENTED("Descriptor-backed load not yet implemented");
}
case spv::OpAccessChain:
EmitAccessChain(insn, routine);
break;
auto &ptrBase = routine->getValue(pointer.pointerBase);
auto &dst = routine->createIntermediate(objectId, objectTy.sizeInComponents);
case spv::OpCompositeConstruct:
EmitCompositeConstruct(insn, routine);
break;
if (pointer.kind == Object::Kind::Value)
{
auto offsets = As<SIMD::Int>(routine->getIntermediate(insn.word(3))[0]);
for (auto i = 0u; i < objectTy.sizeInComponents; i++)
{
// i wish i had a Float,Float,Float,Float constructor here..
SIMD::Float v;
for (int j = 0; j < SIMD::Width; j++)
{
Int offset = Int(i) + Extract(offsets, j);
v = Insert(v, Extract(ptrBase[offset], j), j);
}
dst.emplace(i, v);
}
}
else
{
// no divergent offsets to worry about
for (auto i = 0u; i < objectTy.sizeInComponents; i++)
{
dst.emplace(i, ptrBase[i]);
}
}
case spv::OpCompositeInsert:
EmitCompositeInsert(insn, routine);
break;
case spv::OpCompositeExtract:
EmitCompositeExtract(insn, routine);
break;
case spv::OpVectorShuffle:
EmitVectorShuffle(insn, routine);
break;
default:
printf("emit: ignoring opcode %s\n", OpcodeName(insn.opcode()).c_str());
break;
}
case spv::OpAccessChain:
}
}
void SpirvShader::EmitVariable(InsnIterator insn, SpirvRoutine *routine) const
{
ObjectID resultId = insn.word(2);
auto &object = getObject(resultId);
auto &objectTy = getType(object.type);
if (object.kind == Object::Kind::InterfaceVariable && objectTy.storageClass == spv::StorageClassInput)
{
auto &dst = routine->getValue(resultId);
int offset = 0;
VisitInterface(resultId,
[&](Decorations const &d, AttribType type) {
auto scalarSlot = d.Location << 2 | d.Component;
dst[offset++] = routine->inputs[scalarSlot];
});
}
}
void SpirvShader::EmitLoad(InsnIterator insn, SpirvRoutine *routine) const
{
ObjectID objectId = insn.word(2);
ObjectID pointerId = insn.word(3);
auto &object = getObject(objectId);
auto &objectTy = getType(object.type);
auto &pointer = getObject(pointerId);
auto &pointerBase = getObject(pointer.pointerBase);
auto &pointerBaseTy = getType(pointerBase.type);
ASSERT(getType(pointer.type).element == object.type);
ASSERT(TypeID(insn.word(1)) == object.type);
if (pointerBaseTy.storageClass == spv::StorageClassImage ||
pointerBaseTy.storageClass == spv::StorageClassUniform ||
pointerBaseTy.storageClass == spv::StorageClassUniformConstant)
{
UNIMPLEMENTED("Descriptor-backed load not yet implemented");
}
auto &ptrBase = routine->getValue(pointer.pointerBase);
auto &dst = routine->createIntermediate(objectId, objectTy.sizeInComponents);
if (pointer.kind == Object::Kind::Value)
{
auto offsets = As<SIMD::Int>(routine->getIntermediate(insn.word(3))[0]);
for (auto i = 0u; i < objectTy.sizeInComponents; i++)
{
TypeID typeId = insn.word(1);
ObjectID objectId = insn.word(2);
ObjectID baseId = insn.word(3);
auto &object = getObject(objectId);
auto &type = getType(typeId);
auto &pointerBase = getObject(object.pointerBase);
auto &pointerBaseTy = getType(pointerBase.type);
ASSERT(type.sizeInComponents == 1);
ASSERT(getObject(baseId).pointerBase == object.pointerBase);
if (pointerBaseTy.storageClass == spv::StorageClassImage ||
pointerBaseTy.storageClass == spv::StorageClassUniform ||
pointerBaseTy.storageClass == spv::StorageClassUniformConstant)
// i wish i had a Float,Float,Float,Float constructor here..
SIMD::Float v;
for (int j = 0; j < SIMD::Width; j++)
{
UNIMPLEMENTED("Descriptor-backed OpAccessChain not yet implemented");
Int offset = Int(i) + Extract(offsets, j);
v = Insert(v, Extract(ptrBase[offset], j), j);
}
auto &dst = routine->createIntermediate(objectId, type.sizeInComponents);
dst.emplace(0, As<SIMD::Float>(WalkAccessChain(baseId, insn.wordCount() - 4, insn.wordPointer(4), routine)));
break;
dst.emplace(i, v);
}
case spv::OpStore:
}
else
{
// no divergent offsets to worry about
for (auto i = 0u; i < objectTy.sizeInComponents; i++)
{
ObjectID pointerId = insn.word(1);
ObjectID objectId = insn.word(2);
auto &object = getObject(objectId);
auto &pointer = getObject(pointerId);
auto &pointerTy = getType(pointer.type);
auto &elementTy = getType(pointerTy.element);
auto &pointerBase = getObject(pointer.pointerBase);
auto &pointerBaseTy = getType(pointerBase.type);
if (pointerBaseTy.storageClass == spv::StorageClassImage ||
pointerBaseTy.storageClass == spv::StorageClassUniform ||
pointerBaseTy.storageClass == spv::StorageClassUniformConstant)
{
UNIMPLEMENTED("Descriptor-backed store not yet implemented");
}
dst.emplace(i, ptrBase[i]);
}
}
}
void SpirvShader::EmitAccessChain(InsnIterator insn, SpirvRoutine *routine) const
{
TypeID typeId = insn.word(1);
ObjectID objectId = insn.word(2);
ObjectID baseId = insn.word(3);
auto &object = getObject(objectId);
auto &type = getType(typeId);
auto &pointerBase = getObject(object.pointerBase);
auto &pointerBaseTy = getType(pointerBase.type);
ASSERT(type.sizeInComponents == 1);
ASSERT(getObject(baseId).pointerBase == object.pointerBase);
if (pointerBaseTy.storageClass == spv::StorageClassImage ||
pointerBaseTy.storageClass == spv::StorageClassUniform ||
pointerBaseTy.storageClass == spv::StorageClassUniformConstant)
{
UNIMPLEMENTED("Descriptor-backed OpAccessChain not yet implemented");
}
auto &dst = routine->createIntermediate(objectId, type.sizeInComponents);
dst.emplace(0, As<SIMD::Float>(WalkAccessChain(baseId, insn.wordCount() - 4, insn.wordPointer(4), routine)));
}
auto &ptrBase = routine->getValue(pointer.pointerBase);
void SpirvShader::EmitStore(InsnIterator insn, SpirvRoutine *routine) const
{
ObjectID pointerId = insn.word(1);
ObjectID objectId = insn.word(2);
auto &object = getObject(objectId);
auto &pointer = getObject(pointerId);
auto &pointerTy = getType(pointer.type);
auto &elementTy = getType(pointerTy.element);
auto &pointerBase = getObject(pointer.pointerBase);
auto &pointerBaseTy = getType(pointerBase.type);
if (pointerBaseTy.storageClass == spv::StorageClassImage ||
pointerBaseTy.storageClass == spv::StorageClassUniform ||
pointerBaseTy.storageClass == spv::StorageClassUniformConstant)
{
UNIMPLEMENTED("Descriptor-backed store not yet implemented");
}
if (object.kind == Object::Kind::Constant)
{
auto src = reinterpret_cast<float *>(object.constantValue.get());
auto &ptrBase = routine->getValue(pointer.pointerBase);
if (pointer.kind == Object::Kind::Value)
{
auto offsets = As<SIMD::Int>(routine->getIntermediate(pointerId)[0]);
for (auto i = 0u; i < elementTy.sizeInComponents; i++)
{
// Scattered store
for (int j = 0; j < SIMD::Width; j++)
{
auto dst = ptrBase[Int(i) + Extract(offsets, j)];
dst = Insert(dst, Float(src[i]), j);
}
}
}
else
if (object.kind == Object::Kind::Constant)
{
auto src = reinterpret_cast<float *>(object.constantValue.get());
if (pointer.kind == Object::Kind::Value)
{
auto offsets = As<SIMD::Int>(routine->getIntermediate(pointerId)[0]);
for (auto i = 0u; i < elementTy.sizeInComponents; i++)
{
// Scattered store
for (int j = 0; j < SIMD::Width; j++)
{
// no divergent offsets
for (auto i = 0u; i < elementTy.sizeInComponents; i++)
{
ptrBase[i] = RValue<SIMD::Float>(src[i]);
}
auto dst = ptrBase[Int(i) + Extract(offsets, j)];
dst = Insert(dst, Float(src[i]), j);
}
}
else
}
else
{
// no divergent offsets
for (auto i = 0u; i < elementTy.sizeInComponents; i++)
{
auto &src = routine->getIntermediate(objectId);
ptrBase[i] = RValue<SIMD::Float>(src[i]);
}
}
}
else
{
auto &src = routine->getIntermediate(objectId);
if (pointer.kind == Object::Kind::Value)
{
auto offsets = As<SIMD::Int>(routine->getIntermediate(pointerId)[0]);
for (auto i = 0u; i < elementTy.sizeInComponents; i++)
{
// Scattered store
for (int j = 0; j < SIMD::Width; j++)
{
auto dst = ptrBase[Int(i) + Extract(offsets, j)];
dst = Insert(dst, Extract(src[i], j), j);
}
}
}
else
if (pointer.kind == Object::Kind::Value)
{
auto offsets = As<SIMD::Int>(routine->getIntermediate(pointerId)[0]);
for (auto i = 0u; i < elementTy.sizeInComponents; i++)
{
// Scattered store
for (int j = 0; j < SIMD::Width; j++)
{
// no divergent offsets
for (auto i = 0u; i < elementTy.sizeInComponents; i++)
{
ptrBase[i] = src[i];
}
auto dst = ptrBase[Int(i) + Extract(offsets, j)];
dst = Insert(dst, Extract(src[i], j), j);
}
}
break;
}
case spv::OpCompositeConstruct:
else
{
auto &type = getType(insn.word(1));
auto &dst = routine->createIntermediate(insn.word(2), type.sizeInComponents);
auto offset = 0u;
for (auto i = 0u; i < insn.wordCount() - 3; i++)
// no divergent offsets
for (auto i = 0u; i < elementTy.sizeInComponents; i++)
{
ObjectID srcObjectId = insn.word(3u + i);
auto & srcObject = getObject(srcObjectId);
auto & srcObjectTy = getType(srcObject.type);
GenericValue srcObjectAccess(this, routine, srcObjectId);
for (auto j = 0u; j < srcObjectTy.sizeInComponents; j++)
dst.emplace(offset++, srcObjectAccess[j]);
ptrBase[i] = src[i];
}
break;
}
case spv::OpCompositeInsert:
}
}
void SpirvShader::EmitCompositeConstruct(InsnIterator insn, SpirvRoutine *routine) const
{
auto &type = getType(insn.word(1));
auto &dst = routine->createIntermediate(insn.word(2), type.sizeInComponents);
auto offset = 0u;
for (auto i = 0u; i < insn.wordCount() - 3; i++)
{
ObjectID srcObjectId = insn.word(3u + i);
auto & srcObject = getObject(srcObjectId);
auto & srcObjectTy = getType(srcObject.type);
GenericValue srcObjectAccess(this, routine, srcObjectId);
for (auto j = 0u; j < srcObjectTy.sizeInComponents; j++)
dst.emplace(offset++, srcObjectAccess[j]);
}
}
void SpirvShader::EmitCompositeInsert(InsnIterator insn, SpirvRoutine *routine) const
{
TypeID resultTypeId = insn.word(1);
auto &type = getType(resultTypeId);
auto &dst = routine->createIntermediate(insn.word(2), type.sizeInComponents);
auto &newPartObject = getObject(insn.word(3));
auto &newPartObjectTy = getType(newPartObject.type);
auto firstNewComponent = WalkLiteralAccessChain(resultTypeId, insn.wordCount() - 5, insn.wordPointer(5));
GenericValue srcObjectAccess(this, routine, insn.word(4));
GenericValue newPartObjectAccess(this, routine, insn.word(3));
// old components before
for (auto i = 0u; i < firstNewComponent; i++)
{
dst.emplace(i, srcObjectAccess[i]);
}
// new part
for (auto i = 0u; i < newPartObjectTy.sizeInComponents; i++)
{
dst.emplace(firstNewComponent + i, newPartObjectAccess[i]);
}
// old components after
for (auto i = firstNewComponent + newPartObjectTy.sizeInComponents; i < type.sizeInComponents; i++)
{
dst.emplace(i, srcObjectAccess[i]);
}
}
void SpirvShader::EmitCompositeExtract(InsnIterator insn, SpirvRoutine *routine) const
{
auto &type = getType(insn.word(1));
auto &dst = routine->createIntermediate(insn.word(2), type.sizeInComponents);
auto &compositeObject = getObject(insn.word(3));
TypeID compositeTypeId = compositeObject.definition.word(1);
auto firstComponent = WalkLiteralAccessChain(compositeTypeId, insn.wordCount() - 4, insn.wordPointer(4));
GenericValue compositeObjectAccess(this, routine, insn.word(3));
for (auto i = 0u; i < type.sizeInComponents; i++)
{
dst.emplace(i, compositeObjectAccess[firstComponent + i]);
}
}
void SpirvShader::EmitVectorShuffle(InsnIterator insn, SpirvRoutine *routine) const
{
auto &type = getType(insn.word(1));
auto &dst = routine->createIntermediate(insn.word(2), type.sizeInComponents);
GenericValue firstHalfAccess(this, routine, insn.word(3));
GenericValue secondHalfAccess(this, routine, insn.word(4));
for (auto i = 0u; i < type.sizeInComponents; i++)
{
auto selector = insn.word(5 + i);
if (selector == static_cast<uint32_t>(-1))
{
TypeID resultTypeId = insn.word(1);
auto &type = getType(resultTypeId);
auto &dst = routine->createIntermediate(insn.word(2), type.sizeInComponents);
auto &newPartObject = getObject(insn.word(3));
auto &newPartObjectTy = getType(newPartObject.type);
auto firstNewComponent = WalkLiteralAccessChain(resultTypeId, insn.wordCount() - 5, insn.wordPointer(5));
GenericValue srcObjectAccess(this, routine, insn.word(4));
GenericValue newPartObjectAccess(this, routine, insn.word(3));
// old components before
for (auto i = 0u; i < firstNewComponent; i++)
dst.emplace(i, srcObjectAccess[i]);
// new part
for (auto i = 0u; i < newPartObjectTy.sizeInComponents; i++)
dst.emplace(firstNewComponent + i, newPartObjectAccess[i]);
// old components after
for (auto i = firstNewComponent + newPartObjectTy.sizeInComponents; i < type.sizeInComponents; i++)
dst.emplace(i, srcObjectAccess[i]);
break;
// Undefined value. Until we decide to do real undef values, zero is as good
// a value as any
dst.emplace(i, RValue<SIMD::Float>(0.0f));
}
case spv::OpCompositeExtract:
else if (selector < type.sizeInComponents)
{
auto &type = getType(insn.word(1));
auto &dst = routine->createIntermediate(insn.word(2), type.sizeInComponents);
auto &compositeObject = getObject(insn.word(3));
TypeID compositeTypeId = compositeObject.definition.word(1);
auto firstComponent = WalkLiteralAccessChain(compositeTypeId, insn.wordCount() - 4, insn.wordPointer(4));
GenericValue compositeObjectAccess(this, routine, insn.word(3));
for (auto i = 0u; i < type.sizeInComponents; i++)
dst.emplace(i, compositeObjectAccess[firstComponent + i]);
break;
dst.emplace(i, firstHalfAccess[selector]);
}
case spv::OpVectorShuffle:
else
{
auto &type = getType(insn.word(1));
auto &dst = routine->createIntermediate(insn.word(2), type.sizeInComponents);
GenericValue firstHalfAccess(this, routine, insn.word(3));
GenericValue secondHalfAccess(this, routine, insn.word(4));
for (auto i = 0u; i < type.sizeInComponents; i++)
{
auto selector = insn.word(5 + i);
if (selector == static_cast<uint32_t>(-1))
{
// Undefined value. Until we decide to do real undef values, zero is as good
// a value as any
dst.emplace(i, RValue<SIMD::Float>(0.0f));
}
else if (selector < type.sizeInComponents)
{
dst.emplace(i, firstHalfAccess[selector]);
}
else
{
dst.emplace(i, secondHalfAccess[selector - type.sizeInComponents]);
}
}
break;
}
default:
printf("emit: ignoring opcode %s\n", OpcodeName(insn.opcode()).c_str());
break;
dst.emplace(i, secondHalfAccess[selector - type.sizeInComponents]);
}
}
}
......
......@@ -381,6 +381,16 @@ namespace sw
SIMD::Int WalkAccessChain(ObjectID id, uint32_t numIndexes, uint32_t const *indexIds, SpirvRoutine *routine) const;
uint32_t WalkLiteralAccessChain(TypeID id, uint32_t numIndexes, uint32_t const *indexes) const;
// Emit pass instructions:
void EmitVariable(InsnIterator insn, SpirvRoutine *routine) const;
void EmitLoad(InsnIterator insn, SpirvRoutine *routine) const;
void EmitStore(InsnIterator insn, SpirvRoutine *routine) const;
void EmitAccessChain(InsnIterator insn, SpirvRoutine *routine) const;
void EmitCompositeConstruct(InsnIterator insn, SpirvRoutine *routine) const;
void EmitCompositeInsert(InsnIterator insn, SpirvRoutine *routine) const;
void EmitCompositeExtract(InsnIterator insn, SpirvRoutine *routine) const;
void EmitVectorShuffle(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.
static std::string OpcodeName(spv::Op op);
......
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