Skip to content

Commit 233ab4e

Browse files
committed
feat(d3d11, dxmt): record potential hazard info in binding bitset
Since not all bound resource may introduce hazard, it would be a even sparser set.
1 parent 78cfaf5 commit 233ab4e

2 files changed

Lines changed: 22 additions & 7 deletions

File tree

src/d3d11/d3d11_context_impl.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2676,8 +2676,8 @@ template <typename ContextInternalState> class MTLD3D11DeviceContextImplBase : p
26762676

26772677
auto &SRVs = state_.ShaderStages[Stage].SRVs;
26782678

2679-
// TODO: iterate _hazard_ set rather than _bound_ set (former is a subset)
2680-
for (const auto & [Slot, Bound] : SRVs) {
2679+
for (auto it = SRVs.hazard_begin(); it != SRVs.hazard_end(); it++) {
2680+
const auto & [Slot, Bound] = *it;
26812681
if (CheckOverlap(Bound.SRV.ptr(), pViewOrBuffer)) {
26822682
if (SRVs.unbind(Slot)) {
26832683
EmitST([=](ArgumentEncodingContext& enc) {
@@ -2710,8 +2710,9 @@ template <typename ContextInternalState> class MTLD3D11DeviceContextImplBase : p
27102710
}
27112711

27122712
if (pViewOrBuffer->bindFlags() & D3D11_BIND_VERTEX_BUFFER) {
2713-
// TODO: iterate _hazard_ set rather than _bound_ set (former is a subset)
2714-
for (const auto &[Slot, Bound] : state_.InputAssembler.VertexBuffers) {
2713+
for (auto it = state_.InputAssembler.VertexBuffers.hazard_begin();
2714+
it != state_.InputAssembler.VertexBuffers.hazard_end(); it++) {
2715+
const auto &[Slot, Bound] = *it;
27152716
if (CheckOverlap(Bound.Buffer.ptr(), pViewOrBuffer)) {
27162717
if (state_.InputAssembler.VertexBuffers.unbind(Slot)) {
27172718
EmitST([=](ArgumentEncodingContext &enc) { enc.bindVertexBuffer(Slot, 0, 0, {}); });
@@ -3492,7 +3493,7 @@ template <typename ContextInternalState> class MTLD3D11DeviceContextImplBase : p
34923493
auto pView = static_cast<D3D11ShaderResourceView *>(ppShaderResourceViews[slot - StartSlot]);
34933494
if (pView && ValidateSRVHazard<Stage>(pView)) {
34943495
bool replaced = false;
3495-
auto &entry = ShaderStage.SRVs.bind(slot, {pView}, replaced);
3496+
auto &entry = ShaderStage.SRVs.bind(slot, {pView}, replaced, !pView->hazardsFree());
34963497
if (!replaced)
34973498
continue;
34983499
entry.SRV = pView;
@@ -3641,7 +3642,7 @@ template <typename ContextInternalState> class MTLD3D11DeviceContextImplBase : p
36413642
auto pVertexBuffer = reinterpret_cast<D3D11ResourceCommon *>(ppVertexBuffers[slot - StartSlot]);
36423643
if (pVertexBuffer && (pVertexBuffer->bindFlags() & D3D11_BIND_VERTEX_BUFFER) && ValidateIAHazard(pVertexBuffer)) {
36433644
bool replaced = false;
3644-
auto &entry = VertexBuffers.bind(slot, {pVertexBuffer}, replaced);
3645+
auto &entry = VertexBuffers.bind(slot, {pVertexBuffer}, replaced, !pVertexBuffer->hazardsFree());
36453646
if (!replaced) {
36463647
if (pStrides && pStrides[slot - StartSlot] != entry.Stride) {
36473648
VertexBuffers.set_dirty(slot);

src/dxmt/dxmt_binding_set.hpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Element is required to be move-assignable
1414
template <typename Element, size_t NumElements> class BindingSet {
1515
bit::bitset<NumElements> dirty;
1616
bit::bitset<NumElements> bound;
17+
bit::bitset<NumElements> hazard;
1718
std::array<Element, NumElements> storage;
1819

1920
public:
@@ -22,13 +23,15 @@ template <typename Element, size_t NumElements> class BindingSet {
2223
BindingSet(BindingSet &&move) : storage(std::move(move.storage)) {
2324
bound = move.bound;
2425
dirty = move.bound; // intended behavior
26+
hazard = move.hazard;
2527
};
2628

2729
BindingSet &
2830
operator=(BindingSet &&move) {
2931
storage = std::move(move.storage);
3032
bound = move.bound;
3133
dirty = move.bound; // intended behavior
34+
hazard = move.hazard;
3235
return *this;
3336
}
3437

@@ -121,13 +124,14 @@ template <typename Element, size_t NumElements> class BindingSet {
121124
(so no initialization overhead if no replacement)
122125
*/
123126
inline Element &
124-
bind(size_t slot, Element &&element, bool &replacement) {
127+
bind(size_t slot, Element &&element, bool &replacement, bool hazard = true) {
125128
if (bound.get(slot)) {
126129
if (redunant_binding_trait<Element>::is_redunant(storage[slot], element)) {
127130
return storage[slot];
128131
}
129132
} else {
130133
bound.set(slot, true);
134+
this->hazard.set(slot, hazard);
131135
}
132136
// new (storage.data() + slot) Element(std::forward<Element>(element));
133137
// std::construct_at(storage.data() + slot, std::forward<Element>(element));
@@ -149,6 +153,7 @@ template <typename Element, size_t NumElements> class BindingSet {
149153
// at bind()
150154
storage[slot] = {};
151155
bound.set(slot, false);
156+
hazard.set(slot, false);
152157
dirty.set(slot, true);
153158
return true;
154159
}
@@ -223,5 +228,14 @@ template <typename Element, size_t NumElements> class BindingSet {
223228
end() const {
224229
return NumElements;
225230
}
231+
232+
bound_iterator
233+
hazard_begin() const {
234+
return bound_iterator(*this, hazard, 0);
235+
}
236+
uint64_t
237+
hazard_end() const {
238+
return NumElements;
239+
}
226240
};
227241
} // namespace dxmt

0 commit comments

Comments
 (0)