// Copyright 2021 The Dawn Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef SRC_DAWN_NATIVE_INDIRECTDRAWMETADATA_H_ #define SRC_DAWN_NATIVE_INDIRECTDRAWMETADATA_H_ #include #include #include #include #include #include "dawn/common/NonCopyable.h" #include "dawn/common/RefCounted.h" #include "dawn/native/Buffer.h" #include "dawn/native/CommandBufferStateTracker.h" #include "dawn/native/Commands.h" namespace dawn::native { class RenderBundleBase; struct CombinedLimits; // 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); // Metadata corresponding to the validation requirements of a single render pass. This metadata // is accumulated while its corresponding render pass is encoded, and is later used to encode // validation commands to be inserted into the command buffer just before the render pass's own // commands. class IndirectDrawMetadata : public NonCopyable { public: struct IndirectDraw { uint64_t inputBufferOffset; // This is a pointer to the command that should be populated with the validated // indirect scratch buffer. It is only valid up until the encoded command buffer // is submitted. DrawIndirectCmd* cmd; }; struct IndirectValidationBatch { uint64_t minOffset; uint64_t maxOffset; std::vector draws; }; // Tracks information about every draw call in this render pass which uses the same indirect // buffer and the same-sized index buffer. Calls are grouped by indirect offset ranges so // that validation work can be chunked efficiently if necessary. class IndexedIndirectBufferValidationInfo { public: explicit IndexedIndirectBufferValidationInfo(BufferBase* indirectBuffer); // Logs a new drawIndexedIndirect call for the render pass. `cmd` is updated with an // assigned (and deferred) buffer ref and relative offset before returning. void AddIndirectDraw(uint32_t maxDrawCallsPerIndirectValidationBatch, uint64_t maxBatchOffsetRange, IndirectDraw draw); // Adds draw calls from an already-computed batch, e.g. from a previously encoded // RenderBundle. The added batch is merged into an existing batch if possible, otherwise // it's added to mBatch. void AddBatch(uint32_t maxDrawCallsPerIndirectValidationBatch, uint64_t maxBatchOffsetRange, const IndirectValidationBatch& batch); const std::vector& GetBatches() const; private: Ref mIndirectBuffer; // A list of information about validation batches that will need to be executed for the // corresponding indirect buffer prior to a single render pass. These are kept sorted by // minOffset and may overlap iff the number of offsets in one batch would otherwise // exceed some large upper bound (roughly ~33M draw calls). // // Since the most common expected cases will overwhelmingly require only a single // validation pass per render pass, this is optimized for efficient updates to a single // batch rather than for efficient manipulation of a large number of batches. std::vector mBatches; }; enum class DrawType { NonIndexed, Indexed, }; struct IndexedIndirectConfig { BufferBase* inputIndirectBuffer; uint64_t numIndexBufferElements; bool duplicateBaseVertexInstance; DrawType drawType; bool operator<(const IndexedIndirectConfig& other) const; bool operator==(const IndexedIndirectConfig& other) const; }; using IndexedIndirectBufferValidationInfoMap = std::map; explicit IndirectDrawMetadata(const CombinedLimits& limits); ~IndirectDrawMetadata(); IndirectDrawMetadata(IndirectDrawMetadata&&); IndirectDrawMetadata& operator=(IndirectDrawMetadata&&); IndexedIndirectBufferValidationInfoMap* GetIndexedIndirectBufferValidationInfo(); void AddBundle(RenderBundleBase* bundle); void AddIndexedIndirectDraw(wgpu::IndexFormat indexFormat, uint64_t indexBufferSize, BufferBase* indirectBuffer, uint64_t indirectOffset, bool duplicateBaseVertexInstance, DrawIndexedIndirectCmd* cmd); void AddIndirectDraw(BufferBase* indirectBuffer, uint64_t indirectOffset, bool duplicateBaseVertexInstance, DrawIndirectCmd* cmd); private: IndexedIndirectBufferValidationInfoMap mIndexedIndirectBufferValidationInfo; std::set mAddedBundles; uint64_t mMaxBatchOffsetRange; uint32_t mMaxDrawCallsPerBatch; }; } // namespace dawn::native #endif // SRC_DAWN_NATIVE_INDIRECTDRAWMETADATA_H_