1 // Copyright 2021 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef DAWNNATIVE_INDIRECTDRAWMETADATA_H_ 16 #define DAWNNATIVE_INDIRECTDRAWMETADATA_H_ 17 18 #include "common/NonCopyable.h" 19 #include "common/RefCounted.h" 20 #include "dawn_native/Buffer.h" 21 #include "dawn_native/CommandBufferStateTracker.h" 22 #include "dawn_native/Commands.h" 23 24 #include <cstdint> 25 #include <map> 26 #include <set> 27 #include <utility> 28 #include <vector> 29 30 namespace dawn_native { 31 32 class RenderBundleBase; 33 struct CombinedLimits; 34 35 // In the unlikely scenario that indirect offsets used over a single buffer span more than 36 // this length of the buffer, we split the validation work into multiple batches. 37 uint32_t ComputeMaxIndirectValidationBatchOffsetRange(const CombinedLimits& limits); 38 39 // Metadata corresponding to the validation requirements of a single render pass. This metadata 40 // is accumulated while its corresponding render pass is encoded, and is later used to encode 41 // validation commands to be inserted into the command buffer just before the render pass's own 42 // commands. 43 class IndirectDrawMetadata : public NonCopyable { 44 public: 45 struct IndexedIndirectDraw { 46 uint64_t clientBufferOffset; 47 // This is a pointer to the command that should be populated with the validated 48 // indirect scratch buffer. It is only valid up until the encoded command buffer 49 // is submitted. 50 DrawIndexedIndirectCmd* cmd; 51 }; 52 53 struct IndexedIndirectValidationBatch { 54 uint64_t minOffset; 55 uint64_t maxOffset; 56 std::vector<IndexedIndirectDraw> draws; 57 }; 58 59 // Tracks information about every draw call in this render pass which uses the same indirect 60 // buffer and the same-sized index buffer. Calls are grouped by indirect offset ranges so 61 // that validation work can be chunked efficiently if necessary. 62 class IndexedIndirectBufferValidationInfo { 63 public: 64 explicit IndexedIndirectBufferValidationInfo(BufferBase* indirectBuffer); 65 66 // Logs a new drawIndexedIndirect call for the render pass. `cmd` is updated with an 67 // assigned (and deferred) buffer ref and relative offset before returning. 68 void AddIndexedIndirectDraw(uint32_t maxDrawCallsPerIndirectValidationBatch, 69 uint32_t maxBatchOffsetRange, 70 IndexedIndirectDraw draw); 71 72 // Adds draw calls from an already-computed batch, e.g. from a previously encoded 73 // RenderBundle. The added batch is merged into an existing batch if possible, otherwise 74 // it's added to mBatch. 75 void AddBatch(uint32_t maxDrawCallsPerIndirectValidationBatch, 76 uint32_t maxBatchOffsetRange, 77 const IndexedIndirectValidationBatch& batch); 78 79 const std::vector<IndexedIndirectValidationBatch>& GetBatches() const; 80 81 private: 82 Ref<BufferBase> mIndirectBuffer; 83 84 // A list of information about validation batches that will need to be executed for the 85 // corresponding indirect buffer prior to a single render pass. These are kept sorted by 86 // minOffset and may overlap iff the number of offsets in one batch would otherwise 87 // exceed some large upper bound (roughly ~33M draw calls). 88 // 89 // Since the most common expected cases will overwhelmingly require only a single 90 // validation pass per render pass, this is optimized for efficient updates to a single 91 // batch rather than for efficient manipulation of a large number of batches. 92 std::vector<IndexedIndirectValidationBatch> mBatches; 93 }; 94 95 // Combination of an indirect buffer reference, and the number of addressable index buffer 96 // elements at the time of a draw call. 97 using IndexedIndirectConfig = std::pair<BufferBase*, uint64_t>; 98 using IndexedIndirectBufferValidationInfoMap = 99 std::map<IndexedIndirectConfig, IndexedIndirectBufferValidationInfo>; 100 101 explicit IndirectDrawMetadata(const CombinedLimits& limits); 102 ~IndirectDrawMetadata(); 103 104 IndirectDrawMetadata(IndirectDrawMetadata&&); 105 IndirectDrawMetadata& operator=(IndirectDrawMetadata&&); 106 107 IndexedIndirectBufferValidationInfoMap* GetIndexedIndirectBufferValidationInfo(); 108 109 void AddBundle(RenderBundleBase* bundle); 110 void AddIndexedIndirectDraw(wgpu::IndexFormat indexFormat, 111 uint64_t indexBufferSize, 112 BufferBase* indirectBuffer, 113 uint64_t indirectOffset, 114 DrawIndexedIndirectCmd* cmd); 115 116 private: 117 IndexedIndirectBufferValidationInfoMap mIndexedIndirectBufferValidationInfo; 118 std::set<RenderBundleBase*> mAddedBundles; 119 120 uint32_t mMaxDrawCallsPerBatch; 121 uint32_t mMaxBatchOffsetRange; 122 }; 123 124 } // namespace dawn_native 125 126 #endif // DAWNNATIVE_INDIRECTDRAWMETADATA_H_ 127