Commit fabdec51 by Nicolas Capens Committed by Nicolas Capens

Use a C array for temporary load results

Array<> emits GEP instructions on every access, which aren't necessary. Note that these temporaries are required because the If/Else blocks both write to them, while the destination intermediate object is an rvalue which can only be initialized once to maintain SSA form. Also EmitAccessChain was moved to match the declaration order. Bug b/128539387 Change-Id: I726fb0fd28b0a19a61e8759679e30bc699f3279d Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/27788 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
parent 5e8414e4
...@@ -1387,16 +1387,16 @@ namespace sw ...@@ -1387,16 +1387,16 @@ namespace sw
void SpirvShader::EmitLoad(InsnIterator insn, SpirvRoutine *routine) const void SpirvShader::EmitLoad(InsnIterator insn, SpirvRoutine *routine) const
{ {
Object::ID objectId = insn.word(2); Object::ID resultId = insn.word(2);
Object::ID pointerId = insn.word(3); Object::ID pointerId = insn.word(3);
auto &object = getObject(objectId); auto &result = getObject(resultId);
auto &objectTy = getType(object.type); auto &resultTy = getType(result.type);
auto &pointer = getObject(pointerId); auto &pointer = getObject(pointerId);
auto &pointerBase = getObject(pointer.pointerBase); auto &pointerBase = getObject(pointer.pointerBase);
auto &pointerBaseTy = getType(pointerBase.type); auto &pointerBaseTy = getType(pointerBase.type);
ASSERT(getType(pointer.type).element == object.type); ASSERT(getType(pointer.type).element == result.type);
ASSERT(Type::ID(insn.word(1)) == object.type); ASSERT(Type::ID(insn.word(1)) == result.type);
ASSERT((insn.opcode() != spv::OpAtomicLoad) || getType(getType(pointer.type).element).opcode() == spv::OpTypeInt); // Vulkan 1.1: "Atomic instructions must declare a scalar 32-bit integer type, for the value pointed to by Pointer." ASSERT((insn.opcode() != spv::OpAtomicLoad) || getType(getType(pointer.type).element).opcode() == spv::OpTypeInt); // Vulkan 1.1: "Atomic instructions must declare a scalar 32-bit integer type, for the value pointed to by Pointer."
if (pointerBaseTy.storageClass == spv::StorageClassImage) if (pointerBaseTy.storageClass == spv::StorageClassImage)
...@@ -1417,7 +1417,7 @@ namespace sw ...@@ -1417,7 +1417,7 @@ namespace sw
bool interleavedByLane = IsStorageInterleavedByLane(pointerBaseTy.storageClass); bool interleavedByLane = IsStorageInterleavedByLane(pointerBaseTy.storageClass);
auto anyInactiveLanes = SignMask(~routine->activeLaneMask) != 0; auto anyInactiveLanes = SignMask(~routine->activeLaneMask) != 0;
auto load = SpirvRoutine::Value(objectTy.sizeInComponents); auto load = std::unique_ptr<SIMD::Float[]>(new SIMD::Float[resultTy.sizeInComponents]);
If(pointer.kind == Object::Kind::Value || anyInactiveLanes) If(pointer.kind == Object::Kind::Value || anyInactiveLanes)
{ {
...@@ -1425,7 +1425,7 @@ namespace sw ...@@ -1425,7 +1425,7 @@ namespace sw
auto offsets = pointer.kind == Object::Kind::Value ? auto offsets = pointer.kind == Object::Kind::Value ?
As<SIMD::Int>(routine->getIntermediate(pointerId).Int(0)) : As<SIMD::Int>(routine->getIntermediate(pointerId).Int(0)) :
RValue<SIMD::Int>(SIMD::Int(0)); RValue<SIMD::Int>(SIMD::Int(0));
for (auto i = 0u; i < objectTy.sizeInComponents; i++) for (auto i = 0u; i < resultTy.sizeInComponents; i++)
{ {
// i wish i had a Float,Float,Float,Float constructor here.. // i wish i had a Float,Float,Float,Float constructor here..
for (int j = 0; j < SIMD::Width; j++) for (int j = 0; j < SIMD::Width; j++)
...@@ -1446,7 +1446,7 @@ namespace sw ...@@ -1446,7 +1446,7 @@ namespace sw
{ {
// Lane-interleaved data. // Lane-interleaved data.
Pointer<SIMD::Float> src = ptrBase; Pointer<SIMD::Float> src = ptrBase;
for (auto i = 0u; i < objectTy.sizeInComponents; i++) for (auto i = 0u; i < resultTy.sizeInComponents; i++)
{ {
load[i] = src[i]; load[i] = src[i];
} }
...@@ -1454,45 +1454,20 @@ namespace sw ...@@ -1454,45 +1454,20 @@ namespace sw
else else
{ {
// Non-interleaved data. // Non-interleaved data.
for (auto i = 0u; i < objectTy.sizeInComponents; i++) for (auto i = 0u; i < resultTy.sizeInComponents; i++)
{ {
load[i] = RValue<SIMD::Float>(ptrBase[i]); load[i] = RValue<SIMD::Float>(ptrBase[i]);
} }
} }
} }
auto &dst = routine->createIntermediate(objectId, objectTy.sizeInComponents); auto &dst = routine->createIntermediate(resultId, resultTy.sizeInComponents);
for (auto i = 0u; i < objectTy.sizeInComponents; i++) for (auto i = 0u; i < resultTy.sizeInComponents; i++)
{ {
dst.move(i, load[i]); dst.move(i, load[i]);
} }
} }
void SpirvShader::EmitAccessChain(InsnIterator insn, SpirvRoutine *routine) const
{
Type::ID typeId = insn.word(1);
Object::ID resultId = insn.word(2);
Object::ID baseId = insn.word(3);
uint32_t numIndexes = insn.wordCount() - 4;
const uint32_t *indexes = insn.wordPointer(4);
auto &type = getType(typeId);
ASSERT(type.sizeInComponents == 1);
ASSERT(getObject(baseId).pointerBase == getObject(resultId).pointerBase);
auto &dst = routine->createIntermediate(resultId, type.sizeInComponents);
if(type.storageClass == spv::StorageClassPushConstant ||
type.storageClass == spv::StorageClassUniform ||
type.storageClass == spv::StorageClassStorageBuffer)
{
dst.move(0, WalkExplicitLayoutAccessChain(baseId, numIndexes, indexes, routine));
}
else
{
dst.move(0, WalkAccessChain(baseId, numIndexes, indexes, routine));
}
}
void SpirvShader::EmitStore(InsnIterator insn, SpirvRoutine *routine) const void SpirvShader::EmitStore(InsnIterator insn, SpirvRoutine *routine) const
{ {
bool atomic = (insn.opcode() == spv::OpAtomicStore); bool atomic = (insn.opcode() == spv::OpAtomicStore);
...@@ -1607,6 +1582,31 @@ namespace sw ...@@ -1607,6 +1582,31 @@ namespace sw
} }
} }
void SpirvShader::EmitAccessChain(InsnIterator insn, SpirvRoutine *routine) const
{
Type::ID typeId = insn.word(1);
Object::ID resultId = insn.word(2);
Object::ID baseId = insn.word(3);
uint32_t numIndexes = insn.wordCount() - 4;
const uint32_t *indexes = insn.wordPointer(4);
auto &type = getType(typeId);
ASSERT(type.sizeInComponents == 1);
ASSERT(getObject(baseId).pointerBase == getObject(resultId).pointerBase);
auto &dst = routine->createIntermediate(resultId, type.sizeInComponents);
if(type.storageClass == spv::StorageClassPushConstant ||
type.storageClass == spv::StorageClassUniform ||
type.storageClass == spv::StorageClassStorageBuffer)
{
dst.move(0, WalkExplicitLayoutAccessChain(baseId, numIndexes, indexes, routine));
}
else
{
dst.move(0, WalkAccessChain(baseId, numIndexes, indexes, routine));
}
}
void SpirvShader::EmitCompositeConstruct(InsnIterator insn, SpirvRoutine *routine) const void SpirvShader::EmitCompositeConstruct(InsnIterator insn, SpirvRoutine *routine) const
{ {
auto &type = getType(insn.word(1)); auto &type = getType(insn.word(1));
......
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