// Copyright 2025 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/vulkan/ResourceTableVk.h"

#include <vector>

#include "dawn/common/Enumerator.h"
#include "dawn/native/DynamicArrayState.h"
#include "dawn/native/DynamicUploader.h"
#include "dawn/native/vulkan/DescriptorSetAllocator.h"
#include "dawn/native/vulkan/DeviceVk.h"
#include "dawn/native/vulkan/TextureVk.h"
#include "dawn/native/vulkan/UtilsVulkan.h"
#include "dawn/native/vulkan/VulkanError.h"

namespace dawn::native::vulkan {

// static
ResultOrError<Ref<ResourceTable>> ResourceTable::Create(Device* device,
                                                        const ResourceTableDescriptor* descriptor) {
    Ref<ResourceTable> table = AcquireRef(new ResourceTable(device, descriptor));
    DAWN_TRY(table->Initialize());
    return table;
}

// static
ResultOrError<VkDescriptorSetLayout> ResourceTable::MakeDescriptorSetLayout(Device* device) {
    // A resource table is a bindgroup made of two entries:
    //
    //  - Binding 0: the metadata storage buffer.
    //  - Binding 1: the variable length, partially bound, update-after-bind array of sampled
    //  textures/samplers.
    std::array<VkDescriptorSetLayoutBinding, 2> bindings = {
        {{
             .binding = 0,
             .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
             .descriptorCount = 1,
             .stageFlags = VulkanShaderStages(kAllStages),
             .pImmutableSamplers = nullptr,
         },
         {
             .binding = 1,
             .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
             .descriptorCount = device->GetLimits().resourceTableLimits.maxResourceTableSize +
                                kReservedDynamicBindingArrayEntries,
             .stageFlags = VulkanShaderStages(kAllStages),
             .pImmutableSamplers = nullptr,
         }}};
    std::array<VkDescriptorBindingFlags, 2> flags = {
        0,  //
        VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT |
            VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT |
            VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT |
            VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT};

    VkDescriptorSetLayoutBindingFlagsCreateInfo flagCreateInfo{
        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
        .pNext = nullptr,
        .bindingCount = flags.size(),
        .pBindingFlags = flags.data(),
    };
    VkDescriptorSetLayoutCreateInfo createInfo{
        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
        .pNext = &flagCreateInfo,
        .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT,
        .bindingCount = bindings.size(),
        .pBindings = bindings.data(),
    };

    VkDescriptorSetLayout dsLayout = VK_NULL_HANDLE;
    DAWN_TRY(CheckVkSuccess(device->fn.CreateDescriptorSetLayout(device->GetVkDevice(), &createInfo,
                                                                 nullptr, &*dsLayout),
                            "CreateDescriptorSetLayout"));
    return dsLayout;
}

ResourceTable::~ResourceTable() = default;

MaybeError ResourceTable::Initialize() {
    DAWN_TRY(ResourceTableBase::InitializeBase());

    Device* device = ToBackend(GetDevice());

    // Allocate the VkDescriptorSet used for this resource table.
    mDSAllocator = DescriptorSetAllocatorDynamicArray::Create(device);

    // The only non-dynamic binding (using the terminology of DescriptorSetAllocatorDynamicArray) is
    // the metadata buffer.
    absl::flat_hash_map<VkDescriptorType, uint32_t> descriptorCountPerType;
    descriptorCountPerType[VK_DESCRIPTOR_TYPE_STORAGE_BUFFER] = 1;

    DAWN_TRY_ASSIGN(
        mAllocation,
        mDSAllocator->Allocate(device->GetResourceTableLayout(), descriptorCountPerType,
                               VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
                               uint32_t(GetDynamicArrayState()->GetSizeWithDefaultBindings())));

    // Only write the metadata buffer in the VkDescriptorSet initially, all the other bindings will
    // be written as needed when they are inserted in the ResourceTable.
    Buffer* metadataBuffer = ToBackend(GetDynamicArrayState()->GetMetadataBuffer());
    VkDescriptorBufferInfo bufferInfo = {
        .buffer = metadataBuffer->GetHandle(),
        .offset = 0,
        .range = metadataBuffer->GetSize(),
    };
    VkWriteDescriptorSet write = {
        .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
        .pNext = nullptr,
        .dstSet = mAllocation.set,
        .dstBinding = 0,
        .dstArrayElement = 0,
        .descriptorCount = 1,
        .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
        .pImageInfo = nullptr,
        .pBufferInfo = &bufferInfo,
        .pTexelBufferView = nullptr,
    };
    device->fn.UpdateDescriptorSets(device->GetVkDevice(), 1, &write, 0, nullptr);

    return {};
}

// Apply updates to resources or to the metadata buffers that are pending.
MaybeError ResourceTable::ApplyPendingUpdates(CommandRecordingContext* recordingContext) {
    DynamicArrayState::BindingUpdates updates =
        GetDynamicArrayState()->AcquireDirtyBindingUpdates();

    if (!updates.metadataUpdates.empty()) {
        DAWN_TRY(UpdateMetadataBuffer(recordingContext, updates.metadataUpdates));
    }
    if (!updates.resourceUpdates.empty()) {
        UpdateResourceBindings(updates.resourceUpdates);
    }

    return {};
}

MaybeError ResourceTable::UpdateMetadataBuffer(
    CommandRecordingContext* recordingContext,
    const std::vector<DynamicArrayState::MetadataUpdate>& updates) {
    // Updates a dynamic array metadata buffer by scheduling a copy for each u32 that needs to be
    // updated.
    // TODO(https://crbug.com/435317394): If we had a way to use Dawn reentrantly now, we could use
    // a compute shader to dispatch the updates instead of individual copies for each update, and
    // move that logic in the frontend to share it between backends. (also a single dispatch could
    // update multiple metadata buffers potentially).
    Device* device = ToBackend(GetDevice());

    // Allocate enough space for all the data to modify and schedule the copies.
    return device->GetDynamicUploader()->WithUploadReservation(
        sizeof(uint32_t) * updates.size(), kCopyBufferToBufferOffsetAlignment,
        [&](UploadReservation reservation) -> MaybeError {
            uint32_t* stagedData = static_cast<uint32_t*>(reservation.mappedPointer);

            // The metadata buffer will be copied to.
            Buffer* metadataBuffer = ToBackend(GetDynamicArrayState()->GetMetadataBuffer());
            DAWN_ASSERT(metadataBuffer->IsInitialized());
            metadataBuffer->TransitionUsageNow(recordingContext, wgpu::BufferUsage::CopyDst);

            // Prepare the copies.
            std::vector<VkBufferCopy> copies(updates.size());
            for (auto [i, update] : Enumerate(updates)) {
                stagedData[i] = update.data;

                VkBufferCopy copy{
                    .srcOffset = reservation.offsetInBuffer + i * sizeof(uint32_t),
                    .dstOffset = update.offset,
                    .size = sizeof(uint32_t),
                };
                copies[i] = copy;
            }

            // Enqueue the copy commands all at once.
            device->fn.CmdCopyBuffer(recordingContext->commandBuffer,
                                     ToBackend(reservation.buffer)->GetHandle(),
                                     metadataBuffer->GetHandle(), copies.size(), copies.data());

            // Transition the buffer back to be used as storage as that's how it will be used for
            // shader-side validation.
            metadataBuffer->TransitionUsageNow(recordingContext, kReadOnlyStorageBuffer,
                                               kAllStages);

            return {};
        });
}

void ResourceTable::UpdateResourceBindings(
    const std::vector<DynamicArrayState::ResourceUpdate>& updates) {
    std::vector<VkDescriptorImageInfo> imageWrites;
    std::vector<uint32_t> arrayElements;

    for (DynamicArrayState::ResourceUpdate update : updates) {
        // TODO(https://issues.chromium.org/435317394): Support samplers updates.
        // TODO(https://issues.chromium.org/435317394): Support buffer, texel buffers and storage
        // textures.

        VkImageView handle = ToBackend(update.textureView)->GetHandle();
        if (handle == nullptr) {
            continue;
        }

        VkDescriptorImageInfo imageWrite = {
            .sampler = VkSampler{},
            .imageView = handle,
            .imageLayout = VulkanImageLayout(update.textureView->GetFormat(),
                                             wgpu::TextureUsage::TextureBinding),
        };
        imageWrites.push_back(imageWrite);
        arrayElements.push_back(uint32_t(update.slot));
    }

    std::vector<VkWriteDescriptorSet> writes;
    for (size_t i = 0; i < imageWrites.size(); i++) {
        VkWriteDescriptorSet write{
            .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
            .pNext = nullptr,
            .dstSet = mAllocation.set,
            .dstBinding = 1,
            .dstArrayElement = arrayElements[i],
            .descriptorCount = 1,
            .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
            .pImageInfo = &imageWrites[i],
            .pBufferInfo = nullptr,
            .pTexelBufferView = nullptr,
        };
        writes.push_back(write);
    }

    Device* device = ToBackend(GetDevice());
    device->fn.UpdateDescriptorSets(device->GetVkDevice(), writes.size(), writes.data(), 0,
                                    nullptr);
}

VkDescriptorSet ResourceTable::GetHandle() const {
    return mAllocation.set;
}

void ResourceTable::DestroyImpl() {
    mDSAllocator->Deallocate(&mAllocation);
    mDSAllocator = nullptr;

    ResourceTableBase::DestroyImpl();
}

void ResourceTable::SetLabelImpl() {
    SetDebugName(ToBackend(GetDevice()), mAllocation.set, "Dawn_ResourceTable", GetLabel());
}

}  // namespace dawn::native::vulkan
