// Copyright 2018 The NXT 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.

#include "backend/vulkan/BindGroupLayoutVk.h"

#include "backend/vulkan/VulkanBackend.h"
#include "common/BitSetIterator.h"

namespace backend { namespace vulkan {

    namespace {

        VkShaderStageFlags VulkanShaderStageFlags(nxt::ShaderStageBit stages) {
            VkShaderStageFlags flags = 0;

            if (stages & nxt::ShaderStageBit::Vertex) {
                flags |= VK_SHADER_STAGE_VERTEX_BIT;
            }
            if (stages & nxt::ShaderStageBit::Fragment) {
                flags |= VK_SHADER_STAGE_FRAGMENT_BIT;
            }
            if (stages & nxt::ShaderStageBit::Compute) {
                flags |= VK_SHADER_STAGE_COMPUTE_BIT;
            }

            return flags;
        }

    }  // anonymous namespace

    VkDescriptorType VulkanDescriptorType(nxt::BindingType type) {
        switch (type) {
            case nxt::BindingType::UniformBuffer:
                return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
            case nxt::BindingType::Sampler:
                return VK_DESCRIPTOR_TYPE_SAMPLER;
            case nxt::BindingType::SampledTexture:
                return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
            case nxt::BindingType::StorageBuffer:
                return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
            default:
                UNREACHABLE();
        }
    }

    BindGroupLayout::BindGroupLayout(BindGroupLayoutBuilder* builder)
        : BindGroupLayoutBase(builder) {
        const auto& info = GetBindingInfo();

        // Compute the bindings that will be chained in the DescriptorSetLayout create info. We add
        // one entry per binding set. This might be optimized by computing continuous ranges of
        // bindings of the same type.
        uint32_t numBindings = 0;
        std::array<VkDescriptorSetLayoutBinding, kMaxBindingsPerGroup> bindings;
        for (uint32_t bindingIndex : IterateBitSet(info.mask)) {
            auto& binding = bindings[numBindings];
            binding.binding = bindingIndex;
            binding.descriptorType = VulkanDescriptorType(info.types[bindingIndex]);
            binding.descriptorCount = 1;
            binding.stageFlags = VulkanShaderStageFlags(info.visibilities[bindingIndex]);
            binding.pImmutableSamplers = nullptr;

            numBindings++;
        }

        VkDescriptorSetLayoutCreateInfo createInfo;
        createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
        createInfo.pNext = nullptr;
        createInfo.flags = 0;
        createInfo.bindingCount = numBindings;
        createInfo.pBindings = bindings.data();

        Device* device = ToBackend(GetDevice());
        if (device->fn.CreateDescriptorSetLayout(device->GetVkDevice(), &createInfo, nullptr,
                                                 &mHandle) != VK_SUCCESS) {
            ASSERT(false);
        }
    }

    BindGroupLayout::~BindGroupLayout() {
        // DescriptorSetLayout aren't used by execution on the GPU and can be deleted at any time,
        // so we destroy mHandle immediately instead of using the FencedDeleter
        if (mHandle != VK_NULL_HANDLE) {
            Device* device = ToBackend(GetDevice());
            device->fn.DestroyDescriptorSetLayout(device->GetVkDevice(), mHandle, nullptr);
            mHandle = VK_NULL_HANDLE;
        }
    }

    VkDescriptorSetLayout BindGroupLayout::GetHandle() const {
        return mHandle;
    }

    BindGroupLayout::PoolSizeSpec BindGroupLayout::ComputePoolSizes(uint32_t* numPoolSizes) const {
        uint32_t numSizes = 0;
        PoolSizeSpec result{};

        // Defines an array and indices into it that will contain for each sampler type at which
        // position it is in the PoolSizeSpec, or -1 if it isn't present yet.
        enum DescriptorType {
            UNIFORM_BUFFER,
            SAMPLER,
            SAMPLED_IMAGE,
            STORAGE_BUFFER,
            MAX_TYPE,
        };
        static_assert(MAX_TYPE == kMaxPoolSizesNeeded, "");
        auto ToDescriptorType = [](nxt::BindingType type) -> DescriptorType {
            switch (type) {
                case nxt::BindingType::UniformBuffer:
                    return UNIFORM_BUFFER;
                case nxt::BindingType::Sampler:
                    return SAMPLER;
                case nxt::BindingType::SampledTexture:
                    return SAMPLED_IMAGE;
                case nxt::BindingType::StorageBuffer:
                    return STORAGE_BUFFER;
                default:
                    UNREACHABLE();
            }
        };

        std::array<int, MAX_TYPE> descriptorTypeIndex;
        descriptorTypeIndex.fill(-1);

        const auto& info = GetBindingInfo();
        for (uint32_t bindingIndex : IterateBitSet(info.mask)) {
            DescriptorType type = ToDescriptorType(info.types[bindingIndex]);

            if (descriptorTypeIndex[type] == -1) {
                descriptorTypeIndex[type] = numSizes;
                result[numSizes].type = VulkanDescriptorType(info.types[bindingIndex]);
                result[numSizes].descriptorCount = 1;
                numSizes++;
            } else {
                result[descriptorTypeIndex[type]].descriptorCount++;
            }
        }

        *numPoolSizes = numSizes;
        return result;
    }
}}  // namespace backend::vulkan
