// Copyright 2017 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/d3d12/BindGroupLayoutD3D12.h"

#include <utility>

#include "dawn/common/MatchVariant.h"
#include "dawn/native/d3d12/DeviceD3D12.h"
#include "dawn/native/d3d12/SamplerD3D12.h"
#include "dawn/native/d3d12/SamplerHeapCacheD3D12.h"
#include "dawn/native/d3d12/StagingDescriptorAllocatorD3D12.h"
#include "dawn/native/d3d12/UtilsD3D12.h"

namespace dawn::native::d3d12 {
namespace {
D3D12_DESCRIPTOR_RANGE_TYPE WGPUBindingInfoToDescriptorRangeType(const BindingInfo& bindingInfo) {
    return MatchVariant(
        bindingInfo.bindingLayout,
        [](const BufferBindingInfo& layout) -> D3D12_DESCRIPTOR_RANGE_TYPE {
            switch (layout.type) {
                case wgpu::BufferBindingType::Uniform:
                    return D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
                case wgpu::BufferBindingType::Storage:
                case kInternalStorageBufferBinding:
                    return D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
                case wgpu::BufferBindingType::ReadOnlyStorage:
                case kInternalReadOnlyStorageBufferBinding:
                    return D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
                case wgpu::BufferBindingType::BindingNotUsed:
                case wgpu::BufferBindingType::Undefined:
                default:
                    DAWN_UNREACHABLE();
            }
        },
        [](const StaticSamplerBindingInfo&) -> D3D12_DESCRIPTOR_RANGE_TYPE {
            return D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
        },
        [](const SamplerBindingInfo&) -> D3D12_DESCRIPTOR_RANGE_TYPE {
            return D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
        },
        [](const TextureBindingInfo&) -> D3D12_DESCRIPTOR_RANGE_TYPE {
            return D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
        },
        [](const StorageTextureBindingInfo& layout) -> D3D12_DESCRIPTOR_RANGE_TYPE {
            switch (layout.access) {
                case wgpu::StorageTextureAccess::WriteOnly:
                case wgpu::StorageTextureAccess::ReadWrite:
                    return D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
                case wgpu::StorageTextureAccess::ReadOnly:
                    return D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
                case wgpu::StorageTextureAccess::BindingNotUsed:
                case wgpu::StorageTextureAccess::Undefined:
                default:
                    DAWN_UNREACHABLE();
            }
        },
        [](const TexelBufferBindingInfo&) -> D3D12_DESCRIPTOR_RANGE_TYPE {
            // D3D12 does not support texel buffers.
            // TODO(crbug/382544164): Prototype texel buffer feature
            DAWN_UNREACHABLE();
        },
        [](const InputAttachmentBindingInfo&) -> D3D12_DESCRIPTOR_RANGE_TYPE {
            DAWN_UNREACHABLE();
        },
        [](const ExternalTextureBindingInfo&) -> D3D12_DESCRIPTOR_RANGE_TYPE {
            DAWN_UNREACHABLE();
        });
}
}  // anonymous namespace

// static
Ref<BindGroupLayout> BindGroupLayout::Create(
    Device* device,
    const UnpackedPtr<BindGroupLayoutDescriptor>& descriptor) {
    return AcquireRef(new BindGroupLayout(device, descriptor));
}

BindGroupLayout::BindGroupLayout(Device* device,
                                 const UnpackedPtr<BindGroupLayoutDescriptor>& descriptor)
    : BindGroupLayoutInternalBase(device, descriptor),
      mDescriptorHeapOffsets(GetBindingCount()),
      mShaderRegisters(GetBindingCount()),
      mCbvUavSrvDescriptorCount(0),
      mSamplerDescriptorCount(0),
      mViewSizeIncrement(0),
      mBindGroupAllocator(MakeFrontendBindGroupAllocator<BindGroup>(4096)) {
    for (BindingIndex bindingIndex{0}; bindingIndex < GetBindingCount(); ++bindingIndex) {
        const BindingInfo& bindingInfo = GetBindingInfo(bindingIndex);

        D3D12_DESCRIPTOR_RANGE_TYPE descriptorRangeType =
            WGPUBindingInfoToDescriptorRangeType(bindingInfo);
        mShaderRegisters[bindingIndex] = uint32_t(bindingIndex);

        // Static samplers aren't stored in the descriptor heap. Handle them separately.
        if (std::holds_alternative<StaticSamplerBindingInfo>(bindingInfo.bindingLayout)) {
            const StaticSamplerBindingInfo& staticSamplerBindingInfo =
                std::get<StaticSamplerBindingInfo>(bindingInfo.bindingLayout);

            Sampler* sampler = ToBackend(staticSamplerBindingInfo.sampler.Get());

            const D3D12_SAMPLER_DESC desc = sampler->GetSamplerDescriptor();
            D3D12_STATIC_SAMPLER_DESC staticSamplerDesc = {};
            staticSamplerDesc.ShaderRegister = GetShaderRegister(bindingIndex);
            staticSamplerDesc.RegisterSpace = kRegisterSpacePlaceholder;
            staticSamplerDesc.ShaderVisibility = ShaderVisibilityType(bindingInfo.visibility);
            staticSamplerDesc.AddressU = desc.AddressU;
            staticSamplerDesc.AddressV = desc.AddressV;
            staticSamplerDesc.AddressW = desc.AddressW;
            staticSamplerDesc.Filter = desc.Filter;
            staticSamplerDesc.MinLOD = desc.MinLOD;
            staticSamplerDesc.MaxLOD = desc.MaxLOD;
            staticSamplerDesc.MipLODBias = desc.MipLODBias;
            staticSamplerDesc.MaxAnisotropy = desc.MaxAnisotropy;
            staticSamplerDesc.ComparisonFunc = desc.ComparisonFunc;

            mStaticSamplers.push_back(staticSamplerDesc);

            continue;
        }

        // For dynamic uniform buffers, Dawn uses root descriptors in the D3D12 backend. So there is
        // no need to allocate the descriptor from the descriptor heap or create descriptor ranges.
        if (bindingIndex < GetDynamicBufferCount() && !IsStorageBufferBinding(bindingIndex)) {
            continue;
        }

        mDescriptorHeapOffsets[bindingIndex] =
            descriptorRangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER
                ? mSamplerDescriptorCount++
                : mCbvUavSrvDescriptorCount++;

        D3D12_DESCRIPTOR_RANGE1 range;
        range.RangeType = descriptorRangeType;
        range.NumDescriptors = 1;
        range.BaseShaderRegister = GetShaderRegister(bindingIndex);
        range.RegisterSpace = kRegisterSpacePlaceholder;
        range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;

        // In Dawn we always use the descriptors as static ones, which means the descriptors in a
        // descriptor heap pointed to by a root descriptor table have been initialized by the time
        // the descriptor table is set on a command list (during recording), and the descriptors
        // cannot be changed until the command list has finished executing for the last time, so we
        // don't need to set DESCRIPTORS_VOLATILE for any binding types.
        range.Flags = MatchVariant(
            bindingInfo.bindingLayout,
            [](const StaticSamplerBindingInfo&) -> D3D12_DESCRIPTOR_RANGE_FLAGS {
                // Static samplers should already be handled. This should never be reached.
                DAWN_UNREACHABLE();
                return D3D12_DESCRIPTOR_RANGE_FLAG_NONE;
            },
            [](const SamplerBindingInfo&) -> D3D12_DESCRIPTOR_RANGE_FLAGS {
                // Sampler descriptor ranges don't support DATA_* flags at all since samplers do not
                // point to data.
                return D3D12_DESCRIPTOR_RANGE_FLAG_NONE;
            },
            [&](const BufferBindingInfo&) -> D3D12_DESCRIPTOR_RANGE_FLAGS {
                // In Dawn it's allowed to do state transitions on the buffers or textures after
                // binding them on the current command list, which indicates a change to its data
                // (or possibly resource metadata), so we cannot bind them as DATA_STATIC. We cannot
                // bind them as DATA_STATIC_WHILE_SET_AT_EXECUTE either because it is required to be
                // rebound to the command list before the next (this) Draw/Dispatch call, while
                // currently we may not rebind these resources if the current bind group is not
                // changed.
                if (GetDevice()->IsRobustnessEnabled()) {
                    return D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS |
                           D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE;
                }
                return D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE;
            },
            [](const TextureBindingInfo&) -> D3D12_DESCRIPTOR_RANGE_FLAGS {
                return D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE;
            },
            [](const StorageTextureBindingInfo&) -> D3D12_DESCRIPTOR_RANGE_FLAGS {
                return D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE;
            },
            [](const TexelBufferBindingInfo&) -> D3D12_DESCRIPTOR_RANGE_FLAGS {
                // D3D12 does not support texel buffers.
                // TODO(crbug/382544164): Prototype texel buffer feature
                DAWN_UNREACHABLE();
            },
            [](const InputAttachmentBindingInfo&) -> D3D12_DESCRIPTOR_RANGE_FLAGS {
                DAWN_UNREACHABLE();
            },
            [](const ExternalTextureBindingInfo&) -> D3D12_DESCRIPTOR_RANGE_FLAGS {
                DAWN_UNREACHABLE();
            });

        std::vector<D3D12_DESCRIPTOR_RANGE1>& descriptorRanges =
            descriptorRangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER ? mSamplerDescriptorRanges
                                                                       : mCbvUavSrvDescriptorRanges;

        // Try to join this range with the previous one, if the current range is a continuation
        // of the previous. This is possible because the binding infos in the base type are
        // sorted.
        if (!descriptorRanges.empty()) {
            D3D12_DESCRIPTOR_RANGE1& previous = descriptorRanges.back();
            if (previous.RangeType == range.RangeType && previous.Flags == range.Flags &&
                previous.BaseShaderRegister + previous.NumDescriptors == range.BaseShaderRegister) {
                previous.NumDescriptors += range.NumDescriptors;
                continue;
            }
        }

        descriptorRanges.push_back(range);
    }
    if (mCbvUavSrvDescriptorCount > 0) {
        auto* viewAllocator = device->GetViewStagingDescriptorAllocator(mCbvUavSrvDescriptorCount);
        mViewSizeIncrement = (*viewAllocator)->GetSizeIncrement();
    }
}

ResultOrError<Ref<BindGroup>> BindGroupLayout::AllocateBindGroup(
    Device* device,
    const UnpackedPtr<BindGroupDescriptor>& descriptor) {
    CPUDescriptorHeapAllocation viewAllocation;
    if (GetCbvUavSrvDescriptorCount() > 0) {
        auto* viewAllocator =
            device->GetViewStagingDescriptorAllocator(GetCbvUavSrvDescriptorCount());
        DAWN_ASSERT(viewAllocator != nullptr);
        DAWN_TRY((*viewAllocator).Use([&](auto viewAllocator) -> MaybeError {
            DAWN_TRY_ASSIGN(viewAllocation, viewAllocator->AllocateCPUDescriptors());
            return {};
        }));
    }

    Ref<BindGroup> bindGroup =
        AcquireRef<BindGroup>(mBindGroupAllocator->Allocate(device, descriptor, viewAllocation));

    // The bindgroup must be initialized before getting a sampler heap cache entry because we need
    // to look at the contents of the bind group to deduplicate the sampler heap allocation.
    DAWN_TRY(bindGroup->Initialize(descriptor));

    if (GetSamplerDescriptorCount() > 0) {
        Ref<SamplerHeapCacheEntry> samplerHeapCacheEntry;
        DAWN_TRY_ASSIGN(samplerHeapCacheEntry,
                        device->GetSamplerHeapCache()->GetOrCreate(bindGroup.Get()));
        bindGroup->SetSamplerAllocationEntry(std::move(samplerHeapCacheEntry));
    }

    return bindGroup;
}

void BindGroupLayout::DeallocateBindGroup(BindGroup* bindGroup) {
    mBindGroupAllocator->Deallocate(bindGroup);
}

void BindGroupLayout::DeallocateDescriptor(CPUDescriptorHeapAllocation* viewAllocation) {
    if (viewAllocation->IsValid()) {
        Device* device = ToBackend(GetDevice());
        auto* viewAllocator =
            device->GetViewStagingDescriptorAllocator(GetCbvUavSrvDescriptorCount());
        (*viewAllocator)->Deallocate(viewAllocation);
    }
}

void BindGroupLayout::ReduceMemoryUsage() {
    mBindGroupAllocator->DeleteEmptySlabs();
}

ityp::span<BindingIndex, const uint32_t> BindGroupLayout::GetDescriptorHeapOffsets() const {
    return {mDescriptorHeapOffsets.data(), mDescriptorHeapOffsets.size()};
}

uint32_t BindGroupLayout::GetShaderRegister(BindingIndex bindingIndex) const {
    return mShaderRegisters[bindingIndex];
}

uint32_t BindGroupLayout::GetCbvUavSrvDescriptorCount() const {
    return mCbvUavSrvDescriptorCount;
}

uint32_t BindGroupLayout::GetSamplerDescriptorCount() const {
    return mSamplerDescriptorCount;
}

uint32_t BindGroupLayout::GetViewSizeIncrement() const {
    return mViewSizeIncrement;
}

const std::vector<D3D12_DESCRIPTOR_RANGE1>& BindGroupLayout::GetCbvUavSrvDescriptorRanges() const {
    return mCbvUavSrvDescriptorRanges;
}

const std::vector<D3D12_DESCRIPTOR_RANGE1>& BindGroupLayout::GetSamplerDescriptorRanges() const {
    return mSamplerDescriptorRanges;
}

const std::vector<D3D12_STATIC_SAMPLER_DESC>& BindGroupLayout::GetStaticSamplers() const {
    return mStaticSamplers;
}

}  // namespace dawn::native::d3d12
