// Copyright 2019 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_BINDGROUPTRACKER_H_
#define SRC_DAWN_NATIVE_BINDGROUPTRACKER_H_

#include <array>
#include <bitset>

#include "dawn/common/Constants.h"
#include "dawn/native/BindGroupLayout.h"
#include "dawn/native/Pipeline.h"
#include "dawn/native/PipelineLayout.h"

namespace dawn::native {

// Keeps track of the dirty bind groups so they can be lazily applied when we know the
// pipeline state or it changes.
// |DynamicOffset| is a template parameter because offsets in Vulkan are uint32_t but uint64_t
// in other backends.
template <bool CanInheritBindGroups, typename DynamicOffset>
class BindGroupTrackerBase {
  public:
    void OnSetBindGroup(BindGroupIndex index,
                        BindGroupBase* bindGroup,
                        uint32_t dynamicOffsetCount,
                        uint32_t* dynamicOffsets) {
        ASSERT(index < kMaxBindGroupsTyped);

        if (mBindGroupLayoutsMask[index]) {
            // It is okay to only dirty bind groups that are used by the current pipeline
            // layout. If the pipeline layout changes, then the bind groups it uses will
            // become dirty.

            if (mBindGroups[index] != bindGroup) {
                mDirtyBindGroups.set(index);
                mDirtyBindGroupsObjectChangedOrIsDynamic.set(index);
            }

            if (dynamicOffsetCount > 0) {
                mDirtyBindGroupsObjectChangedOrIsDynamic.set(index);
            }
        }

        mBindGroups[index] = bindGroup;
        mDynamicOffsetCounts[index] = dynamicOffsetCount;
        SetDynamicOffsets(mDynamicOffsets[index].data(), dynamicOffsetCount, dynamicOffsets);
    }

    void OnSetPipeline(PipelineBase* pipeline) { mPipelineLayout = pipeline->GetLayout(); }

  protected:
    // The Derived class should call this before it applies bind groups.
    void BeforeApply() {
        if (mLastAppliedPipelineLayout == mPipelineLayout) {
            return;
        }

        // Use the bind group layout mask to avoid marking unused bind groups as dirty.
        mBindGroupLayoutsMask = mPipelineLayout->GetBindGroupLayoutsMask();

        // Changing the pipeline layout sets bind groups as dirty. If CanInheritBindGroups,
        // the first |k| matching bind groups may be inherited.
        if (CanInheritBindGroups && mLastAppliedPipelineLayout != nullptr) {
            // Dirty bind groups that cannot be inherited.
            BindGroupLayoutMask dirtiedGroups =
                ~mPipelineLayout->InheritedGroupsMask(mLastAppliedPipelineLayout);

            mDirtyBindGroups |= dirtiedGroups;
            mDirtyBindGroupsObjectChangedOrIsDynamic |= dirtiedGroups;

            // Clear any bind groups not in the mask.
            mDirtyBindGroups &= mBindGroupLayoutsMask;
            mDirtyBindGroupsObjectChangedOrIsDynamic &= mBindGroupLayoutsMask;
        } else {
            mDirtyBindGroups = mBindGroupLayoutsMask;
            mDirtyBindGroupsObjectChangedOrIsDynamic = mBindGroupLayoutsMask;
        }
    }

    // The Derived class should call this after it applies bind groups.
    void AfterApply() {
        // Reset all dirty bind groups. Dirty bind groups not in the bind group layout mask
        // will be dirtied again by the next pipeline change.
        mDirtyBindGroups.reset();
        mDirtyBindGroupsObjectChangedOrIsDynamic.reset();
        // Keep track of the last applied pipeline layout. This allows us to avoid computing
        // the intersection of the dirty bind groups and bind group layout mask in next Draw
        // or Dispatch (which is very hot code) until the layout is changed again.
        mLastAppliedPipelineLayout = mPipelineLayout;
    }

    BindGroupLayoutMask mDirtyBindGroups = 0;
    BindGroupLayoutMask mDirtyBindGroupsObjectChangedOrIsDynamic = 0;
    BindGroupLayoutMask mBindGroupLayoutsMask = 0;
    ityp::array<BindGroupIndex, BindGroupBase*, kMaxBindGroups> mBindGroups = {};
    ityp::array<BindGroupIndex, uint32_t, kMaxBindGroups> mDynamicOffsetCounts = {};
    ityp::array<BindGroupIndex,
                std::array<DynamicOffset, kMaxDynamicBuffersPerPipelineLayout>,
                kMaxBindGroups>
        mDynamicOffsets = {};

    // |mPipelineLayout| is the current pipeline layout set on the command buffer.
    // |mLastAppliedPipelineLayout| is the last pipeline layout for which we applied changes
    // to the bind group bindings.
    PipelineLayoutBase* mPipelineLayout = nullptr;
    PipelineLayoutBase* mLastAppliedPipelineLayout = nullptr;

  private:
    // We have two overloads here because offsets in Vulkan are uint32_t but uint64_t
    // in other backends.
    static void SetDynamicOffsets(uint64_t* data,
                                  uint32_t dynamicOffsetCount,
                                  uint32_t* dynamicOffsets) {
        for (uint32_t i = 0; i < dynamicOffsetCount; ++i) {
            data[i] = static_cast<uint64_t>(dynamicOffsets[i]);
        }
    }

    static void SetDynamicOffsets(uint32_t* data,
                                  uint32_t dynamicOffsetCount,
                                  uint32_t* dynamicOffsets) {
        if (dynamicOffsetCount > 0) {
            memcpy(data, dynamicOffsets, sizeof(uint32_t) * dynamicOffsetCount);
        }
    }
};

}  // namespace dawn::native

#endif  // SRC_DAWN_NATIVE_BINDGROUPTRACKER_H_
