blob: c4f62fabb4829c08212eeb01fa38779f01af4421 [file] [log] [blame]
// 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
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
#include "common/NonCopyable.h"
#include "common/RefCounted.h"
#include "dawn_native/Buffer.h"
#include "dawn_native/CommandBufferStateTracker.h"
#include "dawn_native/Commands.h"
#include <cstdint>
#include <map>
#include <set>
#include <utility>
#include <vector>
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.
uint32_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 {
struct IndexedIndirectDraw {
uint64_t clientBufferOffset;
// 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.
DrawIndexedIndirectCmd* cmd;
struct IndexedIndirectValidationBatch {
uint64_t minOffset;
uint64_t maxOffset;
std::vector<IndexedIndirectDraw> 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 {
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 AddIndexedIndirectDraw(uint32_t maxDrawCallsPerIndirectValidationBatch,
uint32_t maxBatchOffsetRange,
IndexedIndirectDraw 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,
uint32_t maxBatchOffsetRange,
const IndexedIndirectValidationBatch& batch);
const std::vector<IndexedIndirectValidationBatch>& GetBatches() const;
Ref<BufferBase> 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<IndexedIndirectValidationBatch> mBatches;
// Combination of an indirect buffer reference, and the number of addressable index buffer
// elements at the time of a draw call.
using IndexedIndirectConfig = std::pair<BufferBase*, uint64_t>;
using IndexedIndirectBufferValidationInfoMap =
std::map<IndexedIndirectConfig, IndexedIndirectBufferValidationInfo>;
explicit IndirectDrawMetadata(const CombinedLimits& limits);
IndirectDrawMetadata& operator=(IndirectDrawMetadata&&);
IndexedIndirectBufferValidationInfoMap* GetIndexedIndirectBufferValidationInfo();
void AddBundle(RenderBundleBase* bundle);
void AddIndexedIndirectDraw(wgpu::IndexFormat indexFormat,
uint64_t indexBufferSize,
BufferBase* indirectBuffer,
uint64_t indirectOffset,
DrawIndexedIndirectCmd* cmd);
IndexedIndirectBufferValidationInfoMap mIndexedIndirectBufferValidationInfo;
std::set<RenderBundleBase*> mAddedBundles;
uint32_t mMaxDrawCallsPerBatch;
uint32_t mMaxBatchOffsetRange;
} // namespace dawn::native