// Copyright 2023 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "dawn/native/d3d11/BindGroupTrackerD3D11.h"

#include <algorithm>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

#include "dawn/common/Assert.h"
#include "dawn/common/MatchVariant.h"
#include "dawn/common/Range.h"
#include "dawn/native/Format.h"
#include "dawn/native/d3d/D3DError.h"
#include "dawn/native/d3d11/BindGroupD3D11.h"
#include "dawn/native/d3d11/BufferD3D11.h"
#include "dawn/native/d3d11/CommandRecordingContextD3D11.h"
#include "dawn/native/d3d11/DeviceD3D11.h"
#include "dawn/native/d3d11/PipelineLayoutD3D11.h"
#include "dawn/native/d3d11/SamplerD3D11.h"
#include "dawn/native/d3d11/TextureD3D11.h"

namespace dawn::native::d3d11 {
namespace {

constexpr auto kVertex = SingleShaderStage::Vertex;
constexpr auto kFragment = SingleShaderStage::Fragment;
constexpr auto kCompute = SingleShaderStage::Compute;

bool CheckAllSlotsAreEmpty(const ScopedSwapStateCommandRecordingContext* commandContext) {
    auto* deviceContext = commandContext->GetD3D11DeviceContext3();

    // Reserve one slot for builtin constants.
    constexpr uint32_t kReservedCBVSlots = 1;

    // Check constant buffer slots
    for (UINT slot = 0;
         slot < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - kReservedCBVSlots; ++slot) {
        ID3D11Buffer* buffer = nullptr;
        deviceContext->VSGetConstantBuffers1(slot, 1, &buffer, nullptr, nullptr);
        DAWN_ASSERT(buffer == nullptr);
        deviceContext->PSGetConstantBuffers1(slot, 1, &buffer, nullptr, nullptr);
        DAWN_ASSERT(buffer == nullptr);
        deviceContext->CSGetConstantBuffers1(slot, 1, &buffer, nullptr, nullptr);
        DAWN_ASSERT(buffer == nullptr);
    }

    // Check resource slots
    for (UINT slot = 0; slot < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++slot) {
        ID3D11ShaderResourceView* srv = nullptr;
        deviceContext->VSGetShaderResources(slot, 1, &srv);
        DAWN_ASSERT(srv == nullptr);
        deviceContext->PSGetShaderResources(slot, 1, &srv);
        DAWN_ASSERT(srv == nullptr);
        deviceContext->CSGetShaderResources(slot, 1, &srv);
        DAWN_ASSERT(srv == nullptr);
    }

    // Check sampler slots
    for (UINT slot = 0; slot < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++slot) {
        ID3D11SamplerState* sampler = nullptr;
        deviceContext->VSGetSamplers(slot, 1, &sampler);
        DAWN_ASSERT(sampler == nullptr);
        deviceContext->PSGetSamplers(slot, 1, &sampler);
        DAWN_ASSERT(sampler == nullptr);
        deviceContext->CSGetSamplers(slot, 1, &sampler);
        DAWN_ASSERT(sampler == nullptr);
    }

    // Check UAV slots for compute
    for (UINT slot = 0; slot < D3D11_1_UAV_SLOT_COUNT; ++slot) {
        ID3D11UnorderedAccessView* uav = nullptr;
        deviceContext->CSGetUnorderedAccessViews(slot, 1, &uav);
        DAWN_ASSERT(uav == nullptr);
    }
    // Check UAV slots for render
    for (UINT slot = 0; slot < commandContext->GetDevice()->GetUAVSlotCount(); ++slot) {
        ID3D11UnorderedAccessView* uav = nullptr;
        deviceContext->OMGetRenderTargetsAndUnorderedAccessViews(0, nullptr, nullptr, slot, 1,
                                                                 &uav);
        DAWN_ASSERT(uav == nullptr);
    }

    return true;
}

std::tuple<const BindingInfo&, BufferBinding> ExtractBufferBindingInfo(
    BindGroupBase* group,
    BindingIndex bindingIndex,
    const BufferBindingInfo& layout,
    const ityp::span<BindingIndex, uint32_t>& dynamicOffsets) {
    const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(bindingIndex);

    BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
    if (layout.hasDynamicOffset) {
        binding.offset += dynamicOffsets[bindingIndex];
    }

    return std::make_tuple(std::cref(bindingInfo), std::move(binding));
}

template <SingleShaderStage Stage, typename... Args>
void SetConstantBuffersImpl(ID3D11DeviceContext3* deviceContext, Args&&... args) {
    if constexpr (Stage == kVertex) {
        deviceContext->VSSetConstantBuffers1(std::forward<Args>(args)...);
    } else if constexpr (Stage == kFragment) {
        deviceContext->PSSetConstantBuffers1(std::forward<Args>(args)...);
    } else if constexpr (Stage == kCompute) {
        deviceContext->CSSetConstantBuffers1(std::forward<Args>(args)...);
    }
}

template <SingleShaderStage Stage, typename... Args>
void SetShaderResourcesImpl(ID3D11DeviceContext3* deviceContext, Args&&... args) {
    if constexpr (Stage == kVertex) {
        deviceContext->VSSetShaderResources(std::forward<Args>(args)...);
    } else if constexpr (Stage == kFragment) {
        deviceContext->PSSetShaderResources(std::forward<Args>(args)...);
    } else if constexpr (Stage == kCompute) {
        deviceContext->CSSetShaderResources(std::forward<Args>(args)...);
    }
}

template <SingleShaderStage Stage, typename... Args>
void SetSamplersImpl(ID3D11DeviceContext3* deviceContext, Args&&... args) {
    if constexpr (Stage == kVertex) {
        deviceContext->VSSetSamplers(std::forward<Args>(args)...);
    } else if constexpr (Stage == kFragment) {
        deviceContext->PSSetSamplers(std::forward<Args>(args)...);
    } else if constexpr (Stage == kCompute) {
        deviceContext->CSSetSamplers(std::forward<Args>(args)...);
    }
}

template <SingleShaderStage Stage, typename... Args>
void SetUnorderedAccessViewsImpl(ID3D11DeviceContext3* deviceContext, Args&&... args) {
    if constexpr (Stage == kFragment) {
        deviceContext->OMSetRenderTargetsAndUnorderedAccessViews(
            D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr,
            std::forward<Args>(args)..., nullptr);
    } else if constexpr (Stage == kCompute) {
        deviceContext->CSSetUnorderedAccessViews(std::forward<Args>(args)..., nullptr);
    } else {
        DAWN_UNREACHABLE();
    }
}

}  // namespace

template <typename T, uint32_t InitialCapacity>
template <typename Fn>
void BindGroupTracker::BindingSlot<T, InitialCapacity>::Bind(uint32_t idx,
                                                             T binding,
                                                             Fn&& bindFunc) {
    if (MaxBoundSlots() <= idx) {
        mBoundSlots.resize(idx + 1);
    }
    if (mBoundSlots[idx] == binding) {
        // redundant binding, return
        return;
    }

    bindFunc(idx, binding);

    mBoundSlots[idx] = std::move(binding);
}

BindGroupTracker::BindGroupTracker(const ScopedSwapStateCommandRecordingContext* commandContext)
    : mCommandContext(commandContext) {
    mLastAppliedPipelineLayout = mCommandContext->GetDevice()->GetEmptyPipelineLayout();
}

BindGroupTracker::~BindGroupTracker() {
    UnbindConstantBuffers<kVertex>();
    UnbindConstantBuffers<kFragment>();
    UnbindConstantBuffers<kCompute>();

    UnbindShaderResources<kVertex>();
    UnbindShaderResources<kFragment>();
    UnbindShaderResources<kCompute>();

    UnbindSamplers<kVertex>();
    UnbindSamplers<kFragment>();
    UnbindSamplers<kCompute>();

    UnbindUnorderedAccessViews<kFragment>();
    UnbindUnorderedAccessViews<kCompute>();

    DAWN_ASSERT(CheckAllSlotsAreEmpty(mCommandContext));
}

template <SingleShaderStage Stage>
void BindGroupTracker::SetConstantBuffer(uint32_t idx,
                                         ID3D11Buffer* d3d11Buffer,
                                         uint32_t firstConstant,
                                         uint32_t numConstants) {
    mConstantBufferSlots[Stage].Bind(idx, {d3d11Buffer, firstConstant, numConstants},
                                     [this](size_t idx, const ConstantBufferBinding& binding) {
                                         SetConstantBuffersImpl<Stage>(
                                             mCommandContext->GetD3D11DeviceContext3(), idx, 1,
                                             binding.buffer.GetAddressOf(), &binding.firstConstant,
                                             &binding.numConstants);
                                     });
}

template <SingleShaderStage Stage>
void BindGroupTracker::UnbindConstantBuffers() {
    const auto slots = mConstantBufferSlots[Stage].MaxBoundSlots();
    if (slots == 0) {
        return;
    }

    static constexpr ID3D11Buffer* kNullBuffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] =
        {};

    SetConstantBuffersImpl<Stage>(mCommandContext->GetD3D11DeviceContext3(), 0, slots, kNullBuffers,
                                  nullptr, nullptr);
}

template <SingleShaderStage Stage>
void BindGroupTracker::SetShaderResource(uint32_t idx, ID3D11ShaderResourceView* srv) {
    mSRVSlots[Stage].Bind(
        idx, std::move(srv), [this](size_t idx, const ComPtr<ID3D11ShaderResourceView>& binding) {
            SetShaderResourcesImpl<Stage>(mCommandContext->GetD3D11DeviceContext3(), idx, 1,
                                          binding.GetAddressOf());
        });
}

template <SingleShaderStage Stage>
void BindGroupTracker::UnbindShaderResources() {
    const auto slots = mSRVSlots[Stage].MaxBoundSlots();
    if (slots == 0) {
        return;
    }

    static constexpr ID3D11ShaderResourceView*
        kNullSRVs[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {};

    SetShaderResourcesImpl<Stage>(mCommandContext->GetD3D11DeviceContext3(), 0, slots, kNullSRVs);
}

template <SingleShaderStage Stage>
void BindGroupTracker::SetSampler(uint32_t idx, ID3D11SamplerState* sampler) {
    mSamplerSlots[Stage].Bind(idx, sampler,
                              [this](size_t idx, const ComPtr<ID3D11SamplerState>& binding) {
                                  SetSamplersImpl<Stage>(mCommandContext->GetD3D11DeviceContext3(),
                                                         idx, 1, binding.GetAddressOf());
                              });
}

template <SingleShaderStage Stage>
void BindGroupTracker::UnbindSamplers() {
    const auto slots = mSamplerSlots[Stage].MaxBoundSlots();
    if (slots == 0) {
        return;
    }

    static constexpr ID3D11SamplerState* kNullSamplers[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT] = {};

    SetSamplersImpl<Stage>(mCommandContext->GetD3D11DeviceContext3(), 0, slots, kNullSamplers);
}

void BindGroupTracker::CSSetUnorderedAccessView(uint32_t idx, ID3D11UnorderedAccessView* uav) {
    mMinUAVSlots[kCompute] = std::min(mMinUAVSlots[kCompute], idx);

    mCSUAVSlots.Bind(
        idx, std::move(uav), [this](size_t idx, const ComPtr<ID3D11UnorderedAccessView>& binding) {
            SetUnorderedAccessViewsImpl<kCompute>(mCommandContext->GetD3D11DeviceContext3(), idx, 1,
                                                  binding.GetAddressOf());
        });
}

void BindGroupTracker::OMSetUnorderedAccessViews(uint32_t idx,
                                                 uint32_t count,
                                                 ID3D11UnorderedAccessView* const* uavs) {
    mMinUAVSlots[kFragment] = std::min(mMinUAVSlots[kFragment], idx);
    mPSMaxUAVSlot = std::max(mPSMaxUAVSlot, idx + count);

    SetUnorderedAccessViewsImpl<kFragment>(mCommandContext->GetD3D11DeviceContext3(), idx, count,
                                           uavs);
}

template <SingleShaderStage Stage>
void BindGroupTracker::UnbindUnorderedAccessViews() {
    const auto start = mMinUAVSlots[Stage];
    uint32_t end;

    if constexpr (Stage == kFragment) {
        end = mPSMaxUAVSlot;
    } else if constexpr (Stage == kCompute) {
        end = mCSUAVSlots.MaxBoundSlots();
    } else {
        DAWN_UNREACHABLE();
        return;
    }

    if (start >= end) {
        return;
    }

    static constexpr ID3D11UnorderedAccessView* kNullUAVs[D3D11_1_UAV_SLOT_COUNT] = {};

    const auto count = end - start;

    SetUnorderedAccessViewsImpl<Stage>(mCommandContext->GetD3D11DeviceContext3(), start, count,
                                       kNullUAVs);
}

ResultOrError<BindGroupTracker::ConstantBufferBinding> BindGroupTracker::GetConstantBufferBinding(
    BindGroupBase* group,
    BindingIndex bindingIndex,
    const BufferBindingInfo& layout,
    const ityp::span<BindingIndex, uint32_t>& dynamicOffsets) {
    const auto& [bindingInfo, binding] =
        ExtractBufferBindingInfo(group, bindingIndex, layout, dynamicOffsets);

    DAWN_ASSERT(layout.type == wgpu::BufferBindingType::Uniform);

    ID3D11Buffer* d3d11Buffer;
    DAWN_TRY_ASSIGN(d3d11Buffer,
                    ToGPUUsableBuffer(binding.buffer)->GetD3D11ConstantBuffer(mCommandContext));
    // https://learn.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-vssetconstantbuffers1
    // Offset and size are measured in shader constants, which are 16 bytes
    // (4*32-bit components). And the offsets and counts must be multiples
    // of 16.
    // WebGPU's minUniformBufferOffsetAlignment is 256.
    DAWN_ASSERT(IsAligned(binding.offset, 256));
    UINT firstConstant = static_cast<UINT>(binding.offset / 16);
    UINT size = static_cast<UINT>(Align(binding.size, 16) / 16);
    UINT numConstants = Align(size, 16);
    DAWN_ASSERT(binding.offset + numConstants * 16 <= binding.buffer->GetAllocatedSize());

    return ConstantBufferBinding{d3d11Buffer, firstConstant, numConstants};
}

template <typename T>
ResultOrError<ComPtr<T>> BindGroupTracker::GetBufferD3DView(
    BindGroupBase* group,
    BindingIndex bindingIndex,
    const BufferBindingInfo& layout,
    const ityp::span<BindingIndex, uint32_t>& dynamicOffsets) {
    const auto& [bindingInfo, binding] =
        ExtractBufferBindingInfo(group, bindingIndex, layout, dynamicOffsets);

    if constexpr (std::is_same_v<T, ID3D11ShaderResourceView>) {
        DAWN_ASSERT(layout.type == wgpu::BufferBindingType::ReadOnlyStorage ||
                    layout.type == kInternalReadOnlyStorageBufferBinding);

        return ToGPUUsableBuffer(binding.buffer)
            ->UseAsSRV(mCommandContext, binding.offset, binding.size);
    } else if constexpr (std::is_same_v<T, ID3D11UnorderedAccessView>) {
        DAWN_ASSERT(layout.type == wgpu::BufferBindingType::Storage ||
                    layout.type == kInternalStorageBufferBinding);

        return ToGPUUsableBuffer(binding.buffer)
            ->UseAsUAV(mCommandContext, binding.offset, binding.size);
    } else {
        DAWN_UNREACHABLE();
        return ComPtr<T>();
    }
}

ResultOrError<ComPtr<ID3D11ShaderResourceView>> BindGroupTracker::GetTextureShaderResourceView(
    BindGroupBase* group,
    BindingIndex bindingIndex) {
    const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(bindingIndex);

    DAWN_ASSERT(std::holds_alternative<TextureBindingInfo>(bindingInfo.bindingLayout) ||
                std::holds_alternative<StorageTextureBindingInfo>(bindingInfo.bindingLayout));

    if (std::holds_alternative<StorageTextureBindingInfo>(bindingInfo.bindingLayout)) {
        DAWN_ASSERT(std::get<StorageTextureBindingInfo>(bindingInfo.bindingLayout).access ==
                    wgpu::StorageTextureAccess::ReadOnly);
    }

    TextureView* view = ToBackend(group->GetBindingAsTextureView(bindingIndex));
    ComPtr<ID3D11ShaderResourceView> srv;

    if (view->GetAspects() == Aspect::Stencil) [[unlikely]] {
        // For sampling from stencil, we have to use an internal mirror 'R8Uint' texture.
        DAWN_TRY_ASSIGN(srv, ToBackend(view->GetTexture())->GetStencilSRV(mCommandContext, view));
    } else {
        DAWN_TRY_ASSIGN(srv, view->GetOrCreateD3D11ShaderResourceView());
    }

    return srv;
}

ResultOrError<ComPtr<ID3D11UnorderedAccessView>> BindGroupTracker::GetTextureUnorderedAccessView(
    BindGroupBase* group,
    BindingIndex bindingIndex) {
    const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(bindingIndex);

    DAWN_ASSERT(std::holds_alternative<StorageTextureBindingInfo>(bindingInfo.bindingLayout));

    [[maybe_unused]] const auto& layout =
        std::get<StorageTextureBindingInfo>(bindingInfo.bindingLayout);

    DAWN_ASSERT(layout.access == wgpu::StorageTextureAccess::ReadWrite ||
                layout.access == wgpu::StorageTextureAccess::WriteOnly);

    TextureView* view = ToBackend(group->GetBindingAsTextureView(bindingIndex));
    ComPtr<ID3D11UnorderedAccessView> uav;

    DAWN_TRY_ASSIGN(uav, view->GetOrCreateD3D11UnorderedAccessView());

    return uav;
}

template <typename T>
ResultOrError<ComPtr<T>> BindGroupTracker::GetTextureD3DView(BindGroupBase* group,
                                                             BindingIndex bindingIndex) {
    if constexpr (std::is_same_v<T, ID3D11ShaderResourceView>) {
        return GetTextureShaderResourceView(group, bindingIndex);
    } else if constexpr (std::is_same_v<T, ID3D11UnorderedAccessView>) {
        return GetTextureUnorderedAccessView(group, bindingIndex);
    }

    DAWN_UNREACHABLE();
    return ComPtr<T>();
}

ID3D11SamplerState* BindGroupTracker::GetSamplerState(BindGroupBase* group,
                                                      BindingIndex bindingIndex) {
    const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(bindingIndex);
    DAWN_ASSERT(std::holds_alternative<SamplerBindingInfo>(bindingInfo.bindingLayout));

    Sampler* sampler = ToBackend(group->GetBindingAsSampler(bindingIndex));
    return sampler->GetD3D11SamplerState();
}

template <wgpu::ShaderStage kVisibleStage>
MaybeError BindGroupTracker::ApplyBindGroup(BindGroupIndex index) {
    constexpr wgpu::ShaderStage kVisibleFragment = wgpu::ShaderStage::Fragment & kVisibleStage;
    constexpr wgpu::ShaderStage kVisibleVertex = wgpu::ShaderStage::Vertex & kVisibleStage;
    constexpr wgpu::ShaderStage kVisibleCompute = wgpu::ShaderStage::Compute & kVisibleStage;

    BindGroupBase* group = mBindGroups[index];
    const ityp::span<BindingIndex, uint32_t>& dynamicOffsets = GetDynamicOffsets(index);
    const auto& indices = ToBackend(mPipelineLayout)->GetBindingTableIndexMap()[index];

    for (BindingIndex bindingIndex : Range(group->GetLayout()->GetBindingCount())) {
        const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(bindingIndex);
        const auto bindingVisibility = bindingInfo.visibility & kVisibleStage;

        uint32_t bindingSlotVS;
        uint32_t bindingSlotPS;
        uint32_t bindingSlotCS;
        if (bindingVisibility & kVisibleVertex) {
            bindingSlotVS = indices[bindingIndex][kVertex];
        }
        if (bindingVisibility & kVisibleFragment) {
            bindingSlotPS = indices[bindingIndex][kFragment];
        }
        if (bindingVisibility & kVisibleCompute) {
            bindingSlotCS = indices[bindingIndex][kCompute];
        }

        DAWN_TRY(MatchVariant(
            bindingInfo.bindingLayout,
            [&](const BufferBindingInfo& layout) -> MaybeError {
                switch (layout.type) {
                    case wgpu::BufferBindingType::Uniform: {
                        ConstantBufferBinding bufferBinding;
                        DAWN_TRY_ASSIGN(bufferBinding,
                                        this->GetConstantBufferBinding(group, bindingIndex, layout,
                                                                       dynamicOffsets));

                        auto d3d11Buffer = bufferBinding.buffer.Get();
                        if (bindingVisibility & kVisibleVertex) {
                            this->SetConstantBuffer<kVertex>(bindingSlotVS, d3d11Buffer,
                                                             bufferBinding.firstConstant,
                                                             bufferBinding.numConstants);
                        }
                        if (bindingVisibility & kVisibleFragment) {
                            this->SetConstantBuffer<kFragment>(bindingSlotPS, d3d11Buffer,
                                                               bufferBinding.firstConstant,
                                                               bufferBinding.numConstants);
                        }
                        if (bindingVisibility & kVisibleCompute) {
                            this->SetConstantBuffer<kCompute>(bindingSlotCS, d3d11Buffer,
                                                              bufferBinding.firstConstant,
                                                              bufferBinding.numConstants);
                        }
                        break;
                    }
                    case wgpu::BufferBindingType::Storage:
                    case kInternalStorageBufferBinding: {
                        // Skip fragment on purpose because render passes requires a single
                        // OMSetRenderTargetsAndUnorderedAccessViews call to set all UAVs.
                        // Delegate to RenderPassBindGroupTracker::Apply.
                        if (bindingVisibility & wgpu::ShaderStage::Compute) {
                            ComPtr<ID3D11UnorderedAccessView> d3d11UAV;
                            DAWN_TRY_ASSIGN(d3d11UAV,
                                            GetBufferD3DView<ID3D11UnorderedAccessView>(
                                                group, bindingIndex, layout, dynamicOffsets));
                            this->CSSetUnorderedAccessView(bindingSlotCS, d3d11UAV.Get());
                        }
                        break;
                    }
                    case wgpu::BufferBindingType::ReadOnlyStorage:
                    case kInternalReadOnlyStorageBufferBinding: {
                        ComPtr<ID3D11ShaderResourceView> d3d11SRV;
                        DAWN_TRY_ASSIGN(d3d11SRV, GetBufferD3DView<ID3D11ShaderResourceView>(
                                                      group, bindingIndex, layout, dynamicOffsets));
                        if (bindingVisibility & kVisibleVertex) {
                            this->SetShaderResource<kVertex>(bindingSlotVS, d3d11SRV.Get());
                        }
                        if (bindingVisibility & kVisibleFragment) {
                            this->SetShaderResource<kFragment>(bindingSlotPS, d3d11SRV.Get());
                        }
                        if (bindingVisibility & kVisibleCompute) {
                            this->SetShaderResource<kCompute>(bindingSlotCS, d3d11SRV.Get());
                        }
                        break;
                    }
                    case wgpu::BufferBindingType::BindingNotUsed:
                    case wgpu::BufferBindingType::Undefined:
                        DAWN_UNREACHABLE();
                }
                return {};
            },
            [&](const StaticSamplerBindingInfo&) -> MaybeError {
                // Static samplers are implemented in the frontend on
                // D3D11.
                DAWN_UNREACHABLE();
                return {};
            },
            [&](const SamplerBindingInfo&) -> MaybeError {
                ID3D11SamplerState* d3d11SamplerState = GetSamplerState(group, bindingIndex);
                if (bindingVisibility & kVisibleVertex) {
                    this->SetSampler<kVertex>(bindingSlotVS, d3d11SamplerState);
                }
                if (bindingVisibility & kVisibleFragment) {
                    this->SetSampler<kFragment>(bindingSlotPS, d3d11SamplerState);
                }
                if (bindingVisibility & kVisibleCompute) {
                    this->SetSampler<kCompute>(bindingSlotCS, d3d11SamplerState);
                }
                return {};
            },
            [&](const TextureBindingInfo&) -> MaybeError {
                ComPtr<ID3D11ShaderResourceView> srv;
                DAWN_TRY_ASSIGN(srv,
                                GetTextureD3DView<ID3D11ShaderResourceView>(group, bindingIndex));

                if (bindingVisibility & kVisibleVertex) {
                    this->SetShaderResource<kVertex>(bindingSlotVS, srv.Get());
                }
                if (bindingVisibility & kVisibleFragment) {
                    this->SetShaderResource<kFragment>(bindingSlotPS, srv.Get());
                }
                if (bindingVisibility & kVisibleCompute) {
                    this->SetShaderResource<kCompute>(bindingSlotCS, srv.Get());
                }
                return {};
            },
            [&](const StorageTextureBindingInfo& layout) -> MaybeError {
                switch (layout.access) {
                    case wgpu::StorageTextureAccess::WriteOnly:
                    case wgpu::StorageTextureAccess::ReadWrite: {
                        // Skip fragment on purpose because render passes requires a single
                        // OMSetRenderTargetsAndUnorderedAccessViews call to set all UAVs.
                        // Delegate to RenderPassBindGroupTracker::Apply.
                        if (bindingVisibility & kVisibleCompute) {
                            ComPtr<ID3D11UnorderedAccessView> d3d11UAV = nullptr;
                            DAWN_TRY_ASSIGN(d3d11UAV, GetTextureD3DView<ID3D11UnorderedAccessView>(
                                                          group, bindingIndex));
                            this->CSSetUnorderedAccessView(bindingSlotCS, d3d11UAV.Get());
                        }
                        break;
                    }
                    case wgpu::StorageTextureAccess::ReadOnly: {
                        ComPtr<ID3D11ShaderResourceView> d3d11SRV = nullptr;
                        DAWN_TRY_ASSIGN(d3d11SRV, GetTextureD3DView<ID3D11ShaderResourceView>(
                                                      group, bindingIndex));
                        if (bindingVisibility & kVisibleVertex) {
                            this->SetShaderResource<kVertex>(bindingSlotVS, d3d11SRV.Get());
                        }
                        if (bindingVisibility & kVisibleFragment) {
                            this->SetShaderResource<kFragment>(bindingSlotPS, d3d11SRV.Get());
                        }
                        if (bindingVisibility & kVisibleCompute) {
                            this->SetShaderResource<kCompute>(bindingSlotCS, d3d11SRV.Get());
                        }
                        break;
                    }
                    default:
                        DAWN_UNREACHABLE();
                }
                return {};
            },
            [&](const TexelBufferBindingInfo&) -> MaybeError {
                // D3D11 does not support texel buffers.
                // TODO(crbug/382544164): Prototype texel buffer feature
                DAWN_UNREACHABLE();
                return {};
            },
            [](const InputAttachmentBindingInfo&) -> MaybeError { DAWN_UNREACHABLE(); },
            [](const ExternalTextureBindingInfo&) -> MaybeError { DAWN_UNREACHABLE(); }));
    }
    return {};
}

ComputePassBindGroupTracker::ComputePassBindGroupTracker(
    const ScopedSwapStateCommandRecordingContext* commandContext)
    : BindGroupTracker(commandContext) {}

ComputePassBindGroupTracker::~ComputePassBindGroupTracker() = default;

void ComputePassBindGroupTracker::UnapplyComputeBindings(BindGroupIndex index) {
    const BindGroupLayoutInternalBase* groupLayout =
        mLastAppliedPipelineLayout->GetBindGroupLayout(index);
    const auto& indices = ToBackend(mLastAppliedPipelineLayout)->GetBindingTableIndexMap()[index];

    for (BindingIndex bindingIndex : Range(groupLayout->GetBindingCount())) {
        const BindingInfo& bindingInfo = groupLayout->GetBindingInfo(bindingIndex);
        const uint32_t bindingSlot = indices[bindingIndex][kCompute];
        if (!(bindingInfo.visibility & wgpu::ShaderStage::Compute)) {
            continue;
        }

        MatchVariant(
            bindingInfo.bindingLayout,
            [&](const BufferBindingInfo& layout) {
                switch (layout.type) {
                    case wgpu::BufferBindingType::Uniform: {
                        this->SetConstantBuffer<kCompute>(bindingSlot, nullptr, 0, 0);
                        break;
                    }
                    case wgpu::BufferBindingType::Storage:
                    case kInternalStorageBufferBinding: {
                        this->CSSetUnorderedAccessView(bindingSlot, nullptr);
                        break;
                    }
                    case wgpu::BufferBindingType::ReadOnlyStorage:
                    case kInternalReadOnlyStorageBufferBinding: {
                        this->SetShaderResource<kCompute>(bindingSlot, nullptr);
                        break;
                    }
                    case wgpu::BufferBindingType::BindingNotUsed:
                    case wgpu::BufferBindingType::Undefined:
                        DAWN_UNREACHABLE();
                }
            },
            [&](const StaticSamplerBindingInfo&) {
                // Static samplers are implemented in the frontend on
                // D3D11.
                DAWN_UNREACHABLE();
            },
            [&](const SamplerBindingInfo&) { this->SetSampler<kCompute>(bindingSlot, nullptr); },
            [&](const TextureBindingInfo&) {
                this->SetShaderResource<kCompute>(bindingSlot, nullptr);
            },
            [&](const StorageTextureBindingInfo& layout) {
                switch (layout.access) {
                    case wgpu::StorageTextureAccess::WriteOnly:
                    case wgpu::StorageTextureAccess::ReadWrite: {
                        this->CSSetUnorderedAccessView(bindingSlot, nullptr);
                        break;
                    }
                    case wgpu::StorageTextureAccess::ReadOnly: {
                        this->SetShaderResource<kCompute>(bindingSlot, nullptr);
                        break;
                    }
                    default:
                        DAWN_UNREACHABLE();
                }
            },
            [&](const TexelBufferBindingInfo&) {
                // D3D11 does not support texel buffers.
                // TODO(crbug/382544164): Prototype texel buffer feature
                DAWN_UNREACHABLE();
            },
            [](const InputAttachmentBindingInfo&) { DAWN_UNREACHABLE(); },
            [](const ExternalTextureBindingInfo&) { DAWN_UNREACHABLE(); });
    }
}

MaybeError ComputePassBindGroupTracker::Apply() {
    BeforeApply();

    BindGroupMask inheritedGroups =
        mPipelineLayout->InheritedGroupsMask(mLastAppliedPipelineLayout);
    BindGroupMask previousGroups = mLastAppliedPipelineLayout->GetBindGroupLayoutsMask();

    // To avoid UAV / SRV conflicts with bindings in previously bind groups, we unset the bind
    // groups that aren't reused by the current pipeline.
    // We also need to unset the inherited bind groups which are dirty as the group may have
    // both SRV and UAV, and the same resource may change its binding from UAV to SRV next
    // dispatch in the same group.
    //
    // Note: WebGPU API guarantees that resources are not used both as UAV and SRV in the same
    // render pass. So we don't need to do this inside render passes.
    BindGroupMask groupsToUnset = previousGroups & (~inheritedGroups | mDirtyBindGroups);
    for (BindGroupIndex index : groupsToUnset) {
        UnapplyComputeBindings(index);
    }

    for (BindGroupIndex index : mDirtyBindGroupsObjectChangedOrIsDynamic) {
        DAWN_TRY(ApplyBindGroup<wgpu::ShaderStage::Compute>(index));
    }

    AfterApply();

    return {};
}

RenderPassBindGroupTracker::RenderPassBindGroupTracker(
    const ScopedSwapStateCommandRecordingContext* commandContext,
    std::vector<ComPtr<ID3D11UnorderedAccessView>> pixelLocalStorageUAVs)
    : BindGroupTracker(commandContext), mPixelLocalStorageUAVs(std::move(pixelLocalStorageUAVs)) {}

RenderPassBindGroupTracker::~RenderPassBindGroupTracker() = default;

MaybeError RenderPassBindGroupTracker::Apply() {
    BeforeApply();

    if (!mDirtyBindGroupsObjectChangedOrIsDynamic.any() &&
        mLastAppliedPipelineLayout == mPipelineLayout) {
        AfterApply();
        return {};
    }

    // As D3d11 requires to bind all UAVs slots at the same time for pixel shaders, we record
    // all UAV slot assignments in the bind groups, and then bind them all together.
    const BindGroupMask uavBindGroups = ToBackend(mPipelineLayout)->GetUAVBindGroupLayoutsMask();
    const uint32_t plsSlotCount = ToBackend(mPipelineLayout)->GetPLSSlotCount();
    const uint32_t uavStartSlot = ToBackend(mPipelineLayout)->GetUAVStartIndex(kFragment);
    const uint32_t uavCount = ToBackend(mPipelineLayout)->GetUAVCount(kFragment);

    DAWN_ASSERT(uavCount >= plsSlotCount);
    const uint32_t usedUavCount = uavCount - plsSlotCount;

    absl::InlinedVector<ComPtr<ID3D11UnorderedAccessView>, 1> uavsInBindGroup(usedUavCount);

    for (BindGroupIndex index : uavBindGroups) {
        BindGroupBase* group = mBindGroups[index];
        const ityp::span<BindingIndex, uint32_t>& dynamicOffsets = GetDynamicOffsets(index);
        const auto& indices = ToBackend(mPipelineLayout)->GetBindingTableIndexMap()[index];

        // D3D11 uav slot allocated in reverse order.
        for (BindingIndex bindingIndex : Range(group->GetLayout()->GetBindingCount())) {
            const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(bindingIndex);

            // Skip if this binding isn't visible in the fragment shader.
            if (!(bindingInfo.visibility & wgpu::ShaderStage::Fragment)) {
                continue;
            }

            uint32_t pos = indices[bindingIndex][kFragment] - uavStartSlot;
            DAWN_TRY(MatchVariant(
                bindingInfo.bindingLayout,
                [&](const BufferBindingInfo& layout) -> MaybeError {
                    switch (layout.type) {
                        case wgpu::BufferBindingType::Storage:
                        case kInternalStorageBufferBinding: {
                            ComPtr<ID3D11UnorderedAccessView> d3d11UAV;
                            DAWN_TRY_ASSIGN(d3d11UAV,
                                            GetBufferD3DView<ID3D11UnorderedAccessView>(
                                                group, bindingIndex, layout, dynamicOffsets));
                            uavsInBindGroup[pos] = std::move(d3d11UAV);
                            break;
                        }
                        case wgpu::BufferBindingType::Uniform:
                        case wgpu::BufferBindingType::ReadOnlyStorage:
                        case kInternalReadOnlyStorageBufferBinding: {
                            break;
                        }
                        case wgpu::BufferBindingType::BindingNotUsed:
                        case wgpu::BufferBindingType::Undefined:
                            DAWN_UNREACHABLE();
                    }
                    return {};
                },
                [&](const StorageTextureBindingInfo& layout) -> MaybeError {
                    switch (layout.access) {
                        case wgpu::StorageTextureAccess::WriteOnly:
                        case wgpu::StorageTextureAccess::ReadWrite: {
                            ComPtr<ID3D11UnorderedAccessView> d3d11UAV;
                            DAWN_TRY_ASSIGN(d3d11UAV, GetTextureD3DView<ID3D11UnorderedAccessView>(
                                                          group, bindingIndex));
                            uavsInBindGroup[pos] = std::move(d3d11UAV);
                            break;
                        }
                        case wgpu::StorageTextureAccess::ReadOnly:
                            break;
                        default:
                            DAWN_UNREACHABLE();
                            break;
                    }
                    return {};
                },
                [](const TextureBindingInfo&) -> MaybeError { return {}; },
                [](const SamplerBindingInfo&) -> MaybeError { return {}; },
                [](const StaticSamplerBindingInfo&) -> MaybeError {
                    // Static samplers are implemented in the frontend on
                    // D3D11.
                    DAWN_UNREACHABLE();
                    return {};
                },
                [](const TexelBufferBindingInfo&) -> MaybeError {
                    // D3D11 does not support texel buffers.
                    // TODO(crbug/382544164): Prototype texel buffer feature
                    DAWN_UNREACHABLE();
                    return {};
                },
                [](const InputAttachmentBindingInfo&) -> MaybeError { DAWN_UNREACHABLE(); },
                [](const ExternalTextureBindingInfo&) -> MaybeError { DAWN_UNREACHABLE(); }));
        }
    }

    const uint32_t plsCount = mPixelLocalStorageUAVs.size();
    const uint32_t plsAndUavCount = plsCount + usedUavCount;
    std::vector<ID3D11UnorderedAccessView*> plsAndUavs;
    plsAndUavs.reserve(plsAndUavCount);

    for (auto& uav : uavsInBindGroup) {
        plsAndUavs.push_back(uav.Get());
    }

    for (auto& uav : mPixelLocalStorageUAVs) {
        plsAndUavs.push_back(uav.Get());
    }

    if (!plsAndUavs.empty()) {
        this->OMSetUnorderedAccessViews(uavStartSlot, plsAndUavCount, plsAndUavs.data());
    }

    for (BindGroupIndex index : mDirtyBindGroupsObjectChangedOrIsDynamic) {
        DAWN_TRY(ApplyBindGroup<wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment>(index));
    }

    AfterApply();

    return {};
}

}  // namespace dawn::native::d3d11
