Commit 24ea5159 by Ben Clayton Committed by Ben Clayton

SpirvShader: Add SIMD namespace.

This namespace declares typedefs that represent per-lane-scalars. Once we start mixing per-lane storage with linear external memory, this will help readability. Bug: b/126126820 Change-Id: Ia128c3cc97dd77b3d5c4b7bd9537c19427a9ac3f Reviewed-on: https://swiftshader-review.googlesource.com/c/25548 Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com>
parent 83fc5445
...@@ -548,20 +548,20 @@ namespace sw ...@@ -548,20 +548,20 @@ namespace sw
VisitInterfaceInner<F>(def.word(1), d, f); VisitInterfaceInner<F>(def.word(1), d, f);
} }
Int4 SpirvShader::WalkAccessChain(ObjectID id, uint32_t numIndexes, uint32_t const *indexIds, SpirvRoutine *routine) const SIMD::Int SpirvShader::WalkAccessChain(ObjectID id, uint32_t numIndexes, uint32_t const *indexIds, SpirvRoutine *routine) const
{ {
// TODO: think about explicit layout (UBO/SSBO) storage classes // TODO: think about explicit layout (UBO/SSBO) storage classes
// TODO: avoid doing per-lane work in some cases if we can? // TODO: avoid doing per-lane work in some cases if we can?
int constantOffset = 0; int constantOffset = 0;
Int4 dynamicOffset = Int4(0); SIMD::Int dynamicOffset = SIMD::Int(0);
auto &baseObject = getObject(id); auto &baseObject = getObject(id);
TypeID typeId = getType(baseObject.type).element; TypeID typeId = getType(baseObject.type).element;
// The <base> operand is an intermediate value itself, ie produced by a previous OpAccessChain. // The <base> operand is an intermediate value itself, ie produced by a previous OpAccessChain.
// Start with its offset and build from there. // Start with its offset and build from there.
if (baseObject.kind == Object::Kind::Value) if (baseObject.kind == Object::Kind::Value)
dynamicOffset += As<Int4>(routine->getIntermediate(id)[0]); dynamicOffset += As<SIMD::Int>(routine->getIntermediate(id)[0]);
for (auto i = 0u; i < numIndexes; i++) for (auto i = 0u; i < numIndexes; i++)
{ {
...@@ -590,7 +590,7 @@ namespace sw ...@@ -590,7 +590,7 @@ namespace sw
if (obj.kind == Object::Kind::Constant) if (obj.kind == Object::Kind::Constant)
constantOffset += stride * GetConstantInt(indexIds[i]); constantOffset += stride * GetConstantInt(indexIds[i]);
else else
dynamicOffset += Int4(stride) * As<Int4>(routine->getIntermediate(indexIds[i])[0]); dynamicOffset += SIMD::Int(stride) * As<SIMD::Int>(routine->getIntermediate(indexIds[i])[0]);
typeId = type.element; typeId = type.element;
break; break;
} }
...@@ -600,7 +600,7 @@ namespace sw ...@@ -600,7 +600,7 @@ namespace sw
} }
} }
return dynamicOffset + Int4(constantOffset); return dynamicOffset + SIMD::Int(constantOffset);
} }
uint32_t SpirvShader::WalkLiteralAccessChain(TypeID typeId, uint32_t numIndexes, uint32_t const *indexes) const uint32_t SpirvShader::WalkLiteralAccessChain(TypeID typeId, uint32_t numIndexes, uint32_t const *indexes) const
...@@ -853,12 +853,12 @@ namespace sw ...@@ -853,12 +853,12 @@ namespace sw
if (pointer.kind == Object::Kind::Value) if (pointer.kind == Object::Kind::Value)
{ {
auto offsets = As<Int4>(routine->getIntermediate(insn.word(3))[0]); auto offsets = As<SIMD::Int>(routine->getIntermediate(insn.word(3))[0]);
for (auto i = 0u; i < objectTy.sizeInComponents; i++) for (auto i = 0u; i < objectTy.sizeInComponents; i++)
{ {
// i wish i had a Float,Float,Float,Float constructor here.. // i wish i had a Float,Float,Float,Float constructor here..
Float4 v; SIMD::Float v;
for (int j = 0; j < 4; j++) for (int j = 0; j < SIMD::Width; j++)
{ {
Int offset = Int(i) + Extract(offsets, j); Int offset = Int(i) + Extract(offsets, j);
v = Insert(v, Extract(ptrBase[offset], j), j); v = Insert(v, Extract(ptrBase[offset], j), j);
...@@ -895,7 +895,7 @@ namespace sw ...@@ -895,7 +895,7 @@ namespace sw
UNIMPLEMENTED("Descriptor-backed OpAccessChain not yet implemented"); UNIMPLEMENTED("Descriptor-backed OpAccessChain not yet implemented");
} }
auto &dst = routine->createIntermediate(objectId, type.sizeInComponents); auto &dst = routine->createIntermediate(objectId, type.sizeInComponents);
dst.emplace(0, As<Float4>(WalkAccessChain(baseId, insn.wordCount() - 4, insn.wordPointer(4), routine))); dst.emplace(0, As<SIMD::Float>(WalkAccessChain(baseId, insn.wordCount() - 4, insn.wordPointer(4), routine)));
break; break;
} }
case spv::OpStore: case spv::OpStore:
...@@ -924,11 +924,11 @@ namespace sw ...@@ -924,11 +924,11 @@ namespace sw
if (pointer.kind == Object::Kind::Value) if (pointer.kind == Object::Kind::Value)
{ {
auto offsets = As<Int4>(routine->getIntermediate(pointerId)[0]); auto offsets = As<SIMD::Int>(routine->getIntermediate(pointerId)[0]);
for (auto i = 0u; i < elementTy.sizeInComponents; i++) for (auto i = 0u; i < elementTy.sizeInComponents; i++)
{ {
// Scattered store // Scattered store
for (int j = 0; j < 4; j++) for (int j = 0; j < SIMD::Width; j++)
{ {
auto dst = ptrBase[Int(i) + Extract(offsets, j)]; auto dst = ptrBase[Int(i) + Extract(offsets, j)];
dst = Insert(dst, Float(src[i]), j); dst = Insert(dst, Float(src[i]), j);
...@@ -940,7 +940,7 @@ namespace sw ...@@ -940,7 +940,7 @@ namespace sw
// no divergent offsets // no divergent offsets
for (auto i = 0u; i < elementTy.sizeInComponents; i++) for (auto i = 0u; i < elementTy.sizeInComponents; i++)
{ {
ptrBase[i] = RValue<Float4>(src[i]); ptrBase[i] = RValue<SIMD::Float>(src[i]);
} }
} }
} }
...@@ -950,11 +950,11 @@ namespace sw ...@@ -950,11 +950,11 @@ namespace sw
if (pointer.kind == Object::Kind::Value) if (pointer.kind == Object::Kind::Value)
{ {
auto offsets = As<Int4>(routine->getIntermediate(pointerId)[0]); auto offsets = As<SIMD::Int>(routine->getIntermediate(pointerId)[0]);
for (auto i = 0u; i < elementTy.sizeInComponents; i++) for (auto i = 0u; i < elementTy.sizeInComponents; i++)
{ {
// Scattered store // Scattered store
for (int j = 0; j < 4; j++) for (int j = 0; j < SIMD::Width; j++)
{ {
auto dst = ptrBase[Int(i) + Extract(offsets, j)]; auto dst = ptrBase[Int(i) + Extract(offsets, j)];
dst = Insert(dst, Extract(src[i], j), j); dst = Insert(dst, Extract(src[i], j), j);
...@@ -1041,7 +1041,7 @@ namespace sw ...@@ -1041,7 +1041,7 @@ namespace sw
{ {
// Undefined value. Until we decide to do real undef values, zero is as good // Undefined value. Until we decide to do real undef values, zero is as good
// a value as any // a value as any
dst.emplace(i, RValue<Float4>(0.0f)); dst.emplace(i, RValue<SIMD::Float>(0.0f));
} }
else if (selector < type.sizeInComponents) else if (selector < type.sizeInComponents)
{ {
......
...@@ -31,6 +31,22 @@ ...@@ -31,6 +31,22 @@
namespace sw namespace sw
{ {
// Forward declarations.
class SpirvRoutine;
// SIMD contains types that represent multiple scalars packed into a single
// vector data type. Types in the SIMD namespace provide a semantic hint
// that the data should be treated as a per-execution-lane scalar instead of
// a typical euclidean-style vector type.
namespace SIMD
{
// Width is the number of per-lane scalars packed into each SIMD vector.
static constexpr int Width = 4;
using Float = rr::Float4;
using Int = rr::Int4;
}
// Incrementally constructed complex bundle of rvalues // Incrementally constructed complex bundle of rvalues
// Effectively a restricted vector, supporting only: // Effectively a restricted vector, supporting only:
// - allocation to a (runtime-known) fixed size // - allocation to a (runtime-known) fixed size
...@@ -39,7 +55,7 @@ namespace sw ...@@ -39,7 +55,7 @@ namespace sw
class Intermediate class Intermediate
{ {
public: public:
using Scalar = RValue<Float4>; using Scalar = RValue<SIMD::Float>;
Intermediate(uint32_t size) : contents(new ContentsType[size]), size(size) {} Intermediate(uint32_t size) : contents(new ContentsType[size]), size(size) {}
...@@ -56,6 +72,12 @@ namespace sw ...@@ -56,6 +72,12 @@ namespace sw
new (&contents[n]) Scalar(value); new (&contents[n]) Scalar(value);
} }
void emplace(uint32_t n, const Scalar& value)
{
assert(n < size);
new (&contents[n]) Scalar(value);
}
Scalar const & operator[](uint32_t n) const Scalar const & operator[](uint32_t n) const
{ {
assert(n < size); assert(n < size);
...@@ -75,8 +97,6 @@ namespace sw ...@@ -75,8 +97,6 @@ namespace sw
uint32_t size; uint32_t size;
}; };
class SpirvRoutine;
class SpirvShader class SpirvShader
{ {
public: public:
...@@ -348,14 +368,15 @@ namespace sw ...@@ -348,14 +368,15 @@ namespace sw
void ProcessInterfaceVariable(Object &object); void ProcessInterfaceVariable(Object &object);
Int4 WalkAccessChain(ObjectID id, uint32_t numIndexes, uint32_t const *indexIds, SpirvRoutine *routine) const; 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; uint32_t WalkLiteralAccessChain(TypeID id, uint32_t numIndexes, uint32_t const *indexes) const;
}; };
class SpirvRoutine class SpirvRoutine
{ {
public: public:
using Value = Array<Float4>; using Value = Array<SIMD::Float>;
std::unordered_map<SpirvShader::ObjectID, Value> lvalues; std::unordered_map<SpirvShader::ObjectID, Value> lvalues;
std::unordered_map<SpirvShader::ObjectID, Intermediate> intermediates; std::unordered_map<SpirvShader::ObjectID, Intermediate> intermediates;
...@@ -406,13 +427,13 @@ namespace sw ...@@ -406,13 +427,13 @@ namespace sw
obj(shader->getObject(objId)), obj(shader->getObject(objId)),
intermediate(obj.kind == SpirvShader::Object::Kind::Value ? &routine->getIntermediate(objId) : nullptr) {} intermediate(obj.kind == SpirvShader::Object::Kind::Value ? &routine->getIntermediate(objId) : nullptr) {}
RValue<Float4> operator[](uint32_t i) const RValue<SIMD::Float> operator[](uint32_t i) const
{ {
if (intermediate) if (intermediate)
return (*intermediate)[i]; return (*intermediate)[i];
auto constantValue = reinterpret_cast<float *>(obj.constantValue.get()); auto constantValue = reinterpret_cast<float *>(obj.constantValue.get());
return RValue<Float4>(constantValue[i]); return RValue<SIMD::Float>(constantValue[i]);
} }
}; };
......
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