Track IndirectDrawIndex for all indirect draws Adds an IndirectDrawIndex that tracks the order of indirect draw calls in a render pass so that they can be associated with validated args later. Includes updating the indices of indirect draws merged in from a RenderBundle after the validation batches have been merged. Bug: 495489174 Change-Id: I1639f4f1f827fe8935b6c366b0ab913612fd95e7 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/305976 Commit-Queue: Brandon Jones <bajones@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/native/IndirectDrawMetadata.cpp b/src/dawn/native/IndirectDrawMetadata.cpp index 72fa797..4ab3ab2 100644 --- a/src/dawn/native/IndirectDrawMetadata.cpp +++ b/src/dawn/native/IndirectDrawMetadata.cpp
@@ -103,12 +103,23 @@ mBatches.insert(it, std::move(newBatch)); } +void AdjustValidatedDrawIndex(std::vector<IndirectDrawMetadata::IndirectDraw>& draws, + std::vector<IndirectDrawMetadata::IndirectDraw>::iterator begin, + IndirectDrawIndex indirectDrawIndexOffset) { + // Ensure that the validatedDrawIndex is properly offset for every newly inserted draw. + for (auto it = begin; it != draws.end(); ++it) { + it->validatedDrawIndex += indirectDrawIndexOffset; + } +} + void IndirectDrawMetadata::IndexedIndirectBufferValidationInfo::AddBatch( uint32_t maxDrawCallsPerIndirectValidationBatch, uint64_t maxBatchOffsetRange, - const IndirectValidationBatch& newBatch) { + const IndirectValidationBatch& newBatch, + IndirectDrawIndex indirectDrawIndexOffset) { auto it = mBatches.begin(); while (it != mBatches.end()) { + // TODO(crbug.com/495489174): Investigate simplifying this. IndirectValidationBatch& batch = *it; uint64_t min = std::min(newBatch.minOffset, batch.minOffset); uint64_t max = std::max(newBatch.maxOffset, batch.maxOffset); @@ -117,7 +128,10 @@ // This batch fits within the limits of an existing batch. Merge it. batch.minOffset = min; batch.maxOffset = max; - batch.draws.insert(batch.draws.end(), newBatch.draws.begin(), newBatch.draws.end()); + + auto insertedDraws = + batch.draws.insert(batch.draws.end(), newBatch.draws.begin(), newBatch.draws.end()); + AdjustValidatedDrawIndex(batch.draws, insertedDraws, indirectDrawIndexOffset); return; } @@ -127,7 +141,11 @@ ++it; } - mBatches.push_back(newBatch); + { + mBatches.push_back(newBatch); + IndirectValidationBatch& batch = mBatches.back(); + AdjustValidatedDrawIndex(batch.draws, batch.draws.begin(), indirectDrawIndexOffset); + } } const std::vector<IndirectDrawMetadata::IndirectValidationBatch>& @@ -168,13 +186,17 @@ for (const auto& [config, validationInfo] : bundle->GetIndirectDrawMetadata().mIndexedIndirectBufferValidationInfo) { auto it = mIndexedIndirectBufferValidationInfo.lower_bound(config); - if (it != mIndexedIndirectBufferValidationInfo.end() && it->first == config) { - // We already have batches for the same config. Merge the new ones in. - for (const IndirectValidationBatch& batch : validationInfo.GetBatches()) { - it->second.AddBatch(mMaxDrawCallsPerBatch, mMaxBatchOffsetRange, batch); - } - } else { - mIndexedIndirectBufferValidationInfo.emplace_hint(it, config, validationInfo); + if (it == mIndexedIndirectBufferValidationInfo.end() || it->first != config) { + it = mIndexedIndirectBufferValidationInfo.emplace_hint( + it, config, + IndexedIndirectBufferValidationInfo(validationInfo.GetIndirectBuffer())); + } + + // Merge the bundle's batches in. + for (const IndirectValidationBatch& batch : validationInfo.GetBatches()) { + it->second.AddBatch(mMaxDrawCallsPerBatch, mMaxBatchOffsetRange, batch, + mNextIndirectDrawIndex); + mNextIndirectDrawIndex += IndirectDrawIndex(batch.draws.size()); } } } @@ -211,6 +233,7 @@ } IndirectDraw draw{}; + draw.validatedDrawIndex = mNextIndirectDrawIndex++; draw.inputBufferOffset = indirectOffset; draw.numIndexBufferElements = numIndexBufferElements; draw.indexBufferOffsetInElements = indexBufferOffsetInElements; @@ -232,6 +255,7 @@ } IndirectDraw draw{}; + draw.validatedDrawIndex = mNextIndirectDrawIndex++; draw.inputBufferOffset = indirectOffset; draw.numIndexBufferElements = 0; draw.cmd = cmd;
diff --git a/src/dawn/native/IndirectDrawMetadata.h b/src/dawn/native/IndirectDrawMetadata.h index e58813b..f34297b 100644 --- a/src/dawn/native/IndirectDrawMetadata.h +++ b/src/dawn/native/IndirectDrawMetadata.h
@@ -46,6 +46,11 @@ class RenderBundleBase; struct CombinedLimits; +// The IndirectDrawIndex indicates the order in which an indirect draw is executed in a render +// pass. It is tracked to enable association of validated buffer/offset data with the original +// draw after draws are batched for validation. +using IndirectDrawIndex = TypedInteger<struct IndirectDrawIndexT, uint64_t>; + // In the unlikely scenario that indirect offsets used over a single buffer span more than // this length of the buffer, we split the validation work into multiple batches. uint64_t ComputeMaxIndirectValidationBatchOffsetRange(const CombinedLimits& limits); @@ -62,6 +67,7 @@ }; struct IndirectDraw { + IndirectDrawIndex validatedDrawIndex; uint64_t inputBufferOffset; uint64_t numIndexBufferElements; uint64_t indexBufferOffsetInElements; @@ -115,7 +121,8 @@ // it's added to mBatch. void AddBatch(uint32_t maxDrawCallsPerIndirectValidationBatch, uint64_t maxBatchOffsetRange, - const IndirectValidationBatch& batch); + const IndirectValidationBatch& batch, + IndirectDrawIndex indirectDrawIndexOffset); const std::vector<IndirectValidationBatch>& GetBatches() const; @@ -192,6 +199,8 @@ std::vector<IndirectMultiDraw> mMultiDraws; + IndirectDrawIndex mNextIndirectDrawIndex{0}; + uint64_t mMaxBatchOffsetRange; uint32_t mMaxDrawCallsPerBatch; };