yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Darren WihandiFix UIntSet calcSubtract to handle mismatched buffer sizes (#6205)1f99c2086

master
5.6 KiB209 linesraw
1#include "slang-uint-set.h"
2
3namespace Slang
4{
5
6Index UIntSet::getLSBZero()
7{
8    uint64_t offset = 0;
9    for (Element& element : this->m_buffer)
10    {
11        // Flip all bits so bitscanForward can find a 0 bit
12        Element flippedElement = ~element;
13
14        // continue if we don't have 0 bits
15        if (flippedElement == 0)
16        {
17            offset += sizeof(Element) * 8;
18            continue;
19        }
20
21        // Get LSBZero of current Block, add with offset
22        return bitscanForward(flippedElement) + offset;
23    }
24    return offset;
25}
26
27UIntSet& UIntSet::operator=(UIntSet&& other)
28{
29    m_buffer = _Move(other.m_buffer);
30    return *this;
31}
32
33UIntSet& UIntSet::operator=(const UIntSet& other)
34{
35    m_buffer = other.m_buffer;
36    return *this;
37}
38
39HashCode UIntSet::getHashCode() const
40{
41    int rs = 0;
42    for (auto val : m_buffer)
43        rs ^= val;
44    return rs;
45}
46
47void UIntSet::resizeAndClear(UInt val)
48{
49    // TODO(JS): This could be faster in that if the resize is larger the additional area is cleared
50    // twice
51    resize(val);
52    clear();
53}
54
55void UIntSet::setAll()
56{
57    ::memset(m_buffer.getBuffer(), -1, m_buffer.getCount() * sizeof(Element));
58}
59
60void UIntSet::resize(UInt size)
61{
62    const Index newCount = Index((size + kElementMask) >> kElementShift);
63    resizeBackingBufferDirectly(newCount);
64}
65
66void UIntSet::clear()
67{
68    ::memset(m_buffer.getBuffer(), 0, m_buffer.getCount() * sizeof(Element));
69}
70
71bool UIntSet::isEmpty() const
72{
73    return _areAllZero(m_buffer.getBuffer(), m_buffer.getCount());
74}
75
76void UIntSet::clearAndDeallocate()
77{
78    m_buffer.clearAndDeallocate();
79}
80
81void UIntSet::unionWith(const UIntSet& set)
82{
83    const Index minCount = Math::Min(set.m_buffer.getCount(), m_buffer.getCount());
84    for (Index i = 0; i < minCount; i++)
85    {
86        m_buffer[i] |= set.m_buffer[i];
87    }
88
89    if (set.m_buffer.getCount() > m_buffer.getCount())
90        m_buffer.addRange(
91            set.m_buffer.getBuffer() + m_buffer.getCount(),
92            set.m_buffer.getCount() - m_buffer.getCount());
93}
94
95bool UIntSet::operator==(const UIntSet& set) const
96{
97    const Index aCount = m_buffer.getCount();
98    const auto aElems = m_buffer.getBuffer();
99
100    const Index bCount = set.m_buffer.getCount();
101    const auto bElems = set.m_buffer.getBuffer();
102
103    const Index minCount = Math::Min(aCount, bCount);
104
105    return ::memcmp(aElems, bElems, minCount * sizeof(Element)) == 0 &&
106           _areAllZero(aElems + minCount, aCount - minCount) &&
107           _areAllZero(bElems + minCount, bCount - minCount);
108}
109
110void UIntSet::intersectWith(const UIntSet& set)
111{
112    if (set.m_buffer.getCount() < m_buffer.getCount())
113        ::memset(
114            m_buffer.getBuffer() + set.m_buffer.getCount(),
115            0,
116            (m_buffer.getCount() - set.m_buffer.getCount()) * sizeof(Element));
117
118    const Index minCount = Math::Min(set.m_buffer.getCount(), m_buffer.getCount());
119    for (Index i = 0; i < minCount; i++)
120    {
121        m_buffer[i] &= set.m_buffer[i];
122    }
123}
124
125void UIntSet::subtractWith(const UIntSet& set)
126{
127    const Index minCount = Math::Min(this->m_buffer.getCount(), set.m_buffer.getCount());
128    for (Index i = 0; i < minCount; i++)
129    {
130        this->m_buffer[i] = this->m_buffer[i] & (~set.m_buffer[i]);
131    }
132}
133
134/* static */ void UIntSet::calcUnion(UIntSet& outRs, const UIntSet& set1, const UIntSet& set2)
135{
136    outRs.resizeBackingBufferDirectly(
137        Math::Max(set1.m_buffer.getCount(), set2.m_buffer.getCount()));
138    outRs.clear();
139    for (Index i = 0; i < set1.m_buffer.getCount(); i++)
140        outRs.m_buffer[i] |= set1.m_buffer[i];
141    for (Index i = 0; i < set2.m_buffer.getCount(); i++)
142        outRs.m_buffer[i] |= set2.m_buffer[i];
143}
144
145/* static */ void UIntSet::calcIntersection(
146    UIntSet& outRs,
147    const UIntSet& set1,
148    const UIntSet& set2)
149{
150    const Index minCount = Math::Min(set1.m_buffer.getCount(), set2.m_buffer.getCount());
151    outRs.resizeBackingBufferDirectly(minCount);
152
153    for (Index i = 0; i < minCount; i++)
154        outRs.m_buffer[i] = set1.m_buffer[i] & set2.m_buffer[i];
155}
156
157/* static */ void UIntSet::calcSubtract(UIntSet& outRs, const UIntSet& set1, const UIntSet& set2)
158{
159    const auto set1Count = set1.m_buffer.getCount();
160    const auto set2Count = set2.m_buffer.getCount();
161
162    outRs.resizeBackingBufferDirectly(set1Count);
163
164    for (Index i = 0; i < set1Count; i++)
165    {
166        if (i < set2Count)
167        {
168            outRs.m_buffer[i] = set1.m_buffer[i] & (~set2.m_buffer[i]);
169        }
170        else
171        {
172            // If `set2` is smaller, copy the remaining values from `set1`
173            outRs.m_buffer[i] = set1.m_buffer[i];
174        }
175    }
176}
177
178/* static */ bool UIntSet::hasIntersection(const UIntSet& set1, const UIntSet& set2)
179{
180    const Index minCount = Math::Min(set1.m_buffer.getCount(), set2.m_buffer.getCount());
181    for (Index i = 0; i < minCount; i++)
182    {
183        if (set1.m_buffer[i] & set2.m_buffer[i])
184            return true;
185    }
186    return false;
187}
188
189Index UIntSet::countElements() const
190{
191    // TODO: This can be made faster using SIMD intrinsics to count set bits.
192    uint64_t tmp;
193    constexpr Index loopSize =
194        ((sizeof(Element) / sizeof(tmp)) != 0) ? sizeof(Element) / sizeof(tmp) : 1;
195    Index count = 0;
196    for (auto index = 0; index < this->m_buffer.getCount(); index++)
197    {
198        for (auto i = 0; i < loopSize; i++)
199        {
200            tmp = m_buffer[index] >> (sizeof(tmp) * i);
201            tmp = tmp - ((tmp >> 1) & 0x5555555555555555);
202            tmp = (tmp & 0x3333333333333333) + ((tmp >> 2) & 0x3333333333333333);
203            count += ((tmp + (tmp >> 4) & 0xF0F0F0F0F0F0F0F) * 0x101010101010101) >> 56;
204        }
205    }
206    return count;
207}
208
209} // namespace Slang