// Copyright 2017 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.

#include "dawn_native/BindGroup.h"

#include "common/Assert.h"
#include "common/Math.h"
#include "common/ityp_bitset.h"
#include "dawn_native/BindGroupLayout.h"
#include "dawn_native/Buffer.h"
#include "dawn_native/ChainUtils_autogen.h"
#include "dawn_native/Device.h"
#include "dawn_native/ExternalTexture.h"
#include "dawn_native/ObjectBase.h"
#include "dawn_native/ObjectType_autogen.h"
#include "dawn_native/Sampler.h"
#include "dawn_native/Texture.h"

namespace dawn::native {

    namespace {

        // Helper functions to perform binding-type specific validation

        MaybeError ValidateBufferBinding(const DeviceBase* device,
                                         const BindGroupEntry& entry,
                                         const BindingInfo& bindingInfo) {
            DAWN_INVALID_IF(entry.buffer == nullptr, "Binding entry buffer not set.");

            DAWN_INVALID_IF(entry.sampler != nullptr || entry.textureView != nullptr,
                            "Expected only buffer to be set for binding entry.");

            DAWN_INVALID_IF(entry.nextInChain != nullptr, "nextInChain must be nullptr.");

            DAWN_TRY(device->ValidateObject(entry.buffer));

            ASSERT(bindingInfo.bindingType == BindingInfoType::Buffer);

            wgpu::BufferUsage requiredUsage;
            uint64_t maxBindingSize;
            uint64_t requiredBindingAlignment;
            switch (bindingInfo.buffer.type) {
                case wgpu::BufferBindingType::Uniform:
                    requiredUsage = wgpu::BufferUsage::Uniform;
                    maxBindingSize = device->GetLimits().v1.maxUniformBufferBindingSize;
                    requiredBindingAlignment =
                        device->GetLimits().v1.minUniformBufferOffsetAlignment;
                    break;
                case wgpu::BufferBindingType::Storage:
                case wgpu::BufferBindingType::ReadOnlyStorage:
                    requiredUsage = wgpu::BufferUsage::Storage;
                    maxBindingSize = device->GetLimits().v1.maxStorageBufferBindingSize;
                    requiredBindingAlignment =
                        device->GetLimits().v1.minStorageBufferOffsetAlignment;
                    break;
                case kInternalStorageBufferBinding:
                    requiredUsage = kInternalStorageBuffer;
                    maxBindingSize = device->GetLimits().v1.maxStorageBufferBindingSize;
                    requiredBindingAlignment =
                        device->GetLimits().v1.minStorageBufferOffsetAlignment;
                    break;
                case wgpu::BufferBindingType::Undefined:
                    UNREACHABLE();
            }

            uint64_t bufferSize = entry.buffer->GetSize();

            // Handle wgpu::WholeSize, avoiding overflows.
            DAWN_INVALID_IF(entry.offset > bufferSize,
                            "Binding offset (%u) is larger than the size (%u) of %s.", entry.offset,
                            bufferSize, entry.buffer);

            uint64_t bindingSize =
                (entry.size == wgpu::kWholeSize) ? bufferSize - entry.offset : entry.size;

            DAWN_INVALID_IF(bindingSize > bufferSize,
                            "Binding size (%u) is larger than the size (%u) of %s.", bindingSize,
                            bufferSize, entry.buffer);

            DAWN_INVALID_IF(bindingSize == 0, "Binding size is zero");

            // Note that no overflow can happen because we already checked that
            // bufferSize >= bindingSize
            DAWN_INVALID_IF(
                entry.offset > bufferSize - bindingSize,
                "Binding range (offset: %u, size: %u) doesn't fit in the size (%u) of %s.",
                entry.offset, bufferSize, bindingSize, entry.buffer);

            DAWN_INVALID_IF(!IsAligned(entry.offset, requiredBindingAlignment),
                            "Offset (%u) does not satisfy the minimum %s alignment (%u).",
                            entry.offset, bindingInfo.buffer.type, requiredBindingAlignment);

            DAWN_INVALID_IF(!(entry.buffer->GetUsage() & requiredUsage),
                            "Binding usage (%s) of %s doesn't match expected usage (%s).",
                            entry.buffer->GetUsage(), entry.buffer, requiredUsage);

            DAWN_INVALID_IF(bindingSize < bindingInfo.buffer.minBindingSize,
                            "Binding size (%u) is smaller than the minimum binding size (%u).",
                            bindingSize, bindingInfo.buffer.minBindingSize);

            DAWN_INVALID_IF(bindingSize > maxBindingSize,
                            "Binding size (%u) is larger than the maximum binding size (%u).",
                            bindingSize, maxBindingSize);

            return {};
        }

        MaybeError ValidateTextureBinding(DeviceBase* device,
                                          const BindGroupEntry& entry,
                                          const BindingInfo& bindingInfo) {
            DAWN_INVALID_IF(entry.textureView == nullptr, "Binding entry textureView not set.");

            DAWN_INVALID_IF(entry.sampler != nullptr || entry.buffer != nullptr,
                            "Expected only textureView to be set for binding entry.");

            DAWN_INVALID_IF(entry.nextInChain != nullptr, "nextInChain must be nullptr.");

            DAWN_TRY(device->ValidateObject(entry.textureView));

            TextureViewBase* view = entry.textureView;

            Aspect aspect = view->GetAspects();
            // TODO(dawn:563): Format Aspects
            DAWN_INVALID_IF(!HasOneBit(aspect), "Multiple aspects selected in %s.", view);

            TextureBase* texture = view->GetTexture();
            switch (bindingInfo.bindingType) {
                case BindingInfoType::Texture: {
                    SampleTypeBit supportedTypes =
                        texture->GetFormat().GetAspectInfo(aspect).supportedSampleTypes;
                    SampleTypeBit requiredType =
                        SampleTypeToSampleTypeBit(bindingInfo.texture.sampleType);

                    DAWN_INVALID_IF(
                        !(texture->GetUsage() & wgpu::TextureUsage::TextureBinding),
                        "Usage (%s) of %s doesn't include TextureUsage::TextureBinding.",
                        texture->GetUsage(), texture);

                    DAWN_INVALID_IF(
                        texture->IsMultisampledTexture() != bindingInfo.texture.multisampled,
                        "Sample count (%u) of %s doesn't match expectation (multisampled: %d).",
                        texture->GetSampleCount(), texture, bindingInfo.texture.multisampled);

                    // TODO(dawn:563): Improve error message.
                    DAWN_INVALID_IF((supportedTypes & requiredType) == 0,
                                    "Texture component type usage mismatch.");

                    DAWN_INVALID_IF(
                        entry.textureView->GetDimension() != bindingInfo.texture.viewDimension,
                        "Dimension (%s) of %s doesn't match the expected dimension (%s).",
                        entry.textureView->GetDimension(), entry.textureView,
                        bindingInfo.texture.viewDimension);
                    break;
                }
                case BindingInfoType::StorageTexture: {
                    DAWN_INVALID_IF(
                        !(texture->GetUsage() & wgpu::TextureUsage::StorageBinding),
                        "Usage (%s) of %s doesn't include TextureUsage::StorageBinding.",
                        texture->GetUsage(), texture);

                    ASSERT(!texture->IsMultisampledTexture());

                    DAWN_INVALID_IF(
                        texture->GetFormat().format != bindingInfo.storageTexture.format,
                        "Format (%s) of %s expected to be (%s).", texture->GetFormat().format,
                        texture, bindingInfo.storageTexture.format);

                    DAWN_INVALID_IF(
                        entry.textureView->GetDimension() !=
                            bindingInfo.storageTexture.viewDimension,
                        "Dimension (%s) of %s doesn't match the expected dimension (%s).",
                        entry.textureView->GetDimension(), entry.textureView,
                        bindingInfo.storageTexture.viewDimension);

                    DAWN_INVALID_IF(entry.textureView->GetLevelCount() != 1,
                                    "mipLevelCount (%u) of %s expected to be 1.",
                                    entry.textureView->GetLevelCount(), entry.textureView);
                    break;
                }
                default:
                    UNREACHABLE();
                    break;
            }

            return {};
        }

        MaybeError ValidateSamplerBinding(const DeviceBase* device,
                                          const BindGroupEntry& entry,
                                          const BindingInfo& bindingInfo) {
            DAWN_INVALID_IF(entry.sampler == nullptr, "Binding entry sampler not set.");

            DAWN_INVALID_IF(entry.textureView != nullptr || entry.buffer != nullptr,
                            "Expected only sampler to be set for binding entry.");

            DAWN_INVALID_IF(entry.nextInChain != nullptr, "nextInChain must be nullptr.");

            DAWN_TRY(device->ValidateObject(entry.sampler));

            ASSERT(bindingInfo.bindingType == BindingInfoType::Sampler);

            switch (bindingInfo.sampler.type) {
                case wgpu::SamplerBindingType::NonFiltering:
                    DAWN_INVALID_IF(
                        entry.sampler->IsFiltering(),
                        "Filtering sampler %s is incompatible with non-filtering sampler "
                        "binding.",
                        entry.sampler);
                    [[fallthrough]];
                case wgpu::SamplerBindingType::Filtering:
                    DAWN_INVALID_IF(
                        entry.sampler->IsComparison(),
                        "Comparison sampler %s is incompatible with non-comparison sampler "
                        "binding.",
                        entry.sampler);
                    break;
                case wgpu::SamplerBindingType::Comparison:
                    DAWN_INVALID_IF(
                        !entry.sampler->IsComparison(),
                        "Non-comparison sampler %s is imcompatible with comparison sampler "
                        "binding.",
                        entry.sampler);
                    break;
                default:
                    UNREACHABLE();
                    break;
            }

            return {};
        }

        MaybeError ValidateExternalTextureBinding(const DeviceBase* device,
                                                  const BindGroupEntry& entry,
                                                  const BindingInfo& bindingInfo) {
            const ExternalTextureBindingEntry* externalTextureBindingEntry = nullptr;
            FindInChain(entry.nextInChain, &externalTextureBindingEntry);

            DAWN_INVALID_IF(externalTextureBindingEntry == nullptr,
                            "Binding entry external texture not set.");

            DAWN_INVALID_IF(
                entry.sampler != nullptr || entry.textureView != nullptr || entry.buffer != nullptr,
                "Expected only external texture to be set for binding entry.");

            DAWN_TRY(ValidateSingleSType(externalTextureBindingEntry->nextInChain,
                                         wgpu::SType::ExternalTextureBindingEntry));

            DAWN_TRY(device->ValidateObject(externalTextureBindingEntry->externalTexture));

            return {};
        }

    }  // anonymous namespace

    MaybeError ValidateBindGroupDescriptor(DeviceBase* device,
                                           const BindGroupDescriptor* descriptor) {
        DAWN_INVALID_IF(descriptor->nextInChain != nullptr, "nextInChain must be nullptr.");

        DAWN_TRY(device->ValidateObject(descriptor->layout));

        DAWN_INVALID_IF(
            BindingIndex(descriptor->entryCount) != descriptor->layout->GetBindingCount(),
            "Number of entries (%u) did not match the number of entries (%u) specified in %s",
            descriptor->entryCount, static_cast<uint32_t>(descriptor->layout->GetBindingCount()),
            descriptor->layout);

        const BindGroupLayoutBase::BindingMap& bindingMap = descriptor->layout->GetBindingMap();
        ASSERT(bindingMap.size() <= kMaxBindingsPerPipelineLayout);

        ityp::bitset<BindingIndex, kMaxBindingsPerPipelineLayout> bindingsSet;
        for (uint32_t i = 0; i < descriptor->entryCount; ++i) {
            const BindGroupEntry& entry = descriptor->entries[i];

            const auto& it = bindingMap.find(BindingNumber(entry.binding));
            DAWN_INVALID_IF(it == bindingMap.end(),
                            "In entries[%u], binding index %u not present in the bind group layout",
                            i, entry.binding);

            BindingIndex bindingIndex = it->second;
            ASSERT(bindingIndex < descriptor->layout->GetBindingCount());

            DAWN_INVALID_IF(bindingsSet[bindingIndex],
                            "In entries[%u], binding index %u already used by a previous entry", i,
                            entry.binding);

            bindingsSet.set(bindingIndex);

            const BindingInfo& bindingInfo = descriptor->layout->GetBindingInfo(bindingIndex);

            // Perform binding-type specific validation.
            switch (bindingInfo.bindingType) {
                case BindingInfoType::Buffer:
                    DAWN_TRY_CONTEXT(ValidateBufferBinding(device, entry, bindingInfo),
                                     "validating entries[%u] as a Buffer", i);
                    break;
                case BindingInfoType::Texture:
                case BindingInfoType::StorageTexture:
                    DAWN_TRY_CONTEXT(ValidateTextureBinding(device, entry, bindingInfo),
                                     "validating entries[%u] as a Texture", i);
                    break;
                case BindingInfoType::Sampler:
                    DAWN_TRY_CONTEXT(ValidateSamplerBinding(device, entry, bindingInfo),
                                     "validating entries[%u] as a Sampler", i);
                    break;
                case BindingInfoType::ExternalTexture:
                    DAWN_TRY_CONTEXT(ValidateExternalTextureBinding(device, entry, bindingInfo),
                                     "validating entries[%u] as an ExternalTexture", i);
                    break;
            }
        }

        // This should always be true because
        //  - numBindings has to match between the bind group and its layout.
        //  - Each binding must be set at most once
        //
        // We don't validate the equality because it wouldn't be possible to cover it with a test.
        ASSERT(bindingsSet.count() == bindingMap.size());

        return {};
    }  // anonymous namespace

    // BindGroup

    BindGroupBase::BindGroupBase(DeviceBase* device,
                                 const BindGroupDescriptor* descriptor,
                                 void* bindingDataStart)
        : ApiObjectBase(device, descriptor->label),
          mLayout(descriptor->layout),
          mBindingData(mLayout->ComputeBindingDataPointers(bindingDataStart)) {
        for (BindingIndex i{0}; i < mLayout->GetBindingCount(); ++i) {
            // TODO(enga): Shouldn't be needed when bindings are tightly packed.
            // This is to fill Ref<ObjectBase> holes with nullptrs.
            new (&mBindingData.bindings[i]) Ref<ObjectBase>();
        }

        for (uint32_t i = 0; i < descriptor->entryCount; ++i) {
            const BindGroupEntry& entry = descriptor->entries[i];

            BindingIndex bindingIndex =
                descriptor->layout->GetBindingIndex(BindingNumber(entry.binding));
            ASSERT(bindingIndex < mLayout->GetBindingCount());

            // Only a single binding type should be set, so once we found it we can skip to the
            // next loop iteration.

            if (entry.buffer != nullptr) {
                ASSERT(mBindingData.bindings[bindingIndex] == nullptr);
                mBindingData.bindings[bindingIndex] = entry.buffer;
                mBindingData.bufferData[bindingIndex].offset = entry.offset;
                uint64_t bufferSize = (entry.size == wgpu::kWholeSize)
                                          ? entry.buffer->GetSize() - entry.offset
                                          : entry.size;
                mBindingData.bufferData[bindingIndex].size = bufferSize;
                continue;
            }

            if (entry.textureView != nullptr) {
                ASSERT(mBindingData.bindings[bindingIndex] == nullptr);
                mBindingData.bindings[bindingIndex] = entry.textureView;
                continue;
            }

            if (entry.sampler != nullptr) {
                ASSERT(mBindingData.bindings[bindingIndex] == nullptr);
                mBindingData.bindings[bindingIndex] = entry.sampler;
                continue;
            }

            const ExternalTextureBindingEntry* externalTextureBindingEntry = nullptr;
            FindInChain(entry.nextInChain, &externalTextureBindingEntry);
            if (externalTextureBindingEntry != nullptr) {
                ASSERT(mBindingData.bindings[bindingIndex] == nullptr);
                mBindingData.bindings[bindingIndex] = externalTextureBindingEntry->externalTexture;
                continue;
            }
        }

        uint32_t packedIdx = 0;
        for (BindingIndex bindingIndex{0}; bindingIndex < descriptor->layout->GetBufferCount();
             ++bindingIndex) {
            if (descriptor->layout->GetBindingInfo(bindingIndex).buffer.minBindingSize == 0) {
                mBindingData.unverifiedBufferSizes[packedIdx] =
                    mBindingData.bufferData[bindingIndex].size;
                ++packedIdx;
            }
        }

        TrackInDevice();
    }

    BindGroupBase::BindGroupBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
        TrackInDevice();
    }

    BindGroupBase::~BindGroupBase() = default;

    void BindGroupBase::DestroyImpl() {
        if (mLayout != nullptr) {
            ASSERT(!IsError());
            for (BindingIndex i{0}; i < mLayout->GetBindingCount(); ++i) {
                mBindingData.bindings[i].~Ref<ObjectBase>();
            }
        }
    }

    void BindGroupBase::DeleteThis() {
        // Add another ref to the layout so that if this is the last ref, the layout
        // is destroyed after the bind group. The bind group is slab-allocated inside
        // memory owned by the layout (except for the null backend).
        Ref<BindGroupLayoutBase> layout = mLayout;
        ApiObjectBase::DeleteThis();
    }

    BindGroupBase::BindGroupBase(DeviceBase* device, ObjectBase::ErrorTag tag)
        : ApiObjectBase(device, tag), mBindingData() {
    }

    // static
    BindGroupBase* BindGroupBase::MakeError(DeviceBase* device) {
        return new BindGroupBase(device, ObjectBase::kError);
    }

    ObjectType BindGroupBase::GetType() const {
        return ObjectType::BindGroup;
    }

    BindGroupLayoutBase* BindGroupBase::GetLayout() {
        ASSERT(!IsError());
        return mLayout.Get();
    }

    const BindGroupLayoutBase* BindGroupBase::GetLayout() const {
        ASSERT(!IsError());
        return mLayout.Get();
    }

    const ityp::span<uint32_t, uint64_t>& BindGroupBase::GetUnverifiedBufferSizes() const {
        ASSERT(!IsError());
        return mBindingData.unverifiedBufferSizes;
    }

    BufferBinding BindGroupBase::GetBindingAsBufferBinding(BindingIndex bindingIndex) {
        ASSERT(!IsError());
        ASSERT(bindingIndex < mLayout->GetBindingCount());
        ASSERT(mLayout->GetBindingInfo(bindingIndex).bindingType == BindingInfoType::Buffer);
        BufferBase* buffer = static_cast<BufferBase*>(mBindingData.bindings[bindingIndex].Get());
        return {buffer, mBindingData.bufferData[bindingIndex].offset,
                mBindingData.bufferData[bindingIndex].size};
    }

    SamplerBase* BindGroupBase::GetBindingAsSampler(BindingIndex bindingIndex) const {
        ASSERT(!IsError());
        ASSERT(bindingIndex < mLayout->GetBindingCount());
        ASSERT(mLayout->GetBindingInfo(bindingIndex).bindingType == BindingInfoType::Sampler);
        return static_cast<SamplerBase*>(mBindingData.bindings[bindingIndex].Get());
    }

    TextureViewBase* BindGroupBase::GetBindingAsTextureView(BindingIndex bindingIndex) {
        ASSERT(!IsError());
        ASSERT(bindingIndex < mLayout->GetBindingCount());
        ASSERT(mLayout->GetBindingInfo(bindingIndex).bindingType == BindingInfoType::Texture ||
               mLayout->GetBindingInfo(bindingIndex).bindingType ==
                   BindingInfoType::StorageTexture);
        return static_cast<TextureViewBase*>(mBindingData.bindings[bindingIndex].Get());
    }

    ExternalTextureBase* BindGroupBase::GetBindingAsExternalTexture(BindingIndex bindingIndex) {
        ASSERT(!IsError());
        ASSERT(bindingIndex < mLayout->GetBindingCount());
        ASSERT(mLayout->GetBindingInfo(bindingIndex).bindingType ==
               BindingInfoType::ExternalTexture);
        return static_cast<ExternalTextureBase*>(mBindingData.bindings[bindingIndex].Get());
    }

}  // namespace dawn::native
