// Copyright 2019 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/metal/UtilsMetal.h"
#include "dawn_native/CommandBuffer.h"
#include "dawn_native/Pipeline.h"
#include "dawn_native/ShaderModule.h"

#include "common/Assert.h"

namespace dawn_native::metal {

    MTLCompareFunction ToMetalCompareFunction(wgpu::CompareFunction compareFunction) {
        switch (compareFunction) {
            case wgpu::CompareFunction::Never:
                return MTLCompareFunctionNever;
            case wgpu::CompareFunction::Less:
                return MTLCompareFunctionLess;
            case wgpu::CompareFunction::LessEqual:
                return MTLCompareFunctionLessEqual;
            case wgpu::CompareFunction::Greater:
                return MTLCompareFunctionGreater;
            case wgpu::CompareFunction::GreaterEqual:
                return MTLCompareFunctionGreaterEqual;
            case wgpu::CompareFunction::NotEqual:
                return MTLCompareFunctionNotEqual;
            case wgpu::CompareFunction::Equal:
                return MTLCompareFunctionEqual;
            case wgpu::CompareFunction::Always:
                return MTLCompareFunctionAlways;

            case wgpu::CompareFunction::Undefined:
                UNREACHABLE();
        }
    }

    TextureBufferCopySplit ComputeTextureBufferCopySplit(const Texture* texture,
                                                         uint32_t mipLevel,
                                                         Origin3D origin,
                                                         Extent3D copyExtent,
                                                         uint64_t bufferSize,
                                                         uint64_t bufferOffset,
                                                         uint32_t bytesPerRow,
                                                         uint32_t rowsPerImage,
                                                         Aspect aspect) {
        TextureBufferCopySplit copy;
        const Format textureFormat = texture->GetFormat();
        const TexelBlockInfo& blockInfo = textureFormat.GetAspectInfo(aspect).block;

        // When copying textures from/to an unpacked buffer, the Metal validation layer doesn't
        // compute the correct range when checking if the buffer is big enough to contain the
        // data for the whole copy. Instead of looking at the position of the last texel in the
        // buffer, it computes the volume of the 3D box with bytesPerRow * (rowsPerImage /
        // format.blockHeight) * copySize.depthOrArrayLayers. For example considering the pixel
        // buffer below where in memory, each row data (D) of the texture is followed by some
        // padding data (P):
        //     |DDDDDDD|PP|
        //     |DDDDDDD|PP|
        //     |DDDDDDD|PP|
        //     |DDDDDDD|PP|
        //     |DDDDDDA|PP|
        // The last pixel read will be A, but the driver will think it is the whole last padding
        // row, causing it to generate an error when the pixel buffer is just big enough.

        // We work around this limitation by detecting when Metal would complain and copy the
        // last image and row separately using tight sourceBytesPerRow or sourceBytesPerImage.
        uint32_t bytesPerImage = bytesPerRow * rowsPerImage;

        // Metal validation layer requires that if the texture's pixel format is a compressed
        // format, the sourceSize must be a multiple of the pixel format's block size or be
        // clamped to the edge of the texture if the block extends outside the bounds of a
        // texture.
        const Extent3D clampedCopyExtent =
            texture->ClampToMipLevelVirtualSize(mipLevel, origin, copyExtent);

        ASSERT(texture->GetDimension() != wgpu::TextureDimension::e1D);

        // Check whether buffer size is big enough.
        bool needWorkaround =
            bufferSize - bufferOffset < bytesPerImage * copyExtent.depthOrArrayLayers;
        if (!needWorkaround) {
            copy.count = 1;
            copy.copies[0].bufferOffset = bufferOffset;
            copy.copies[0].bytesPerRow = bytesPerRow;
            copy.copies[0].bytesPerImage = bytesPerImage;
            copy.copies[0].textureOrigin = origin;
            copy.copies[0].copyExtent = {clampedCopyExtent.width, clampedCopyExtent.height,
                                         copyExtent.depthOrArrayLayers};
            return copy;
        }

        uint64_t currentOffset = bufferOffset;

        // Doing all the copy except the last image.
        if (copyExtent.depthOrArrayLayers > 1) {
            copy.copies[copy.count].bufferOffset = currentOffset;
            copy.copies[copy.count].bytesPerRow = bytesPerRow;
            copy.copies[copy.count].bytesPerImage = bytesPerImage;
            copy.copies[copy.count].textureOrigin = origin;
            copy.copies[copy.count].copyExtent = {clampedCopyExtent.width, clampedCopyExtent.height,
                                                  copyExtent.depthOrArrayLayers - 1};

            ++copy.count;

            // Update offset to copy to the last image.
            currentOffset += (copyExtent.depthOrArrayLayers - 1) * bytesPerImage;
        }

        // Doing all the copy in last image except the last row.
        uint32_t copyBlockRowCount = copyExtent.height / blockInfo.height;
        if (copyBlockRowCount > 1) {
            copy.copies[copy.count].bufferOffset = currentOffset;
            copy.copies[copy.count].bytesPerRow = bytesPerRow;
            copy.copies[copy.count].bytesPerImage = bytesPerRow * (copyBlockRowCount - 1);
            copy.copies[copy.count].textureOrigin = {origin.x, origin.y,
                                                     origin.z + copyExtent.depthOrArrayLayers - 1};

            ASSERT(copyExtent.height - blockInfo.height <
                   texture->GetMipLevelVirtualSize(mipLevel).height);
            copy.copies[copy.count].copyExtent = {clampedCopyExtent.width,
                                                  copyExtent.height - blockInfo.height, 1};

            ++copy.count;

            // Update offset to copy to the last row.
            currentOffset += (copyBlockRowCount - 1) * bytesPerRow;
        }

        // Doing the last row copy with the exact number of bytes in last row.
        // Workaround this issue in a way just like the copy to a 1D texture.
        uint32_t lastRowDataSize = (copyExtent.width / blockInfo.width) * blockInfo.byteSize;
        uint32_t lastRowCopyExtentHeight =
            blockInfo.height + clampedCopyExtent.height - copyExtent.height;
        ASSERT(lastRowCopyExtentHeight <= blockInfo.height);

        copy.copies[copy.count].bufferOffset = currentOffset;
        copy.copies[copy.count].bytesPerRow = lastRowDataSize;
        copy.copies[copy.count].bytesPerImage = lastRowDataSize;
        copy.copies[copy.count].textureOrigin = {origin.x,
                                                 origin.y + copyExtent.height - blockInfo.height,
                                                 origin.z + copyExtent.depthOrArrayLayers - 1};
        copy.copies[copy.count].copyExtent = {clampedCopyExtent.width, lastRowCopyExtentHeight, 1};
        ++copy.count;

        return copy;
    }

    void EnsureDestinationTextureInitialized(CommandRecordingContext* commandContext,
                                             Texture* texture,
                                             const TextureCopy& dst,
                                             const Extent3D& size) {
        ASSERT(texture == dst.texture.Get());
        SubresourceRange range = GetSubresourcesAffectedByCopy(dst, size);
        if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), size, dst.mipLevel)) {
            texture->SetIsSubresourceContentInitialized(true, range);
        } else {
            texture->EnsureSubresourceContentInitialized(commandContext, range);
        }
    }

    MTLBlitOption ComputeMTLBlitOption(const Format& format, Aspect aspect) {
        ASSERT(HasOneBit(aspect));
        ASSERT(format.aspects & aspect);

        if (IsSubset(Aspect::Depth | Aspect::Stencil, format.aspects)) {
            // We only provide a blit option if the format has both depth and stencil.
            // It is invalid to provide a blit option otherwise.
            switch (aspect) {
                case Aspect::Depth:
                    return MTLBlitOptionDepthFromDepthStencil;
                case Aspect::Stencil:
                    return MTLBlitOptionStencilFromDepthStencil;
                default:
                    UNREACHABLE();
            }
        }
        return MTLBlitOptionNone;
    }

    MaybeError CreateMTLFunction(const ProgrammableStage& programmableStage,
                                 SingleShaderStage singleShaderStage,
                                 PipelineLayout* pipelineLayout,
                                 ShaderModule::MetalFunctionData* functionData,
                                 uint32_t sampleMask,
                                 const RenderPipeline* renderPipeline) {
        ShaderModule* shaderModule = ToBackend(programmableStage.module.Get());
        const char* shaderEntryPoint = programmableStage.entryPoint.c_str();
        const auto& entryPointMetadata = programmableStage.module->GetEntryPoint(shaderEntryPoint);
        if (entryPointMetadata.overridableConstants.size() == 0) {
            DAWN_TRY(shaderModule->CreateFunction(shaderEntryPoint, singleShaderStage,
                                                  pipelineLayout, functionData, nil, sampleMask,
                                                  renderPipeline));
            return {};
        }

        if (@available(macOS 10.12, *)) {
            // MTLFunctionConstantValues can only be created within the if available branch
            NSRef<MTLFunctionConstantValues> constantValues =
                AcquireNSRef([MTLFunctionConstantValues new]);

            std::unordered_set<std::string> overriddenConstants;

            auto switchType = [&](EntryPointMetadata::OverridableConstant::Type dawnType,
                                  MTLDataType* type, OverridableConstantScalar* entry,
                                  double value = 0) {
                switch (dawnType) {
                    case EntryPointMetadata::OverridableConstant::Type::Boolean:
                        *type = MTLDataTypeBool;
                        if (entry) {
                            entry->b = static_cast<int32_t>(value);
                        }
                        break;
                    case EntryPointMetadata::OverridableConstant::Type::Float32:
                        *type = MTLDataTypeFloat;
                        if (entry) {
                            entry->f32 = static_cast<float>(value);
                        }
                        break;
                    case EntryPointMetadata::OverridableConstant::Type::Int32:
                        *type = MTLDataTypeInt;
                        if (entry) {
                            entry->i32 = static_cast<int32_t>(value);
                        }
                        break;
                    case EntryPointMetadata::OverridableConstant::Type::Uint32:
                        *type = MTLDataTypeUInt;
                        if (entry) {
                            entry->u32 = static_cast<uint32_t>(value);
                        }
                        break;
                    default:
                        UNREACHABLE();
                }
            };

            for (const auto& [name, value] : programmableStage.constants) {
                overriddenConstants.insert(name);

                // This is already validated so `name` must exist
                const auto& moduleConstant = entryPointMetadata.overridableConstants.at(name);

                MTLDataType type;
                OverridableConstantScalar entry{};

                switchType(moduleConstant.type, &type, &entry, value);

                [constantValues.Get() setConstantValue:&entry type:type atIndex:moduleConstant.id];
            }

            // Set shader initialized default values because MSL function_constant
            // has no default value
            for (const std::string& name : entryPointMetadata.initializedOverridableConstants) {
                if (overriddenConstants.count(name) != 0) {
                    // This constant already has overridden value
                    continue;
                }

                // Must exist because it is validated
                const auto& moduleConstant = entryPointMetadata.overridableConstants.at(name);
                ASSERT(moduleConstant.isInitialized);
                MTLDataType type;

                switchType(moduleConstant.type, &type, nullptr);

                [constantValues.Get() setConstantValue:&moduleConstant.defaultValue
                                                  type:type
                                               atIndex:moduleConstant.id];
            }

            DAWN_TRY(shaderModule->CreateFunction(
                shaderEntryPoint, singleShaderStage, pipelineLayout, functionData,
                constantValues.Get(), sampleMask, renderPipeline));
        } else {
            UNREACHABLE();
        }
        return {};
    }

}  // namespace dawn_native::metal
