// 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 DAWNNATIVE_INDIRECTDRAWMETADATA_H_
#define DAWNNATIVE_INDIRECTDRAWMETADATA_H_

#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"

#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 {
      public:
        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 {
          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 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;

          private:
            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();

        IndirectDrawMetadata(IndirectDrawMetadata&&);
        IndirectDrawMetadata& operator=(IndirectDrawMetadata&&);

        IndexedIndirectBufferValidationInfoMap* GetIndexedIndirectBufferValidationInfo();

        void AddBundle(RenderBundleBase* bundle);
        void AddIndexedIndirectDraw(wgpu::IndexFormat indexFormat,
                                    uint64_t indexBufferSize,
                                    BufferBase* indirectBuffer,
                                    uint64_t indirectOffset,
                                    DrawIndexedIndirectCmd* cmd);

      private:
        IndexedIndirectBufferValidationInfoMap mIndexedIndirectBufferValidationInfo;
        std::set<RenderBundleBase*> mAddedBundles;

        uint32_t mMaxDrawCallsPerBatch;
        uint32_t mMaxBatchOffsetRange;
    };

}  // namespace dawn::native

#endif  // DAWNNATIVE_INDIRECTDRAWMETADATA_H_
