Commit 0ea9fe43 by Ben Clayton

SpirvShader: Split SIMD::Pointer limits into dynamic and static parts.

Currently does not do anything differently, but is a stepping stone to optimizations. Bug: b/135609394 Change-Id: I9020d4819b0e6f4bdd9564c2407c1903b7f33f4f Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/33052Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
parent 867ee1d6
...@@ -291,7 +291,7 @@ namespace sw ...@@ -291,7 +291,7 @@ namespace sw
{ {
using EL = typename Element<T>::type; using EL = typename Element<T>::type;
auto offsets = ptr.offsets(); auto offsets = ptr.offsets();
mask &= CmpLT(offsets + SIMD::Int(sizeof(float) - 1), SIMD::Int(ptr.limit)); // Disable OOB reads. mask &= ptr.isInBounds(sizeof(float)); // Disable OOB reads.
if (!atomic && order == std::memory_order_relaxed) if (!atomic && order == std::memory_order_relaxed)
{ {
return rr::Gather(rr::Pointer<EL>(ptr.base), offsets, mask, sizeof(float)); return rr::Gather(rr::Pointer<EL>(ptr.base), offsets, mask, sizeof(float));
...@@ -335,7 +335,7 @@ namespace sw ...@@ -335,7 +335,7 @@ namespace sw
{ {
using EL = typename Element<T>::type; using EL = typename Element<T>::type;
auto offsets = ptr.offsets(); auto offsets = ptr.offsets();
mask &= CmpLT(offsets + SIMD::Int(sizeof(float) - 1), SIMD::Int(ptr.limit)); // Disable OOB reads. mask &= ptr.isInBounds(sizeof(float)); // Disable OOB writes.
if (!atomic && order == std::memory_order_relaxed) if (!atomic && order == std::memory_order_relaxed)
{ {
return rr::Scatter(rr::Pointer<EL>(ptr.base), val, offsets, mask, sizeof(float)); return rr::Scatter(rr::Pointer<EL>(ptr.base), val, offsets, mask, sizeof(float));
...@@ -5863,7 +5863,7 @@ namespace sw ...@@ -5863,7 +5863,7 @@ namespace sw
ASSERT(d.HasOffset); ASSERT(d.HasOffset);
auto arrayBase = structBase + d.Offset; auto arrayBase = structBase + d.Offset;
auto arraySizeInBytes = SIMD::Int(arrayBase.limit) - arrayBase.offsets(); auto arraySizeInBytes = SIMD::Int(arrayBase.limit()) - arrayBase.offsets();
auto arrayLength = arraySizeInBytes / SIMD::Int(arrayElTy.sizeInComponents * sizeof(float)); auto arrayLength = arraySizeInBytes / SIMD::Int(arrayElTy.sizeInComponents * sizeof(float));
result.move(0, SIMD::Int(arrayLength)); result.move(0, SIMD::Int(arrayLength));
......
...@@ -72,9 +72,28 @@ namespace sw ...@@ -72,9 +72,28 @@ namespace sw
struct Pointer struct Pointer
{ {
Pointer(rr::Pointer<Byte> base, rr::Int limit) Pointer(rr::Pointer<Byte> base, rr::Int limit)
: base(base), limit(limit), dynamicOffsets(0), staticOffsets{}, hasDynamicOffsets(false) {} : base(base),
dynamicLimit(limit), staticLimit(0),
dynamicOffsets(0), staticOffsets{},
hasDynamicLimit(true), hasDynamicOffsets(false) {}
Pointer(rr::Pointer<Byte> base, unsigned int limit)
: base(base),
dynamicLimit(0), staticLimit(limit),
dynamicOffsets(0), staticOffsets{},
hasDynamicLimit(false), hasDynamicOffsets(false) {}
Pointer(rr::Pointer<Byte> base, rr::Int limit, SIMD::Int offset) Pointer(rr::Pointer<Byte> base, rr::Int limit, SIMD::Int offset)
: base(base), limit(limit), dynamicOffsets(offset), staticOffsets{}, hasDynamicOffsets(true) {} : base(base),
dynamicLimit(limit), staticLimit(0),
dynamicOffsets(offset), staticOffsets{},
hasDynamicLimit(true), hasDynamicOffsets(true) {}
Pointer(rr::Pointer<Byte> base, unsigned int limit, SIMD::Int offset)
: base(base),
dynamicLimit(0), staticLimit(limit),
dynamicOffsets(offset), staticOffsets{},
hasDynamicLimit(false), hasDynamicOffsets(true) {}
inline Pointer& operator += (Int i) inline Pointer& operator += (Int i)
{ {
...@@ -119,6 +138,18 @@ namespace sw ...@@ -119,6 +138,18 @@ namespace sw
return dynamicOffsets + SIMD::Int(staticOffsets[0], staticOffsets[1], staticOffsets[2], staticOffsets[3]); return dynamicOffsets + SIMD::Int(staticOffsets[0], staticOffsets[1], staticOffsets[2], staticOffsets[3]);
} }
inline SIMD::Int isInBounds(unsigned int accessSize) const
{
ASSERT(accessSize > 0);
return CmpLT(offsets() + SIMD::Int(accessSize - 1), SIMD::Int(limit()));
}
inline Int limit() const
{
return dynamicLimit + staticLimit;
}
// Returns true if all offsets are sequential (N+0, N+1, N+2, N+3) // Returns true if all offsets are sequential (N+0, N+1, N+2, N+3)
inline rr::Bool hasSequentialOffsets() const inline rr::Bool hasSequentialOffsets() const
{ {
...@@ -161,14 +192,15 @@ namespace sw ...@@ -161,14 +192,15 @@ namespace sw
rr::Pointer<rr::Byte> base; rr::Pointer<rr::Byte> base;
// Upper (non-inclusive) limit for offsets from base. // Upper (non-inclusive) limit for offsets from base.
rr::Int limit; rr::Int dynamicLimit; // If hasDynamicLimit is false, dynamicLimit is zero.
unsigned int staticLimit;
// Per lane offsets from base. // Per lane offsets from base.
SIMD::Int dynamicOffsets; // If hasDynamicOffsets is false, all dynamicOffsets are zero. SIMD::Int dynamicOffsets; // If hasDynamicOffsets is false, all dynamicOffsets are zero.
std::array<int32_t, SIMD::Width> staticOffsets; std::array<int32_t, SIMD::Width> staticOffsets;
// True if all dynamicOffsets are zero. bool hasDynamicLimit; // True if dynamicLimit is zero.
bool hasDynamicOffsets; bool hasDynamicOffsets; // True if all dynamicOffsets are zero.
}; };
template <typename T> struct Element {}; template <typename T> struct Element {};
......
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