зеркало из https://github.com/AvaloniaUI/angle.git
Optimize angle::BitSetIterator.
Adds a new custom bitset template to handle packing as many bits as possible into a single variable. Intelligently select the right class depending on platform features and bit sizes. For now, always use a packed 64-bit set on 64-bit, instead of using a 32-bit set for smaller bitsets. BUG=angleproject:1814 Change-Id: I3ffef815c15515555833f6fc9302d8a4eee5423b Reviewed-on: https://chromium-review.googlesource.com/471827 Reviewed-by: Geoff Lang <geofflang@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Родитель
a0e0aebbf2
Коммит
6de5185898
7
BUILD.gn
7
BUILD.gn
|
@ -59,6 +59,13 @@ config("internal_config") {
|
|||
"GL_GLEXT_PROTOTYPES",
|
||||
"EGL_EGLEXT_PROTOTYPES",
|
||||
]
|
||||
|
||||
if (target_cpu == "x86") {
|
||||
defines += [ "ANGLE_X86_CPU" ]
|
||||
}
|
||||
if (target_cpu == "x64") {
|
||||
defines += [ "ANGLE_X64_CPU" ]
|
||||
}
|
||||
}
|
||||
|
||||
config("extra_warnings") {
|
||||
|
|
|
@ -281,6 +281,7 @@
|
|||
'TargetMachine': '1', # x86
|
||||
},
|
||||
},
|
||||
'defines': [ 'ANGLE_X86_CPU' ],
|
||||
}, # x86_Base
|
||||
|
||||
'x64_Base':
|
||||
|
@ -298,6 +299,7 @@
|
|||
'TargetMachine': '17', # x86 - 64
|
||||
},
|
||||
},
|
||||
'defines': [ 'ANGLE_X64_CPU' ],
|
||||
}, # x64_Base
|
||||
|
||||
# Concrete configurations
|
||||
|
|
|
@ -21,13 +21,104 @@
|
|||
|
||||
namespace angle
|
||||
{
|
||||
template <size_t N>
|
||||
class BitSetIterator final
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
class BitSetT final
|
||||
{
|
||||
public:
|
||||
BitSetIterator(const std::bitset<N> &bitset);
|
||||
BitSetIterator(const BitSetIterator &other);
|
||||
BitSetIterator &operator=(const BitSetIterator &other);
|
||||
class Reference final
|
||||
{
|
||||
public:
|
||||
~Reference() {}
|
||||
Reference &operator=(bool x) { mParent->set(mBit, x); }
|
||||
operator bool() const { return mParent->test(mBit); }
|
||||
|
||||
private:
|
||||
friend class BitSetT;
|
||||
|
||||
Reference(BitSetT *parent, std::size_t bit) : mParent(parent), mBit(bit) {}
|
||||
|
||||
BitSetT *mParent;
|
||||
std::size_t mBit;
|
||||
};
|
||||
|
||||
class Iterator final
|
||||
{
|
||||
public:
|
||||
Iterator(const BitSetT &bits);
|
||||
Iterator &operator++();
|
||||
|
||||
bool operator==(const Iterator &other) const;
|
||||
bool operator!=(const Iterator &other) const;
|
||||
std::size_t operator*() const;
|
||||
|
||||
private:
|
||||
std::size_t getNextBit();
|
||||
|
||||
BitSetT mBitsCopy;
|
||||
std::size_t mCurrentBit;
|
||||
};
|
||||
|
||||
BitSetT();
|
||||
BitSetT(BitsT value);
|
||||
~BitSetT();
|
||||
|
||||
BitSetT(const BitSetT &other);
|
||||
BitSetT &operator=(const BitSetT &other);
|
||||
|
||||
bool operator==(const BitSetT &other) const;
|
||||
bool operator!=(const BitSetT &other) const;
|
||||
|
||||
constexpr bool operator[](std::size_t pos) const;
|
||||
Reference operator[](std::size_t pos) { return Reference(this, pos); }
|
||||
|
||||
bool test(std::size_t pos) const;
|
||||
|
||||
bool all() const;
|
||||
bool any() const;
|
||||
bool none() const;
|
||||
std::size_t count() const;
|
||||
|
||||
constexpr std::size_t size() const { return N; }
|
||||
|
||||
BitSetT &operator&=(const BitSetT &other);
|
||||
BitSetT &operator|=(const BitSetT &other);
|
||||
BitSetT &operator^=(const BitSetT &other);
|
||||
BitSetT operator~() const;
|
||||
|
||||
BitSetT operator<<(std::size_t pos) const;
|
||||
BitSetT &operator<<=(std::size_t pos);
|
||||
BitSetT operator>>(std::size_t pos) const;
|
||||
BitSetT &operator>>=(std::size_t pos);
|
||||
|
||||
BitSetT &set();
|
||||
BitSetT &set(std::size_t pos, bool value = true);
|
||||
|
||||
BitSetT &reset();
|
||||
BitSetT &reset(std::size_t pos);
|
||||
|
||||
BitSetT &flip();
|
||||
BitSetT &flip(std::size_t pos);
|
||||
|
||||
unsigned long to_ulong() const { return static_cast<unsigned long>(mBits); }
|
||||
BitsT bits() const { return mBits; }
|
||||
|
||||
Iterator begin() const { return Iterator(*this); }
|
||||
Iterator end() const { return Iterator(BitSetT()); }
|
||||
|
||||
private:
|
||||
constexpr static BitsT Bit(std::size_t x) { return (static_cast<BitsT>(1) << x); }
|
||||
constexpr static BitsT Mask(std::size_t x) { return ((Bit(x - 1) - 1) << 1) + 1; }
|
||||
|
||||
BitsT mBits;
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
class IterableBitSet : public std::bitset<N>
|
||||
{
|
||||
public:
|
||||
IterableBitSet() {}
|
||||
IterableBitSet(const std::bitset<N> &implicitBitSet) : std::bitset<N>(implicitBitSet) {}
|
||||
|
||||
class Iterator final
|
||||
{
|
||||
|
@ -42,41 +133,21 @@ class BitSetIterator final
|
|||
private:
|
||||
unsigned long getNextBit();
|
||||
|
||||
static const size_t BitsPerWord = sizeof(unsigned long) * 8;
|
||||
static constexpr size_t BitsPerWord = sizeof(uint32_t) * 8;
|
||||
std::bitset<N> mBits;
|
||||
unsigned long mCurrentBit;
|
||||
unsigned long mOffset;
|
||||
};
|
||||
|
||||
Iterator begin() const { return Iterator(mBits); }
|
||||
Iterator begin() const { return Iterator(*this); }
|
||||
Iterator end() const { return Iterator(std::bitset<N>(0)); }
|
||||
|
||||
private:
|
||||
const std::bitset<N> mBits;
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
BitSetIterator<N>::BitSetIterator(const std::bitset<N> &bitset) : mBits(bitset)
|
||||
IterableBitSet<N>::Iterator::Iterator(const std::bitset<N> &bitset)
|
||||
: mBits(bitset), mCurrentBit(0), mOffset(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
BitSetIterator<N>::BitSetIterator(const BitSetIterator &other) : mBits(other.mBits)
|
||||
{
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
BitSetIterator<N> &BitSetIterator<N>::operator=(const BitSetIterator &other)
|
||||
{
|
||||
mBits = other.mBits;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
BitSetIterator<N>::Iterator::Iterator(const std::bitset<N> &bits)
|
||||
: mBits(bits), mCurrentBit(0), mOffset(0)
|
||||
{
|
||||
if (bits.any())
|
||||
if (mBits.any())
|
||||
{
|
||||
mCurrentBit = getNextBit();
|
||||
}
|
||||
|
@ -87,7 +158,7 @@ BitSetIterator<N>::Iterator::Iterator(const std::bitset<N> &bits)
|
|||
}
|
||||
|
||||
template <size_t N>
|
||||
typename BitSetIterator<N>::Iterator &BitSetIterator<N>::Iterator::operator++()
|
||||
typename IterableBitSet<N>::Iterator &IterableBitSet<N>::Iterator::operator++()
|
||||
{
|
||||
ASSERT(mBits.any());
|
||||
mBits.set(mCurrentBit - mOffset, 0);
|
||||
|
@ -96,26 +167,27 @@ typename BitSetIterator<N>::Iterator &BitSetIterator<N>::Iterator::operator++()
|
|||
}
|
||||
|
||||
template <size_t N>
|
||||
bool BitSetIterator<N>::Iterator::operator==(const Iterator &other) const
|
||||
bool IterableBitSet<N>::Iterator::operator==(const Iterator &other) const
|
||||
{
|
||||
return mOffset == other.mOffset && mBits == other.mBits;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
bool BitSetIterator<N>::Iterator::operator!=(const Iterator &other) const
|
||||
bool IterableBitSet<N>::Iterator::operator!=(const Iterator &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
unsigned long BitSetIterator<N>::Iterator::getNextBit()
|
||||
unsigned long IterableBitSet<N>::Iterator::getNextBit()
|
||||
{
|
||||
static std::bitset<N> wordMask(std::numeric_limits<unsigned long>::max());
|
||||
// TODO(jmadill): Use 64-bit scan when possible.
|
||||
static constexpr std::bitset<N> wordMask(std::numeric_limits<uint32_t>::max());
|
||||
|
||||
while (mOffset < N)
|
||||
{
|
||||
unsigned long wordBits = (mBits & wordMask).to_ulong();
|
||||
if (wordBits != 0ul)
|
||||
uint32_t wordBits = static_cast<uint32_t>((mBits & wordMask).to_ulong());
|
||||
if (wordBits != 0)
|
||||
{
|
||||
return gl::ScanForward(wordBits) + mOffset;
|
||||
}
|
||||
|
@ -126,13 +198,297 @@ unsigned long BitSetIterator<N>::Iterator::getNextBit()
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Helper to avoid needing to specify the template parameter size
|
||||
template <size_t N>
|
||||
BitSetIterator<N> IterateBitSet(const std::bitset<N> &bitset)
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT>::BitSetT() : mBits(0)
|
||||
{
|
||||
return BitSetIterator<N>(bitset);
|
||||
static_assert(N > 0, "Bitset type cannot support zero bits.");
|
||||
static_assert(N <= sizeof(BitsT) * 8, "Bitset type cannot support a size this large.");
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT>::BitSetT(BitsT value) : mBits(value & Mask(N))
|
||||
{
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT>::~BitSetT()
|
||||
{
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT>::BitSetT(const BitSetT &other) : mBits(other.mBits)
|
||||
{
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator=(const BitSetT &other)
|
||||
{
|
||||
mBits = other.mBits;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
bool BitSetT<N, BitsT>::operator==(const BitSetT &other) const
|
||||
{
|
||||
return mBits == other.mBits;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
bool BitSetT<N, BitsT>::operator!=(const BitSetT &other) const
|
||||
{
|
||||
return mBits != other.mBits;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
constexpr bool BitSetT<N, BitsT>::operator[](std::size_t pos) const
|
||||
{
|
||||
return test(pos);
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
bool BitSetT<N, BitsT>::test(std::size_t pos) const
|
||||
{
|
||||
return (mBits & Bit(pos)) != 0;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
bool BitSetT<N, BitsT>::all() const
|
||||
{
|
||||
ASSERT(mBits == (mBits & Mask(N)));
|
||||
return mBits == Mask(N);
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
bool BitSetT<N, BitsT>::any() const
|
||||
{
|
||||
ASSERT(mBits == (mBits & Mask(N)));
|
||||
return (mBits != 0);
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
bool BitSetT<N, BitsT>::none() const
|
||||
{
|
||||
ASSERT(mBits == (mBits & Mask(N)));
|
||||
return (mBits == 0);
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
std::size_t BitSetT<N, BitsT>::count() const
|
||||
{
|
||||
return gl::BitCount(mBits);
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator&=(const BitSetT &other)
|
||||
{
|
||||
mBits &= other.mBits;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator|=(const BitSetT &other)
|
||||
{
|
||||
mBits |= other.mBits;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator^=(const BitSetT &other)
|
||||
{
|
||||
mBits = (mBits ^ other.mBits) & Mask(N);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT> BitSetT<N, BitsT>::operator~() const
|
||||
{
|
||||
return BitSetT<N, BitsT>(~mBits & Mask(N));
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT> BitSetT<N, BitsT>::operator<<(std::size_t pos) const
|
||||
{
|
||||
return BitSetT<N, BitsT>((mBits << pos) & Mask(N));
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator<<=(std::size_t pos)
|
||||
{
|
||||
mBits = (mBits << pos & Mask(N));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT> BitSetT<N, BitsT>::operator>>(std::size_t pos) const
|
||||
{
|
||||
return BitSetT<N, BitsT>(mBits >> pos);
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator>>=(std::size_t pos)
|
||||
{
|
||||
mBits = ((mBits >> pos) & Mask(N));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT> &BitSetT<N, BitsT>::set()
|
||||
{
|
||||
mBits = Mask(N);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT> &BitSetT<N, BitsT>::set(std::size_t pos, bool value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
mBits |= Bit(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
reset(pos);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT> &BitSetT<N, BitsT>::reset()
|
||||
{
|
||||
mBits = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT> &BitSetT<N, BitsT>::reset(std::size_t pos)
|
||||
{
|
||||
mBits &= ~Bit(pos);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT> &BitSetT<N, BitsT>::flip()
|
||||
{
|
||||
mBits ^= Mask(N);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT> &BitSetT<N, BitsT>::flip(std::size_t pos)
|
||||
{
|
||||
mBits ^= Bit(pos);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
BitSetT<N, BitsT>::Iterator::Iterator(const BitSetT &bits) : mBitsCopy(bits), mCurrentBit(0)
|
||||
{
|
||||
if (bits.any())
|
||||
{
|
||||
mCurrentBit = getNextBit();
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
typename BitSetT<N, BitsT>::Iterator &BitSetT<N, BitsT>::Iterator::operator++()
|
||||
{
|
||||
ASSERT(mBitsCopy.any());
|
||||
mBitsCopy.reset(mCurrentBit);
|
||||
mCurrentBit = getNextBit();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
bool BitSetT<N, BitsT>::Iterator::operator==(const Iterator &other) const
|
||||
{
|
||||
return mBitsCopy == other.mBitsCopy;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
bool BitSetT<N, BitsT>::Iterator::operator!=(const Iterator &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
std::size_t BitSetT<N, BitsT>::Iterator::operator*() const
|
||||
{
|
||||
return mCurrentBit;
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
std::size_t BitSetT<N, BitsT>::Iterator::getNextBit()
|
||||
{
|
||||
if (mBitsCopy.none())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return gl::ScanForward(mBitsCopy.mBits);
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
using BitSet32 = BitSetT<N, uint32_t>;
|
||||
|
||||
// ScanForward for 64-bits requires a 64-bit implementation.
|
||||
#if defined(ANGLE_X64_CPU)
|
||||
template <size_t N>
|
||||
using BitSet64 = BitSetT<N, uint64_t>;
|
||||
#endif // defined(ANGLE_X64_CPU)
|
||||
|
||||
namespace priv
|
||||
{
|
||||
|
||||
template <size_t N, typename T>
|
||||
using EnableIfBitsFit = typename std::enable_if<N <= sizeof(T) * 8>::type;
|
||||
|
||||
template <size_t N, typename Enable = void>
|
||||
struct GetBitSet
|
||||
{
|
||||
using Type = IterableBitSet<N>;
|
||||
};
|
||||
|
||||
// Prefer 64-bit bitsets on 64-bit CPUs. They seem faster than 32-bit.
|
||||
#if defined(ANGLE_X64_CPU)
|
||||
template <size_t N>
|
||||
struct GetBitSet<N, EnableIfBitsFit<N, uint64_t>>
|
||||
{
|
||||
using Type = BitSet64<N>;
|
||||
};
|
||||
#else
|
||||
template <size_t N>
|
||||
struct GetBitSet<N, EnableIfBitsFit<N, uint32_t>>
|
||||
{
|
||||
using Type = BitSet32<N>;
|
||||
};
|
||||
#endif // defined(ANGLE_X64_CPU)
|
||||
|
||||
} // namespace priv
|
||||
|
||||
template <size_t N>
|
||||
using BitSet = typename priv::GetBitSet<N>::Type;
|
||||
|
||||
} // angle
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
inline angle::BitSetT<N, BitsT> operator&(const angle::BitSetT<N, BitsT> &lhs,
|
||||
const angle::BitSetT<N, BitsT> &rhs)
|
||||
{
|
||||
return angle::BitSetT<N, BitsT>(lhs.bits() & rhs.bits());
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
inline angle::BitSetT<N, BitsT> operator|(const angle::BitSetT<N, BitsT> &lhs,
|
||||
const angle::BitSetT<N, BitsT> &rhs)
|
||||
{
|
||||
return angle::BitSetT<N, BitsT>(lhs.bits() | rhs.bits());
|
||||
}
|
||||
|
||||
template <size_t N, typename BitsT>
|
||||
inline angle::BitSetT<N, BitsT> operator^(const angle::BitSetT<N, BitsT> &lhs,
|
||||
const angle::BitSetT<N, BitsT> &rhs)
|
||||
{
|
||||
return angle::BitSetT<N, BitsT>(lhs.bits() ^ rhs.bits());
|
||||
}
|
||||
|
||||
#endif // COMMON_BITSETITERATOR_H_
|
||||
|
|
|
@ -18,25 +18,25 @@ namespace
|
|||
class BitSetIteratorTest : public testing::Test
|
||||
{
|
||||
protected:
|
||||
std::bitset<40> mStateBits;
|
||||
BitSet<40> mStateBits;
|
||||
};
|
||||
|
||||
// Simple iterator test.
|
||||
TEST_F(BitSetIteratorTest, Iterator)
|
||||
{
|
||||
std::set<unsigned long> originalValues;
|
||||
std::set<size_t> originalValues;
|
||||
originalValues.insert(2);
|
||||
originalValues.insert(6);
|
||||
originalValues.insert(8);
|
||||
originalValues.insert(35);
|
||||
|
||||
for (unsigned long value : originalValues)
|
||||
for (size_t value : originalValues)
|
||||
{
|
||||
mStateBits.set(value);
|
||||
}
|
||||
|
||||
std::set<unsigned long> readValues;
|
||||
for (unsigned long bit : IterateBitSet(mStateBits))
|
||||
std::set<size_t> readValues;
|
||||
for (size_t bit : mStateBits)
|
||||
{
|
||||
EXPECT_EQ(1u, originalValues.count(bit));
|
||||
EXPECT_EQ(0u, readValues.count(bit));
|
||||
|
@ -52,7 +52,7 @@ TEST_F(BitSetIteratorTest, EmptySet)
|
|||
// We don't use the FAIL gtest macro here since it returns immediately,
|
||||
// causing an unreachable code warning in MSVS
|
||||
bool sawBit = false;
|
||||
for (unsigned long bit : IterateBitSet(mStateBits))
|
||||
for (size_t bit : mStateBits)
|
||||
{
|
||||
sawBit = true;
|
||||
UNUSED_VARIABLE(bit);
|
||||
|
@ -63,7 +63,7 @@ TEST_F(BitSetIteratorTest, EmptySet)
|
|||
// Test iterating a result of combining two bitsets.
|
||||
TEST_F(BitSetIteratorTest, NonLValueBitset)
|
||||
{
|
||||
std::bitset<40> otherBits;
|
||||
BitSet<40> otherBits;
|
||||
|
||||
mStateBits.set(1);
|
||||
mStateBits.set(2);
|
||||
|
@ -75,9 +75,10 @@ TEST_F(BitSetIteratorTest, NonLValueBitset)
|
|||
otherBits.set(3);
|
||||
otherBits.set(5);
|
||||
|
||||
std::set<unsigned long> seenBits;
|
||||
std::set<size_t> seenBits;
|
||||
|
||||
for (unsigned long bit : IterateBitSet(mStateBits & otherBits))
|
||||
angle::BitSet<40> maskedBits = (mStateBits & otherBits);
|
||||
for (size_t bit : maskedBits)
|
||||
{
|
||||
EXPECT_EQ(0u, seenBits.count(bit));
|
||||
seenBits.insert(bit);
|
||||
|
|
|
@ -805,34 +805,73 @@ inline uint32_t BitfieldReverse(uint32_t value)
|
|||
}
|
||||
|
||||
// Count the 1 bits.
|
||||
inline int BitCount(unsigned int bits)
|
||||
#if defined(ANGLE_PLATFORM_WINDOWS)
|
||||
inline int BitCount(uint32_t bits)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
return static_cast<int>(__popcnt(bits));
|
||||
#elif defined(__GNUC__)
|
||||
}
|
||||
#if defined(ANGLE_X64_CPU)
|
||||
inline int BitCount(uint64_t bits)
|
||||
{
|
||||
return static_cast<int>(__popcnt64(bits));
|
||||
}
|
||||
#endif // defined(ANGLE_X64_CPU)
|
||||
#endif // defined(ANGLE_PLATFORM_WINDOWS)
|
||||
|
||||
#if defined(ANGLE_PLATFORM_POSIX)
|
||||
inline int BitCount(uint32_t bits)
|
||||
{
|
||||
return __builtin_popcount(bits);
|
||||
#else
|
||||
#error Please implement bit count for your platform!
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(ANGLE_X64_CPU)
|
||||
inline int BitCount(uint64_t bits)
|
||||
{
|
||||
return __builtin_popcountll(bits);
|
||||
}
|
||||
#endif // defined(ANGLE_X64_CPU)
|
||||
#endif // defined(ANGLE_PLATFORM_POSIX)
|
||||
|
||||
#if defined(ANGLE_PLATFORM_WINDOWS)
|
||||
// Return the index of the least significant bit set. Indexing is such that bit 0 is the least
|
||||
// significant bit.
|
||||
inline unsigned long ScanForward(unsigned long bits)
|
||||
// significant bit. Implemented for different bit widths on different platforms.
|
||||
inline unsigned long ScanForward(uint32_t bits)
|
||||
{
|
||||
ASSERT(bits != 0u);
|
||||
#if defined(ANGLE_PLATFORM_WINDOWS)
|
||||
unsigned long firstBitIndex = 0ul;
|
||||
unsigned char ret = _BitScanForward(&firstBitIndex, bits);
|
||||
ASSERT(ret != 0u);
|
||||
return firstBitIndex;
|
||||
#elif defined(ANGLE_PLATFORM_POSIX)
|
||||
return static_cast<unsigned long>(__builtin_ctzl(bits));
|
||||
#else
|
||||
#error Please implement bit-scan-forward for your platform!
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(ANGLE_X64_CPU)
|
||||
inline unsigned long ScanForward(uint64_t bits)
|
||||
{
|
||||
ASSERT(bits != 0u);
|
||||
unsigned long firstBitIndex = 0ul;
|
||||
unsigned char ret = _BitScanForward64(&firstBitIndex, bits);
|
||||
ASSERT(ret != 0u);
|
||||
return firstBitIndex;
|
||||
}
|
||||
#endif // defined(ANGLE_X64_CPU)
|
||||
#endif // defined(ANGLE_PLATFORM_WINDOWS)
|
||||
|
||||
#if defined(ANGLE_PLATFORM_POSIX)
|
||||
inline unsigned long ScanForward(uint32_t bits)
|
||||
{
|
||||
ASSERT(bits != 0u);
|
||||
return static_cast<unsigned long>(__builtin_ctz(bits));
|
||||
}
|
||||
|
||||
#if defined(ANGLE_X64_CPU)
|
||||
inline unsigned long ScanForward(uint64_t bits)
|
||||
{
|
||||
ASSERT(bits != 0u);
|
||||
return static_cast<unsigned long>(__builtin_ctzll(bits));
|
||||
}
|
||||
#endif // defined(ANGLE_X64_CPU)
|
||||
#endif // defined(ANGLE_PLATFORM_POSIX)
|
||||
|
||||
// Return the index of the most significant bit set. Indexing is such that bit 0 is the least
|
||||
// significant bit.
|
||||
inline unsigned long ScanReverse(unsigned long bits)
|
||||
|
@ -851,8 +890,10 @@ inline unsigned long ScanReverse(unsigned long bits)
|
|||
}
|
||||
|
||||
// Returns -1 on 0, otherwise the index of the least significant 1 bit as in GLSL.
|
||||
inline int FindLSB(uint32_t bits)
|
||||
template <typename T>
|
||||
int FindLSB(T bits)
|
||||
{
|
||||
static_assert(std::is_integral<T>::value, "must be integral type.");
|
||||
if (bits == 0u)
|
||||
{
|
||||
return -1;
|
||||
|
@ -864,8 +905,10 @@ inline int FindLSB(uint32_t bits)
|
|||
}
|
||||
|
||||
// Returns -1 on 0, otherwise the index of the most significant 1 bit as in GLSL.
|
||||
inline int FindMSB(uint32_t bits)
|
||||
template <typename T>
|
||||
int FindMSB(T bits)
|
||||
{
|
||||
static_assert(std::is_integral<T>::value, "must be integral type.");
|
||||
if (bits == 0u)
|
||||
{
|
||||
return -1;
|
||||
|
|
|
@ -274,14 +274,26 @@ TEST(MathUtilTest, BitCount)
|
|||
EXPECT_EQ(0, gl::BitCount(0u));
|
||||
EXPECT_EQ(32, gl::BitCount(0xFFFFFFFFu));
|
||||
EXPECT_EQ(10, gl::BitCount(0x17103121u));
|
||||
|
||||
#if defined(ANGLE_X64_CPU)
|
||||
EXPECT_EQ(0, gl::BitCount(0ull));
|
||||
EXPECT_EQ(32, gl::BitCount(0xFFFFFFFFull));
|
||||
EXPECT_EQ(10, gl::BitCount(0x17103121ull));
|
||||
#endif // defined(ANGLE_X64_CPU)
|
||||
}
|
||||
|
||||
// Test ScanForward, which scans for the least significant 1 bit from a non-zero integer.
|
||||
TEST(MathUtilTest, ScanForward)
|
||||
{
|
||||
EXPECT_EQ(0ul, gl::ScanForward(1ul));
|
||||
EXPECT_EQ(16ul, gl::ScanForward(0x80010000ul));
|
||||
EXPECT_EQ(31ul, gl::ScanForward(0x80000000ul));
|
||||
EXPECT_EQ(0ul, gl::ScanForward(1u));
|
||||
EXPECT_EQ(16ul, gl::ScanForward(0x80010000u));
|
||||
EXPECT_EQ(31ul, gl::ScanForward(0x80000000u));
|
||||
|
||||
#if defined(ANGLE_X64_CPU)
|
||||
EXPECT_EQ(0ul, gl::ScanForward(1ull));
|
||||
EXPECT_EQ(16ul, gl::ScanForward(0x80010000ull));
|
||||
EXPECT_EQ(31ul, gl::ScanForward(0x80000000ull));
|
||||
#endif // defined(ANGLE_X64_CPU)
|
||||
}
|
||||
|
||||
// Test ScanReverse, which scans for the most significant 1 bit from a non-zero integer.
|
||||
|
|
|
@ -1263,7 +1263,7 @@ bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
|
|||
}
|
||||
|
||||
// The bitset will skip inactive draw buffers.
|
||||
for (GLuint drawIndex : angle::IterateBitSet(mState.mEnabledDrawBuffers))
|
||||
for (size_t drawIndex : mState.mEnabledDrawBuffers)
|
||||
{
|
||||
const FramebufferAttachment *attachment = getDrawBuffer(drawIndex);
|
||||
if (attachment && attachment->type() == GL_TEXTURE)
|
||||
|
|
|
@ -100,7 +100,7 @@ class FramebufferState final : angle::NonCopyable
|
|||
|
||||
std::vector<GLenum> mDrawBufferStates;
|
||||
GLenum mReadBufferState;
|
||||
std::bitset<IMPLEMENTATION_MAX_DRAW_BUFFERS> mEnabledDrawBuffers;
|
||||
angle::BitSet<IMPLEMENTATION_MAX_DRAW_BUFFERS> mEnabledDrawBuffers;
|
||||
|
||||
GLint mDefaultWidth;
|
||||
GLint mDefaultHeight;
|
||||
|
@ -259,7 +259,7 @@ class Framebuffer final : public LabeledObject, public OnAttachmentDirtyReceiver
|
|||
DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN
|
||||
};
|
||||
|
||||
typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
|
||||
typedef angle::BitSet<DIRTY_BIT_MAX> DirtyBits;
|
||||
bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
|
||||
|
||||
void syncState(const Context *context);
|
||||
|
|
|
@ -260,7 +260,7 @@ class ProgramState final : angle::NonCopyable
|
|||
UniformBlockBindingMask mActiveUniformBlockBindings;
|
||||
|
||||
std::vector<sh::Attribute> mAttributes;
|
||||
std::bitset<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
|
||||
angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
|
||||
|
||||
// Uniforms are sorted in order:
|
||||
// 1. Non-sampler uniforms
|
||||
|
|
|
@ -1370,9 +1370,9 @@ void State::setVertexAttribDivisor(GLuint index, GLuint divisor)
|
|||
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const
|
||||
const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(size_t attribNum) const
|
||||
{
|
||||
ASSERT(static_cast<size_t>(attribNum) < mVertexAttribCurrentValues.size());
|
||||
ASSERT(attribNum < mVertexAttribCurrentValues.size());
|
||||
return mVertexAttribCurrentValues[attribNum];
|
||||
}
|
||||
|
||||
|
@ -2114,7 +2114,7 @@ void State::syncDirtyObjects(const Context *context)
|
|||
|
||||
void State::syncDirtyObjects(const Context *context, const DirtyObjects &bitset)
|
||||
{
|
||||
for (auto dirtyObject : angle::IterateBitSet(bitset))
|
||||
for (auto dirtyObject : bitset)
|
||||
{
|
||||
switch (dirtyObject)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <memory>
|
||||
|
||||
#include "common/angleutils.h"
|
||||
#include "common/bitset_utils.h"
|
||||
#include "common/Color.h"
|
||||
#include "libANGLE/Debug.h"
|
||||
#include "libANGLE/Program.h"
|
||||
|
@ -266,7 +267,7 @@ class State : angle::NonCopyable
|
|||
void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type,
|
||||
bool normalized, bool pureInteger, GLsizei stride, const void *pointer);
|
||||
void setVertexAttribDivisor(GLuint index, GLuint divisor);
|
||||
const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const;
|
||||
const VertexAttribCurrentValueData &getVertexAttribCurrentValue(size_t attribNum) const;
|
||||
const void *getVertexAttribPointer(unsigned int attribNum) const;
|
||||
void bindVertexBuffer(GLuint bindingIndex,
|
||||
Buffer *boundBuffer,
|
||||
|
@ -425,13 +426,13 @@ class State : angle::NonCopyable
|
|||
DIRTY_OBJECT_MAX = DIRTY_OBJECT_UNKNOWN,
|
||||
};
|
||||
|
||||
typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
|
||||
typedef angle::BitSet<DIRTY_BIT_MAX> DirtyBits;
|
||||
const DirtyBits &getDirtyBits() const { return mDirtyBits; }
|
||||
void clearDirtyBits() { mDirtyBits.reset(); }
|
||||
void clearDirtyBits(const DirtyBits &bitset) { mDirtyBits &= ~bitset; }
|
||||
void setAllDirtyBits() { mDirtyBits.set(); }
|
||||
|
||||
typedef std::bitset<DIRTY_OBJECT_MAX> DirtyObjects;
|
||||
typedef angle::BitSet<DIRTY_OBJECT_MAX> DirtyObjects;
|
||||
void clearDirtyObjects() { mDirtyObjects.reset(); }
|
||||
void setAllDirtyObjects() { mDirtyObjects.set(); }
|
||||
void syncDirtyObjects(const Context *context);
|
||||
|
|
|
@ -395,7 +395,7 @@ class Texture final : public egl::ImageSibling,
|
|||
|
||||
DIRTY_BIT_COUNT,
|
||||
};
|
||||
using DirtyBits = std::bitset<DIRTY_BIT_COUNT>;
|
||||
using DirtyBits = angle::BitSet<DIRTY_BIT_COUNT>;
|
||||
|
||||
void syncImplState();
|
||||
bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
|
||||
|
|
|
@ -93,7 +93,7 @@ const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
|
|||
return mState.mVertexBindings[bindingIndex];
|
||||
}
|
||||
|
||||
size_t VertexArray::GetAttribIndex(unsigned long dirtyBit)
|
||||
size_t VertexArray::GetAttribIndex(size_t dirtyBit)
|
||||
{
|
||||
static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
|
||||
"The stride of vertex attributes should equal to that of vertex bindings.");
|
||||
|
|
|
@ -168,9 +168,9 @@ class VertexArray final : public LabeledObject
|
|||
DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN,
|
||||
};
|
||||
|
||||
typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
|
||||
typedef angle::BitSet<DIRTY_BIT_MAX> DirtyBits;
|
||||
|
||||
static size_t GetAttribIndex(unsigned long dirtyBit);
|
||||
static size_t GetAttribIndex(size_t dirtyBit);
|
||||
|
||||
void syncImplState(const Context *context);
|
||||
bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
|
||||
|
|
|
@ -26,7 +26,7 @@ TEST(VertexArrayTest, VerifyGetAttribIndex)
|
|||
dirtyBits.set(bits[i]);
|
||||
}
|
||||
|
||||
for (unsigned long dirtyBit : angle::IterateBitSet(dirtyBits))
|
||||
for (size_t dirtyBit : dirtyBits)
|
||||
{
|
||||
size_t index = VertexArray::GetAttribIndex(dirtyBit);
|
||||
if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#ifndef LIBANGLE_ANGLETYPES_H_
|
||||
#define LIBANGLE_ANGLETYPES_H_
|
||||
|
||||
#include "common/bitset_utils.h"
|
||||
#include "libANGLE/Constants.h"
|
||||
#include "libANGLE/RefCountObject.h"
|
||||
|
||||
|
@ -253,10 +254,10 @@ struct PixelPackState : PixelStoreStateBase
|
|||
};
|
||||
|
||||
// Used in Program and VertexArray.
|
||||
typedef std::bitset<MAX_VERTEX_ATTRIBS> AttributesMask;
|
||||
using AttributesMask = angle::BitSet<MAX_VERTEX_ATTRIBS>;
|
||||
|
||||
// Use in Program
|
||||
typedef std::bitset<IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS> UniformBlockBindingMask;
|
||||
using UniformBlockBindingMask = angle::BitSet<IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS>;
|
||||
|
||||
// A map of GL objects indexed by object ID. The specific map implementation may change.
|
||||
// Client code should treat it as a std::map.
|
||||
|
|
|
@ -306,7 +306,7 @@ void FramebufferD3D::syncState(ContextImpl *contextImpl,
|
|||
invalidateColorAttachmentCache = true;
|
||||
}
|
||||
|
||||
for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
|
||||
for (auto dirtyBit : dirtyBits)
|
||||
{
|
||||
if ((dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 &&
|
||||
dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) ||
|
||||
|
|
|
@ -2359,7 +2359,7 @@ void ProgramD3D::updateCachedInputLayout(const gl::State &state)
|
|||
mCachedInputLayout.clear();
|
||||
const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
|
||||
|
||||
for (unsigned int locationIndex : IterateBitSet(mState.getActiveAttribLocationsMask()))
|
||||
for (size_t locationIndex : mState.getActiveAttribLocationsMask())
|
||||
{
|
||||
int d3dSemantic = mAttribLocationToD3DSemantic[locationIndex];
|
||||
|
||||
|
|
|
@ -241,8 +241,7 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state,
|
|||
translatedAttribs->resize(attribIndex + 1);
|
||||
|
||||
TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex];
|
||||
auto currentValueData =
|
||||
state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex));
|
||||
auto currentValueData = state.getVertexAttribCurrentValue(attribIndex);
|
||||
|
||||
// Record the attribute now
|
||||
translated->active = true;
|
||||
|
@ -401,14 +400,14 @@ gl::Error VertexDataManager::storeDynamicAttribs(
|
|||
StreamingBufferUnmapper localUnmapper(mStreamingBuffer);
|
||||
|
||||
// Reserve the required space for the dynamic buffers.
|
||||
for (auto attribIndex : IterateBitSet(dynamicAttribsMask))
|
||||
for (auto attribIndex : dynamicAttribsMask)
|
||||
{
|
||||
const auto &dynamicAttrib = (*translatedAttribs)[attribIndex];
|
||||
ANGLE_TRY(reserveSpaceForAttrib(dynamicAttrib, count, instances));
|
||||
}
|
||||
|
||||
// Store dynamic attributes
|
||||
for (auto attribIndex : IterateBitSet(dynamicAttribsMask))
|
||||
for (auto attribIndex : dynamicAttribsMask)
|
||||
{
|
||||
auto *dynamicAttrib = &(*translatedAttribs)[attribIndex];
|
||||
ANGLE_TRY(storeDynamicAttrib(dynamicAttrib, start, count, instances));
|
||||
|
@ -422,7 +421,7 @@ void VertexDataManager::PromoteDynamicAttribs(
|
|||
const gl::AttributesMask &dynamicAttribsMask,
|
||||
GLsizei count)
|
||||
{
|
||||
for (auto attribIndex : IterateBitSet(dynamicAttribsMask))
|
||||
for (auto attribIndex : dynamicAttribsMask)
|
||||
{
|
||||
const auto &dynamicAttrib = translatedAttribs[attribIndex];
|
||||
const auto &binding = *dynamicAttrib.binding;
|
||||
|
|
|
@ -384,7 +384,7 @@ void Framebuffer11::syncState(ContextImpl *contextImpl, const gl::Framebuffer::D
|
|||
const auto &mergedDirtyBits = dirtyBits | mInternalDirtyBits;
|
||||
mInternalDirtyBits.reset();
|
||||
|
||||
for (auto dirtyBit : IterateBitSet(mergedDirtyBits))
|
||||
for (auto dirtyBit : mergedDirtyBits)
|
||||
{
|
||||
switch (dirtyBit)
|
||||
{
|
||||
|
|
|
@ -47,7 +47,7 @@ gl::InputLayout GetInputLayout(const std::vector<const TranslatedAttribute *> &t
|
|||
return inputLayout;
|
||||
}
|
||||
|
||||
GLenum GetGLSLAttributeType(const std::vector<sh::Attribute> &shaderAttributes, int index)
|
||||
GLenum GetGLSLAttributeType(const std::vector<sh::Attribute> &shaderAttributes, size_t index)
|
||||
{
|
||||
// Count matrices differently
|
||||
for (const sh::Attribute &attrib : shaderAttributes)
|
||||
|
@ -59,8 +59,9 @@ GLenum GetGLSLAttributeType(const std::vector<sh::Attribute> &shaderAttributes,
|
|||
|
||||
GLenum transposedType = gl::TransposeMatrixType(attrib.type);
|
||||
int rows = gl::VariableRowCount(transposedType);
|
||||
int intIndex = static_cast<int>(index);
|
||||
|
||||
if (index >= attrib.location && index < attrib.location + rows)
|
||||
if (intIndex >= attrib.location && intIndex < attrib.location + rows)
|
||||
{
|
||||
return transposedType;
|
||||
}
|
||||
|
@ -105,7 +106,7 @@ void SortAttributesByLayout(const gl::Program *program,
|
|||
const auto &locationToSemantic =
|
||||
GetImplAs<ProgramD3D>(program)->getAttribLocationToD3DSemantics();
|
||||
|
||||
for (auto locationIndex : angle::IterateBitSet(program->getActiveAttribLocationsMask()))
|
||||
for (auto locationIndex : program->getActiveAttribLocationsMask())
|
||||
{
|
||||
int d3dSemantic = locationToSemantic[locationIndex];
|
||||
if (sortedAttributesOut->size() <= static_cast<size_t>(d3dSemantic))
|
||||
|
@ -485,7 +486,7 @@ gl::Error InputLayoutCache::updateInputLayout(const gl::State &state,
|
|||
const auto &bindings = state.getVertexArray()->getVertexBindings();
|
||||
const auto &locationToSemantic = programD3D->getAttribLocationToD3DSemantics();
|
||||
|
||||
for (unsigned long attribIndex : angle::IterateBitSet(program->getActiveAttribLocationsMask()))
|
||||
for (size_t attribIndex : program->getActiveAttribLocationsMask())
|
||||
{
|
||||
// Record the type of the associated vertex shader vector in our key
|
||||
// This will prevent mismatched vertex shaders from using the same input layout
|
||||
|
@ -495,7 +496,8 @@ gl::Error InputLayoutCache::updateInputLayout(const gl::State &state,
|
|||
const auto &binding = bindings[attrib.bindingIndex];
|
||||
int d3dSemantic = locationToSemantic[attribIndex];
|
||||
|
||||
const auto ¤tValue = state.getVertexAttribCurrentValue(attribIndex);
|
||||
const auto ¤tValue =
|
||||
state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex));
|
||||
gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValue.Type);
|
||||
|
||||
layout.addAttributeData(glslElementType, d3dSemantic, vertexFormatType, binding.divisor);
|
||||
|
|
|
@ -253,7 +253,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
|
|||
return;
|
||||
}
|
||||
|
||||
for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
|
||||
for (auto dirtyBit : dirtyBits)
|
||||
{
|
||||
switch (dirtyBit)
|
||||
{
|
||||
|
@ -1103,15 +1103,14 @@ gl::Error StateManager11::updateCurrentValueAttribs(const gl::State &state,
|
|||
const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs);
|
||||
const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
|
||||
|
||||
for (auto attribIndex : angle::IterateBitSet(dirtyActiveAttribs))
|
||||
for (auto attribIndex : dirtyActiveAttribs)
|
||||
{
|
||||
if (vertexAttributes[attribIndex].enabled)
|
||||
continue;
|
||||
|
||||
mDirtyCurrentValueAttribs.reset(attribIndex);
|
||||
|
||||
const auto ¤tValue =
|
||||
state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex));
|
||||
const auto ¤tValue = state.getVertexAttribCurrentValue(attribIndex);
|
||||
auto currentValueAttrib = &mCurrentValueAttribs[attribIndex];
|
||||
currentValueAttrib->currentValueType = currentValue.Type;
|
||||
currentValueAttrib->attribute = &vertexAttributes[attribIndex];
|
||||
|
|
|
@ -42,7 +42,7 @@ VertexArray11::~VertexArray11()
|
|||
|
||||
void VertexArray11::syncState(ContextImpl *contextImpl, const gl::VertexArray::DirtyBits &dirtyBits)
|
||||
{
|
||||
for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
|
||||
for (auto dirtyBit : dirtyBits)
|
||||
{
|
||||
if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
|
||||
continue;
|
||||
|
@ -62,9 +62,9 @@ void VertexArray11::flushAttribUpdates(const gl::State &state)
|
|||
if (mAttribsToUpdate.any())
|
||||
{
|
||||
// Skip attrib locations the program doesn't use.
|
||||
const auto &activeToUpdate = (mAttribsToUpdate & activeLocations);
|
||||
gl::AttributesMask activeToUpdate = mAttribsToUpdate & activeLocations;
|
||||
|
||||
for (auto toUpdateIndex : angle::IterateBitSet(activeToUpdate))
|
||||
for (auto toUpdateIndex : activeToUpdate)
|
||||
{
|
||||
mAttribsToUpdate.reset(toUpdateIndex);
|
||||
updateVertexAttribStorage(toUpdateIndex);
|
||||
|
@ -155,15 +155,14 @@ gl::Error VertexArray11::updateDirtyAndDynamicAttribs(VertexDataManager *vertexD
|
|||
if (mAttribsToTranslate.any())
|
||||
{
|
||||
// Skip attrib locations the program doesn't use, saving for the next frame.
|
||||
const auto &dirtyActiveAttribs = (mAttribsToTranslate & activeLocations);
|
||||
gl::AttributesMask dirtyActiveAttribs = (mAttribsToTranslate & activeLocations);
|
||||
|
||||
for (auto dirtyAttribIndex : angle::IterateBitSet(dirtyActiveAttribs))
|
||||
for (auto dirtyAttribIndex : dirtyActiveAttribs)
|
||||
{
|
||||
mAttribsToTranslate.reset(dirtyAttribIndex);
|
||||
|
||||
auto *translatedAttrib = &mTranslatedAttribs[dirtyAttribIndex];
|
||||
const auto ¤tValue =
|
||||
state.getVertexAttribCurrentValue(static_cast<unsigned int>(dirtyAttribIndex));
|
||||
const auto ¤tValue = state.getVertexAttribCurrentValue(dirtyAttribIndex);
|
||||
|
||||
// Record basic attrib info
|
||||
translatedAttrib->attribute = &attribs[dirtyAttribIndex];
|
||||
|
@ -195,11 +194,10 @@ gl::Error VertexArray11::updateDirtyAndDynamicAttribs(VertexDataManager *vertexD
|
|||
{
|
||||
auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
|
||||
|
||||
for (auto dynamicAttribIndex : angle::IterateBitSet(activeDynamicAttribs))
|
||||
for (auto dynamicAttribIndex : activeDynamicAttribs)
|
||||
{
|
||||
auto *dynamicAttrib = &mTranslatedAttribs[dynamicAttribIndex];
|
||||
const auto ¤tValue =
|
||||
state.getVertexAttribCurrentValue(static_cast<unsigned int>(dynamicAttribIndex));
|
||||
const auto ¤tValue = state.getVertexAttribCurrentValue(dynamicAttribIndex);
|
||||
|
||||
// Record basic attrib info
|
||||
dynamicAttrib->attribute = &attribs[dynamicAttribIndex];
|
||||
|
|
|
@ -120,7 +120,7 @@ void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits
|
|||
return;
|
||||
}
|
||||
|
||||
for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
|
||||
for (auto dirtyBit : dirtyBits)
|
||||
{
|
||||
switch (dirtyBit)
|
||||
{
|
||||
|
@ -396,7 +396,7 @@ gl::Error StateManager9::setBlendDepthRasterStates(const gl::State &glState,
|
|||
mCurFrontFaceCCW = frontFaceCCW;
|
||||
}
|
||||
|
||||
for (auto dirtyBit : angle::IterateBitSet(mDirtyBits))
|
||||
for (auto dirtyBit : mDirtyBits)
|
||||
{
|
||||
switch (dirtyBit)
|
||||
{
|
||||
|
|
|
@ -155,7 +155,7 @@ class StateManager9 final : angle::NonCopyable
|
|||
DIRTY_BIT_MAX
|
||||
};
|
||||
|
||||
typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
|
||||
using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
|
||||
|
||||
bool mUsingZeroColorMaskWorkaround;
|
||||
|
||||
|
|
|
@ -417,7 +417,7 @@ void FramebufferGL::syncState(ContextImpl *contextImpl, const Framebuffer::Dirty
|
|||
|
||||
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
|
||||
|
||||
for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
|
||||
for (auto dirtyBit : dirtyBits)
|
||||
{
|
||||
switch (dirtyBit)
|
||||
{
|
||||
|
|
|
@ -75,9 +75,10 @@ LinkResult ProgramGL::load(const ContextImpl *contextImpl,
|
|||
const WorkaroundsGL &workaroundsGL = GetAs<ContextGL>(contextImpl)->getWorkaroundsGL();
|
||||
if (workaroundsGL.reapplyUBOBindingsAfterLoadingBinaryProgram)
|
||||
{
|
||||
for (GLuint bindingIndex : angle::IterateBitSet(mState.getActiveUniformBlockBindingsMask()))
|
||||
for (size_t bindingIndex : mState.getActiveUniformBlockBindingsMask())
|
||||
{
|
||||
setUniformBlockBinding(bindingIndex, mState.getUniformBlockBinding(bindingIndex));
|
||||
GLuint uintIndex = static_cast<GLuint>(bindingIndex);
|
||||
setUniformBlockBinding(uintIndex, mState.getUniformBlockBinding(uintIndex));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1394,7 +1394,7 @@ void StateManagerGL::syncState(const gl::ContextState &data,
|
|||
mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB);
|
||||
}
|
||||
|
||||
const auto &glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits);
|
||||
const gl::State::DirtyBits &glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits);
|
||||
|
||||
if (!glAndLocalDirtyBits.any())
|
||||
{
|
||||
|
@ -1402,7 +1402,7 @@ void StateManagerGL::syncState(const gl::ContextState &data,
|
|||
}
|
||||
|
||||
// TODO(jmadill): Investigate only syncing vertex state for active attributes
|
||||
for (auto dirtyBit : angle::IterateBitSet(glAndLocalDirtyBits))
|
||||
for (auto dirtyBit : glAndLocalDirtyBits)
|
||||
{
|
||||
switch (dirtyBit)
|
||||
{
|
||||
|
@ -1648,8 +1648,8 @@ void StateManagerGL::syncState(const gl::ContextState &data,
|
|||
dirtyBit < gl::State::DIRTY_BIT_CURRENT_VALUE_MAX);
|
||||
size_t attribIndex =
|
||||
static_cast<size_t>(dirtyBit) - gl::State::DIRTY_BIT_CURRENT_VALUE_0;
|
||||
setAttributeCurrentData(attribIndex, state.getVertexAttribCurrentValue(
|
||||
static_cast<unsigned int>(attribIndex)));
|
||||
setAttributeCurrentData(attribIndex,
|
||||
state.getVertexAttribCurrentValue(attribIndex));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -942,7 +942,7 @@ void TextureGL::syncState(const gl::Texture::DirtyBits &dirtyBits)
|
|||
mLocalDirtyBits |= GetLevelWorkaroundDirtyBits();
|
||||
}
|
||||
|
||||
for (auto dirtyBit : angle::IterateBitSet(dirtyBits | mLocalDirtyBits))
|
||||
for (auto dirtyBit : (dirtyBits | mLocalDirtyBits))
|
||||
{
|
||||
switch (dirtyBit)
|
||||
{
|
||||
|
|
|
@ -257,7 +257,10 @@ void VertexArrayGL::computeStreamingAttributeSizes(const gl::AttributesMask &act
|
|||
|
||||
const auto &attribs = mData.getVertexAttributes();
|
||||
const auto &bindings = mData.getVertexBindings();
|
||||
for (auto idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask))
|
||||
|
||||
gl::AttributesMask attribsToStream = (mAttributesNeedStreaming & activeAttributesMask);
|
||||
|
||||
for (auto idx : attribsToStream)
|
||||
{
|
||||
const auto &attrib = attribs[idx];
|
||||
const auto &binding = bindings[attrib.bindingIndex];
|
||||
|
@ -320,7 +323,10 @@ gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttrib
|
|||
|
||||
const auto &attribs = mData.getVertexAttributes();
|
||||
const auto &bindings = mData.getVertexBindings();
|
||||
for (auto idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask))
|
||||
|
||||
gl::AttributesMask attribsToStream = (mAttributesNeedStreaming & activeAttributesMask);
|
||||
|
||||
for (auto idx : attribsToStream)
|
||||
{
|
||||
const auto &attrib = attribs[idx];
|
||||
const auto &binding = bindings[attrib.bindingIndex];
|
||||
|
@ -526,7 +532,7 @@ void VertexArrayGL::updateAttribDivisor(size_t attribIndex)
|
|||
|
||||
void VertexArrayGL::syncState(ContextImpl *contextImpl, const VertexArray::DirtyBits &dirtyBits)
|
||||
{
|
||||
for (unsigned long dirtyBit : angle::IterateBitSet(dirtyBits))
|
||||
for (size_t dirtyBit : dirtyBits)
|
||||
{
|
||||
if (dirtyBit == VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
|
||||
{
|
||||
|
|
|
@ -99,7 +99,7 @@ gl::Error ContextVk::initPipeline()
|
|||
std::vector<VkVertexInputBindingDescription> vertexBindings;
|
||||
std::vector<VkVertexInputAttributeDescription> vertexAttribs;
|
||||
|
||||
for (auto attribIndex : angle::IterateBitSet(programGL->getActiveAttribLocationsMask()))
|
||||
for (auto attribIndex : programGL->getActiveAttribLocationsMask())
|
||||
{
|
||||
const auto &attrib = attribs[attribIndex];
|
||||
const auto &binding = bindings[attrib.bindingIndex];
|
||||
|
@ -293,7 +293,7 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count)
|
|||
std::vector<VkBuffer> vertexHandles;
|
||||
std::vector<VkDeviceSize> vertexOffsets;
|
||||
|
||||
for (auto attribIndex : angle::IterateBitSet(programGL->getActiveAttribLocationsMask()))
|
||||
for (auto attribIndex : programGL->getActiveAttribLocationsMask())
|
||||
{
|
||||
const auto &attrib = attribs[attribIndex];
|
||||
const auto &binding = bindings[attrib.bindingIndex];
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
'<(angle_path)/src/tests/perf_tests/ANGLEPerfTest.h',
|
||||
'<(angle_path)/src/tests/perf_tests/BlitFramebufferPerf.cpp',
|
||||
'<(angle_path)/src/tests/perf_tests/BindingPerf.cpp',
|
||||
'<(angle_path)/src/tests/perf_tests/BitSetIteratorPerf.cpp',
|
||||
'<(angle_path)/src/tests/perf_tests/BufferSubData.cpp',
|
||||
'<(angle_path)/src/tests/perf_tests/DrawCallPerf.cpp',
|
||||
'<(angle_path)/src/tests/perf_tests/DrawCallPerfParams.cpp',
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
//
|
||||
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// IndexDataManagerPerfTest:
|
||||
// Performance test for index buffer management.
|
||||
//
|
||||
|
||||
#include "ANGLEPerfTest.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include "angle_unittests_utils.h"
|
||||
#include "common/bitset_utils.h"
|
||||
|
||||
using namespace testing;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
class BitSetIteratorPerfTest : public ANGLEPerfTest
|
||||
{
|
||||
public:
|
||||
BitSetIteratorPerfTest();
|
||||
|
||||
void step() override;
|
||||
|
||||
T mBits;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
BitSetIteratorPerfTest<T>::BitSetIteratorPerfTest() : ANGLEPerfTest("BitSetIteratorPerf", "_run")
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BitSetIteratorPerfTest<T>::step()
|
||||
{
|
||||
mBits.flip();
|
||||
|
||||
for (size_t bit : mBits)
|
||||
{
|
||||
UNUSED_VARIABLE(bit);
|
||||
}
|
||||
|
||||
mBits.reset();
|
||||
}
|
||||
|
||||
// These type names unfortunately don't get printed correctly in Gtest.
|
||||
#if defined(ANGLE_X64_CPU)
|
||||
using TestTypes = Types<angle::IterableBitSet<32>, angle::BitSet32<32>, angle::BitSet64<32>>;
|
||||
#else
|
||||
using TestTypes = Types<angle::IterableBitSet<32>, angle::BitSet32<32>>;
|
||||
#endif // defined(ANGLE_X64_CPU)
|
||||
TYPED_TEST_CASE(BitSetIteratorPerfTest, TestTypes);
|
||||
|
||||
TYPED_TEST(BitSetIteratorPerfTest, Run)
|
||||
{
|
||||
this->run();
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
Загрузка…
Ссылка в новой задаче