// 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 "dawn_native/BindGroupLayout.h"
#include "dawn_native/Buffer.h"
#include "dawn_native/Device.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,
                                         wgpu::BufferUsage requiredUsage) {
            if (entry.buffer == nullptr || entry.sampler != nullptr ||
                entry.textureView != nullptr) {
                return DAWN_VALIDATION_ERROR("expected buffer binding");
            }
            DAWN_TRY(device->ValidateObject(entry.buffer));

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

            // Handle wgpu::WholeSize, avoiding overflows.
            if (entry.offset > bufferSize) {
                return DAWN_VALIDATION_ERROR("Buffer binding doesn't fit in the buffer");
            }
            uint64_t bindingSize =
                (entry.size == wgpu::kWholeSize) ? bufferSize - entry.offset : entry.size;

            if (bindingSize > bufferSize) {
                return DAWN_VALIDATION_ERROR("Buffer binding size larger than the buffer");
            }

            if (bindingSize == 0) {
                return DAWN_VALIDATION_ERROR("Buffer binding size cannot be zero.");
            }

            // Note that no overflow can happen because we already checked that
            // bufferSize >= bindingSize
            if (entry.offset > bufferSize - bindingSize) {
                return DAWN_VALIDATION_ERROR("Buffer binding doesn't fit in the buffer");
            }

            if (!IsAligned(entry.offset, 256)) {
                return DAWN_VALIDATION_ERROR(
                    "Buffer offset for bind group needs to be 256-byte aligned");
            }

            if (!(entry.buffer->GetUsage() & requiredUsage)) {
                return DAWN_VALIDATION_ERROR("buffer binding usage mismatch");
            }

            return {};
        }

        MaybeError ValidateTextureBinding(const DeviceBase* device,
                                          const BindGroupEntry& entry,
                                          wgpu::TextureUsage requiredUsage,
                                          const BindingInfo& bindingInfo) {
            if (entry.textureView == nullptr || entry.sampler != nullptr ||
                entry.buffer != nullptr) {
                return DAWN_VALIDATION_ERROR("expected texture binding");
            }
            DAWN_TRY(device->ValidateObject(entry.textureView));

            TextureBase* texture = entry.textureView->GetTexture();

            if (!(texture->GetUsage() & requiredUsage)) {
                return DAWN_VALIDATION_ERROR("texture binding usage mismatch");
            }

            if (texture->IsMultisampledTexture() != bindingInfo.multisampled) {
                return DAWN_VALIDATION_ERROR("texture multisampling mismatch");
            }

            switch (requiredUsage) {
                case wgpu::TextureUsage::Sampled: {
                    if (!texture->GetFormat().HasComponentType(bindingInfo.textureComponentType)) {
                        return DAWN_VALIDATION_ERROR("texture component type usage mismatch");
                    }
                    break;
                }
                case wgpu::TextureUsage::Storage: {
                    if (texture->GetFormat().format != bindingInfo.storageTextureFormat) {
                        return DAWN_VALIDATION_ERROR("storage texture format mismatch");
                    }
                    break;
                }
                default:
                    UNREACHABLE();
                    break;
            }

            if (entry.textureView->GetDimension() != bindingInfo.viewDimension) {
                return DAWN_VALIDATION_ERROR("texture view dimension mismatch");
            }

            return {};
        }

        MaybeError ValidateSamplerBinding(const DeviceBase* device,
                                          const BindGroupEntry& entry,
                                          wgpu::BindingType bindingType) {
            if (entry.sampler == nullptr || entry.textureView != nullptr ||
                entry.buffer != nullptr) {
                return DAWN_VALIDATION_ERROR("expected sampler binding");
            }
            DAWN_TRY(device->ValidateObject(entry.sampler));

            switch (bindingType) {
                case wgpu::BindingType::Sampler:
                    if (entry.sampler->HasCompareFunction()) {
                        return DAWN_VALIDATION_ERROR("Did not expect comparison sampler");
                    }
                    break;
                case wgpu::BindingType::ComparisonSampler:
                    if (!entry.sampler->HasCompareFunction()) {
                        return DAWN_VALIDATION_ERROR("Expected comparison sampler");
                    }
                    break;
                default:
                    UNREACHABLE();
            }

            return {};
        }

    }  // anonymous namespace

    MaybeError ValidateBindGroupDescriptor(DeviceBase* device,
                                           const BindGroupDescriptor* descriptor) {
        if (descriptor->nextInChain != nullptr) {
            return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
        }

        DAWN_TRY(device->ValidateObject(descriptor->layout));
        if (descriptor->entryCount != descriptor->layout->GetBindingCount()) {
            return DAWN_VALIDATION_ERROR("numBindings mismatch");
        }

        const BindGroupLayoutBase::BindingMap& bindingMap = descriptor->layout->GetBindingMap();

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

            const auto& it = bindingMap.find(BindingNumber(entry.binding));
            if (it == bindingMap.end()) {
                return DAWN_VALIDATION_ERROR("setting non-existent binding");
            }
            BindingIndex bindingIndex = it->second;
            ASSERT(bindingIndex < descriptor->layout->GetBindingCount());

            if (bindingsSet[bindingIndex]) {
                return DAWN_VALIDATION_ERROR("binding set twice");
            }
            bindingsSet.set(bindingIndex);

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

            // Perform binding-type specific validation.
            switch (bindingInfo.type) {
                case wgpu::BindingType::UniformBuffer:
                    DAWN_TRY(ValidateBufferBinding(device, entry, wgpu::BufferUsage::Uniform));
                    break;
                case wgpu::BindingType::StorageBuffer:
                case wgpu::BindingType::ReadonlyStorageBuffer:
                    DAWN_TRY(ValidateBufferBinding(device, entry, wgpu::BufferUsage::Storage));
                    break;
                case wgpu::BindingType::SampledTexture:
                    DAWN_TRY(ValidateTextureBinding(device, entry, wgpu::TextureUsage::Sampled,
                                                    bindingInfo));
                    break;
                case wgpu::BindingType::Sampler:
                case wgpu::BindingType::ComparisonSampler:
                    DAWN_TRY(ValidateSamplerBinding(device, entry, bindingInfo.type));
                    break;
                // TODO(jiawei.shao@intel.com): support creating bind group with read-only and
                // write-only storage textures.
                case wgpu::BindingType::ReadonlyStorageTexture:
                case wgpu::BindingType::WriteonlyStorageTexture:
                    DAWN_TRY(ValidateTextureBinding(device, entry, wgpu::TextureUsage::Storage,
                                                    bindingInfo));
                    break;
                case wgpu::BindingType::StorageTexture:
                    UNREACHABLE();
                    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)
        : ObjectBase(device),
          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].Get() == 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].Get() == nullptr);
                mBindingData.bindings[bindingIndex] = entry.textureView;
                continue;
            }

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

    BindGroupBase::~BindGroupBase() {
        if (mLayout) {
            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;
        RefCounted::DeleteThis();
    }

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

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

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

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

    BufferBinding BindGroupBase::GetBindingAsBufferBinding(BindingIndex bindingIndex) {
        ASSERT(!IsError());
        ASSERT(bindingIndex < mLayout->GetBindingCount());
        ASSERT(mLayout->GetBindingInfo(bindingIndex).type == wgpu::BindingType::UniformBuffer ||
               mLayout->GetBindingInfo(bindingIndex).type == wgpu::BindingType::StorageBuffer ||
               mLayout->GetBindingInfo(bindingIndex).type ==
                   wgpu::BindingType::ReadonlyStorageBuffer);
        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).type == wgpu::BindingType::Sampler ||
               mLayout->GetBindingInfo(bindingIndex).type == wgpu::BindingType::ComparisonSampler);
        return static_cast<SamplerBase*>(mBindingData.bindings[bindingIndex].Get());
    }

    TextureViewBase* BindGroupBase::GetBindingAsTextureView(BindingIndex bindingIndex) {
        ASSERT(!IsError());
        ASSERT(bindingIndex < mLayout->GetBindingCount());
        ASSERT(mLayout->GetBindingInfo(bindingIndex).type == wgpu::BindingType::SampledTexture ||
               mLayout->GetBindingInfo(bindingIndex).type ==
                   wgpu::BindingType::ReadonlyStorageTexture ||
               mLayout->GetBindingInfo(bindingIndex).type ==
                   wgpu::BindingType::WriteonlyStorageTexture);
        return static_cast<TextureViewBase*>(mBindingData.bindings[bindingIndex].Get());
    }

}  // namespace dawn_native
