From: Ben Clayton Date: Tue, 26 Feb 2019 11:02:42 +0000 (+0000) Subject: SpirvShader: Add SIMD namespace. X-Git-Tag: android-x86-9.0-r1~282 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=24ea5159b330bb7c16be025eb120d9d30f551b90;p=android-x86%2Fexternal-swiftshader.git 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 Reviewed-by: Chris Forbes Tested-by: Ben Clayton --- diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp index bfdf462ea..96f88f493 100644 --- a/src/Pipeline/SpirvShader.cpp +++ b/src/Pipeline/SpirvShader.cpp @@ -548,20 +548,20 @@ namespace sw VisitInterfaceInner(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: avoid doing per-lane work in some cases if we can? int constantOffset = 0; - Int4 dynamicOffset = Int4(0); + SIMD::Int dynamicOffset = SIMD::Int(0); auto &baseObject = getObject(id); TypeID typeId = getType(baseObject.type).element; // The operand is an intermediate value itself, ie produced by a previous OpAccessChain. // Start with its offset and build from there. if (baseObject.kind == Object::Kind::Value) - dynamicOffset += As(routine->getIntermediate(id)[0]); + dynamicOffset += As(routine->getIntermediate(id)[0]); for (auto i = 0u; i < numIndexes; i++) { @@ -590,7 +590,7 @@ namespace sw if (obj.kind == Object::Kind::Constant) constantOffset += stride * GetConstantInt(indexIds[i]); else - dynamicOffset += Int4(stride) * As(routine->getIntermediate(indexIds[i])[0]); + dynamicOffset += SIMD::Int(stride) * As(routine->getIntermediate(indexIds[i])[0]); typeId = type.element; break; } @@ -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 @@ -853,12 +853,12 @@ namespace sw if (pointer.kind == Object::Kind::Value) { - auto offsets = As(routine->getIntermediate(insn.word(3))[0]); + auto offsets = As(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.. - Float4 v; - for (int j = 0; j < 4; j++) + 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); @@ -895,7 +895,7 @@ namespace sw UNIMPLEMENTED("Descriptor-backed OpAccessChain not yet implemented"); } auto &dst = routine->createIntermediate(objectId, type.sizeInComponents); - dst.emplace(0, As(WalkAccessChain(baseId, insn.wordCount() - 4, insn.wordPointer(4), routine))); + dst.emplace(0, As(WalkAccessChain(baseId, insn.wordCount() - 4, insn.wordPointer(4), routine))); break; } case spv::OpStore: @@ -924,11 +924,11 @@ namespace sw if (pointer.kind == Object::Kind::Value) { - auto offsets = As(routine->getIntermediate(pointerId)[0]); + auto offsets = As(routine->getIntermediate(pointerId)[0]); for (auto i = 0u; i < elementTy.sizeInComponents; i++) { // 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)]; dst = Insert(dst, Float(src[i]), j); @@ -940,7 +940,7 @@ namespace sw // no divergent offsets for (auto i = 0u; i < elementTy.sizeInComponents; i++) { - ptrBase[i] = RValue(src[i]); + ptrBase[i] = RValue(src[i]); } } } @@ -950,11 +950,11 @@ namespace sw if (pointer.kind == Object::Kind::Value) { - auto offsets = As(routine->getIntermediate(pointerId)[0]); + auto offsets = As(routine->getIntermediate(pointerId)[0]); for (auto i = 0u; i < elementTy.sizeInComponents; i++) { // 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)]; dst = Insert(dst, Extract(src[i], j), j); @@ -1041,7 +1041,7 @@ namespace sw { // Undefined value. Until we decide to do real undef values, zero is as good // a value as any - dst.emplace(i, RValue(0.0f)); + dst.emplace(i, RValue(0.0f)); } else if (selector < type.sizeInComponents) { diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp index 6d4a8e418..96302d724 100644 --- a/src/Pipeline/SpirvShader.hpp +++ b/src/Pipeline/SpirvShader.hpp @@ -31,6 +31,22 @@ 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 // Effectively a restricted vector, supporting only: // - allocation to a (runtime-known) fixed size @@ -39,7 +55,7 @@ namespace sw class Intermediate { public: - using Scalar = RValue; + using Scalar = RValue; Intermediate(uint32_t size) : contents(new ContentsType[size]), size(size) {} @@ -56,6 +72,12 @@ namespace sw 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 { assert(n < size); @@ -75,8 +97,6 @@ namespace sw uint32_t size; }; - class SpirvRoutine; - class SpirvShader { public: @@ -348,14 +368,15 @@ namespace sw 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; }; class SpirvRoutine { public: - using Value = Array; + using Value = Array; + std::unordered_map lvalues; std::unordered_map intermediates; @@ -406,13 +427,13 @@ namespace sw obj(shader->getObject(objId)), intermediate(obj.kind == SpirvShader::Object::Kind::Value ? &routine->getIntermediate(objId) : nullptr) {} - RValue operator[](uint32_t i) const + RValue operator[](uint32_t i) const { if (intermediate) return (*intermediate)[i]; auto constantValue = reinterpret_cast(obj.constantValue.get()); - return RValue(constantValue[i]); + return RValue(constantValue[i]); } };