/*
 * Copyright 2021 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/graphite/mtl/MtlCaps.h"

#include "include/core/SkTextureCompressionType.h"
#include "include/gpu/graphite/TextureInfo.h"
#include "include/gpu/graphite/mtl/MtlGraphiteTypes.h"
#include "include/private/SkLog.h"
#include "src/gpu/SwizzlePriv.h"
#include "src/gpu/graphite/CommandBuffer.h"
#include "src/gpu/graphite/ComputePipelineDesc.h"
#include "src/gpu/graphite/GraphicsPipelineDesc.h"
#include "src/gpu/graphite/GraphiteResourceKey.h"
#include "src/gpu/graphite/RenderPassDesc.h"
#include "src/gpu/graphite/RendererProvider.h"
#include "src/gpu/graphite/TextureInfoPriv.h"
#include "src/gpu/graphite/TextureProxy.h"
#include "src/gpu/graphite/mtl/MtlGraphicsPipeline.h"
#include "src/gpu/graphite/mtl/MtlGraphiteUtils.h"
#include "src/gpu/mtl/MtlUtilsPriv.h"
#include "src/sksl/SkSLUtil.h"

namespace skgpu::graphite {

MtlCaps::MtlCaps(const id<MTLDevice> device, const ContextOptions& options) : Caps() {
    // Metal-specific MtlCaps
    this->initGPUFamily(device);
    this->initCaps(device);
    this->initFormatTable(device);

    // Finish base class
    this->finishInitialization(options);
}

void MtlCaps::initGPUFamily(id<MTLDevice> device) {
    static_assert(SKGPU_GRAPHITE_METAL_SDK_VERSION >= 230);

    static constexpr MTLGPUFamily kFamiliesToCheck[] = {
        // Apple silicon shared between iOS and Mac
        MTLGPUFamilyApple9,
        MTLGPUFamilyApple8,
        MTLGPUFamilyApple7,
#ifdef SK_BUILD_FOR_IOS // This hardware is iOS exclusive
        MTLGPUFamilyApple6,
        MTLGPUFamilyApple5,
        MTLGPUFamilyApple4,
        MTLGPUFamilyApple3,
        MTLGPUFamilyApple2,
#endif
        // Legacy mac hardware
        MTLGPUFamilyMac2
    };

    for (MTLGPUFamily family : kFamiliesToCheck) {
        if ([device supportsFamily:family]) {
            fGPUFamily = family;
            return;
        }
    }

    // If we've reached here, we didn't find a supported family and nothing can be trusted.
    SK_ABORT("Unable to detect supported MTLGPUFamily");
}

void MtlCaps::initCaps(const id<MTLDevice> device) {
#if defined(GPU_TEST_UTILS)
    this->setDeviceName([[device name] UTF8String]);
#endif

    if (this->isMac() || fGPUFamily >= MTLGPUFamilyApple3) {
        fMaxTextureSize = 16384;
    } else {
        fMaxTextureSize = 8192;
    }

    // We use constant address space for our uniform buffers which has various alignment
    // requirements for the offset when binding the buffer. On MacOS Intel the offset must align
    // to 256. On iOS or Apple Silicon we must align to the max of the data type consumed by the
    // vertex function or 4 bytes, or we can ignore the data type and just use 16 bytes.
    //
    // On Mac, all copies must be aligned to at least 4 bytes; on iOS there is no alignment.
    if (this->isMac()) {
        fRequiredUniformBufferAlignment = 256;
        fRequiredTransferBufferAlignment = 4;
    } else {
        fRequiredUniformBufferAlignment = 16;
        fRequiredTransferBufferAlignment = 1;
    }

    fResourceBindingReqs.fBackendApi = BackendApi::kMetal;
    fResourceBindingReqs.fUniformBufferLayout = Layout::kMetal;
    fResourceBindingReqs.fStorageBufferLayout = Layout::kMetal;

    // Graphite/Metal does not group resources into different sets or bind groups at this time,
    // though ResourceBindingRequirements still expects valid assignments of these indices.
    // Assigning both to 0 conveys the usage of one single "set" for all resources.
    fResourceBindingReqs.fUniformsSetIdx = 0;
    fResourceBindingReqs.fTextureSamplerSetIdx = 0;

    fResourceBindingReqs.fComputeUsesDistinctIdxRangesForTextures = true;

    fResourceBindingReqs.fIntrinsicBufferBinding =
            MtlGraphicsPipeline::kIntrinsicUniformBufferIndex;
    fResourceBindingReqs.fCombinedUniformBufferBinding = MtlGraphicsPipeline::kCombinedUniformIndex;
    fResourceBindingReqs.fGradientBufferBinding = MtlGraphicsPipeline::kGradientBufferIndex;

    // Metal does not distinguish between uniform and storage buffers.
    fRequiredStorageBufferAlignment = fRequiredUniformBufferAlignment;

    fStorageBufferSupport = true;

    fComputeSupport = true;

    // See https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf, and what Dawn does at
    // https://crsrc.org/c/third_party/dawn/src/dawn/native/metal/PhysicalDeviceMTL.mm?q=maxInterStageShaderVariables
    if (this->isMac() || fGPUFamily >= MTLGPUFamilyApple4) {
        fMaxVaryings = 31;
    } else {
        fMaxVaryings = 15;
    }

    if (@available(macOS 10.12, iOS 14.0, tvOS 14.0, *)) {
        fClampToBorderSupport = (this->isMac() || fGPUFamily >= MTLGPUFamilyApple7);
    } else {
        fClampToBorderSupport = false;
    }

    const bool isIntel = [device.name containsString:@"Intel"];
    if (isIntel) {
        // All supported Intel Macs are of an old enough Intel generation that we can just assume
        // MSAA should be avoided instead of checking its generation.
        fAvoidMSAA = true;
    }

    // ShaderCaps overrides
    SkSL::ShaderCaps* shaderCaps = fShaderCaps.get();

    // Dual source blending requires Metal 1.2, but our minimum requirements ensure 2.2
    shaderCaps->fDualSourceBlendingSupport = true;
    shaderCaps->fVectorClampMinMaxSupport = !isIntel;
    if (this->isApple()) {
        shaderCaps->fFBFetchSupport = true;
        shaderCaps->fFBFetchColorName = "sk_LastFragColor";
    }
}


void MtlCaps::initFormatTable(const id<MTLDevice> device) {
    // Determine supported sample counts (used for all renderable formats that can be resolved).
    SkEnumBitMask<SampleCount> deviceSampleCounts = SampleCount::k1;
    if (!fAvoidMSAA) {
        for (auto sampleCnt : {SampleCount::k2, SampleCount::k4, SampleCount::k8}) {
            if ([device supportsTextureSampleCount: (uint8_t) sampleCnt]) {
                deviceSampleCounts |= sampleCnt;
            }
        }
    }

    for (int i = 0; i < kTextureFormatCount; ++i) {
        TextureFormat tf = static_cast<TextureFormat>(i);
        MTLPixelFormat format = TextureFormatToMTLPixelFormat(tf);
        SkEnumBitMask<MTLFeatureFlag> features = MTLPixelFormatSupport(fGPUFamily, format);

        // Check device capabilities to override `features`
#ifdef SK_BUILD_FOR_MAC
        if ((format == MTLPixelFormatDepth24Unorm_Stencil8 ||
             format == MTLPixelFormatX24_Stencil8) &&
            ![device isDepth24Stencil8PixelFormatSupported]) {
            features = MTLFeatureFlag::NotAvailable;
        }
#endif

        // The metal backend only supports optimal tiling currently
        auto& [supportedUsage, supportedSampleCounts] = fFormatSupport[(int) Tiling::kOptimal][i];
        if (features == MTLFeatureFlag::NotAvailable) {
            SkASSERT(!SkToBool(supportedUsage) && !SkToBool(supportedSampleCounts));
            continue;
        }

        // Convert from the Metal format feature flags to Graphite's TextureUsage.
        SkASSERT(format != MTLPixelFormatInvalid);

        // Every available pixel format can be used as a copy src and dst in Metal.
        // Graphite chooses to exclude kCopySrc on compressed formats
        if (TextureFormatCompressionType(tf) != SkTextureCompressionType::kNone) {
            supportedUsage |= TextureUsage::kCopyDst;
        } else {
            SkASSERT(tf != TextureFormat::kExternal);
            supportedUsage |= TextureUsage::kCopySrc | TextureUsage::kCopyDst;
        }

        // Graphite assumes you can filter in a shader (not just read texels)
        if (features & MTLFeatureFlag::Filter) {
            supportedUsage |= TextureUsage::kSample;
        }

        // Graphite requires textures to be writable to be used for compute storage
        // (they are always readable).
        if (features & MTLFeatureFlag::Write) {
            supportedUsage |= TextureUsage::kStorage;
        }

        SkEnumBitMask<MTLFeatureFlag> msaaFlags = MTLFeatureFlag::MSAA;
        if (TextureFormatIsDepthOrStencil(tf)) {
            // All available DS formats can be rendered into; Graphite never resolves DS attachments
            // so they support MSAA with just that feature flag
            supportedUsage |= TextureUsage::kRender;
        } else if ((features & MTLFeatureFlag::Color) && (features & MTLFeatureFlag::Blend)) {
            // Color formats require both being a color render target feature and having blending to
            // be useful.
            supportedUsage |= TextureUsage::kRender;
            // Graphite will also assume that it can use the texture format as the resolve target
            // for color attachments.
            msaaFlags |= MTLFeatureFlag::Resolve;
        }

        if ((features & msaaFlags) == msaaFlags) {
            SkASSERT(supportedUsage & TextureUsage::kRender);
            supportedSampleCounts = deviceSampleCounts;
        } else {
            supportedSampleCounts = SampleCount::k1;
        }
    }
}

std::pair<SkEnumBitMask<TextureUsage>, Tiling> MtlCaps::getTextureUsage(
        const TextureInfo& info) const {
    const auto& mtlInfo = TextureInfoPriv::Get<MtlTextureInfo>(info);

    SkEnumBitMask<TextureUsage> usage;
    if (mtlInfo.fUsage & MTLTextureUsageRenderTarget) {
        usage |= TextureUsage::kRender;
        // NOTE: No support for MSRTSS
    }

    // Other than rendering, every other usage is blocked if it's framebuffer-only
    if (!mtlInfo.fFramebufferOnly) {
        if (mtlInfo.fUsage & MTLTextureUsageShaderRead) {
            usage |= TextureUsage::kSample;

            if (mtlInfo.fUsage & MTLTextureUsageShaderWrite) {
                usage |= TextureUsage::kStorage;
            }
        }

        // Always include CopySrc and CopyDst, relying on the format's supported flags to mask
        // the final capabilities automatically (e.g. if this were compressed)
        usage |= TextureUsage::kCopySrc | TextureUsage::kCopyDst;

        // NOTE: No support for TextureUsage::kHostCopy yet
    }

    return {usage, Tiling::kOptimal};
}

TextureInfo MtlCaps::onGetDefaultTextureInfo(SkEnumBitMask<TextureUsage> usage,
                                             TextureFormat format,
                                             SampleCount sampleCount,
                                             Mipmapped mipmapped,
                                             Protected,
                                             Discardable discardable) const {
    MTLPixelFormat mtlFormat = TextureFormatToMTLPixelFormat(format);
    SkASSERT(mtlFormat != MTLPixelFormatInvalid); // should have been caught by support check first

    // Default to private in the event it's not discardable or memoryless is not available
    MTLStorageMode storageMode = MTLStorageModePrivate;
    MTLTextureUsage mtlUsage = MTLTextureUsageUnknown;

    if (usage & TextureUsage::kSample) {
        mtlUsage |= MTLTextureUsageShaderRead;
    }
    if (usage & TextureUsage::kStorage) {
        mtlUsage |= MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite;
    }
    if (usage & TextureUsage::kRender) {
        mtlUsage |= MTLTextureUsageRenderTarget;
        // Switch to memoryless for discardable render targets when possible (only on Apple silicon)
        if (discardable == Discardable::kYes && this->isApple()) {
            storageMode = MTLStorageModeMemoryless;
        }
    }
    // NOTE: CopyDst and CopySrc are not MTLTextureUsages that have to be requested, so ignore them.
    // Caps should not be requested anything with HostCopy or MSRTSS since these are not supported.
    SkASSERT(!SkToBool(usage & TextureUsage::kHostCopy) &&
             !SkToBool(usage & TextureUsage::kMSRTSS));

    MtlTextureInfo info;
    info.fSampleCount = sampleCount;
    info.fMipmapped = mipmapped;
    info.fFormat = mtlFormat;
    info.fUsage = mtlUsage;
    info.fStorageMode = storageMode;
    info.fFramebufferOnly = false;

    return TextureInfos::MakeMetal(info);
}

namespace {

skgpu::UniqueKey::Domain get_domain() {
    static const skgpu::UniqueKey::Domain kMtlGraphicsPipelineDomain =
            skgpu::UniqueKey::GenerateDomain();

    return kMtlGraphicsPipelineDomain;
}

}

static constexpr uint16_t kMtlGraphicsPipelineKeyData32Count = 4;

UniqueKey MtlCaps::makeGraphicsPipelineKey(const GraphicsPipelineDesc& pipelineDesc,
                                           const RenderPassDesc& renderPassDesc) const {
    UniqueKey pipelineKey;
    {
        // 4 uint32_t's (render step id, paint id, renderpass desc, uint16 write swizzle key)
        UniqueKey::Builder builder(&pipelineKey, get_domain(),
                                   kMtlGraphicsPipelineKeyData32Count, "MtlGraphicsPipeline");
        // add GraphicsPipelineDesc key
        builder[0] = static_cast<uint32_t>(pipelineDesc.renderStepID());
        builder[1] = pipelineDesc.paintParamsID().asUInt();

        // add RenderPassDesc key
        builder[2] = this->getRenderPassDescKey(renderPassDesc);
        builder[3] = renderPassDesc.fWriteSwizzle.asKey();

        builder.finish();
    }

    return pipelineKey;
}

bool MtlCaps::extractGraphicsDescs(const UniqueKey& key,
                                   GraphicsPipelineDesc* pipelineDesc,
                                   RenderPassDesc* renderPassDesc,
                                   const RendererProvider* rendererProvider) const {
    struct UnpackedKeyData {
        // From the GraphicsPipelineDesc
        RenderStep::RenderStepID fRenderStepID = RenderStep::RenderStepID::kInvalid;
        UniquePaintParamsID fPaintParamsID = UniquePaintParamsID::Invalid();

        // From the RenderPassDesc
        TextureFormat fColorFormat = TextureFormat::kUnsupported;
        SampleCount fColorSampleCount = SampleCount::k1;

        TextureFormat fDSFormat = TextureFormat::kUnsupported;
        SampleCount fDSSampleCount = SampleCount::k1;

        Swizzle fWriteSwizzle;
    } keyData;

    SkASSERT(key.domain() == get_domain());
    SkASSERT(key.dataSize() == 4 * kMtlGraphicsPipelineKeyData32Count);

    const uint32_t* rawKeyData = key.data();

    SkASSERT(RenderStep::IsValidRenderStepID(rawKeyData[0]));
    keyData.fRenderStepID = static_cast<RenderStep::RenderStepID>(rawKeyData[0]);
    keyData.fPaintParamsID = rawKeyData[1] ? UniquePaintParamsID(rawKeyData[1])
                                           : UniquePaintParamsID::Invalid();

    keyData.fDSFormat = static_cast<TextureFormat>((rawKeyData[2] >> 8) & 0xFF);
    keyData.fDSSampleCount = static_cast<SampleCount>(rawKeyData[2] & 0xFF);

    keyData.fColorFormat = static_cast<TextureFormat>((rawKeyData[2] >> 24) & 0xFF);
    keyData.fColorSampleCount = static_cast<SampleCount>((rawKeyData[2] >> 16) & 0xFF);

    keyData.fWriteSwizzle = SwizzleCtorAccessor::Make(rawKeyData[3]);

    if ((keyData.fColorSampleCount > SampleCount::k1 && this->avoidMSAA()) ||
        (keyData.fDSFormat != TextureFormat::kUnsupported && this->avoidDepthMode())) {
        return false;
    }

    // Recreate the RenderPassDesc, picking arbitrary load/store ops. Since Metal doesn't need
    // to include resolve attachment details, assume that if color attachment's sample count is > 1
    // that there is a matching resolve attachment (no MSAA-render-to-single-sample support in MTL).
    SkASSERT(keyData.fColorSampleCount == keyData.fDSSampleCount ||
             keyData.fDSFormat == TextureFormat::kUnsupported);
    *renderPassDesc = {};
    renderPassDesc->fColorAttachment = {keyData.fColorFormat,
                                        LoadOp::kClear,
                                        StoreOp::kStore,
                                        keyData.fColorSampleCount};
    if (!this->avoidDepthMode()) {
        renderPassDesc->fDepthStencilAttachment = {keyData.fDSFormat,
                                                   LoadOp::kClear,
                                                   StoreOp::kDiscard,
                                                   keyData.fDSSampleCount};
    }
    if (keyData.fColorSampleCount > SampleCount::k1) {
        renderPassDesc->fColorResolveAttachment = {keyData.fColorFormat,
                                                   LoadOp::kClear,
                                                   StoreOp::kStore,
                                                   SampleCount::k1};
        renderPassDesc->fColorAttachment.fStoreOp = StoreOp::kDiscard;
    }

    renderPassDesc->fSampleCount = keyData.fColorSampleCount;
    renderPassDesc->fWriteSwizzle = keyData.fWriteSwizzle;
    renderPassDesc->fDstReadStrategy = this->getDstReadStrategy();

    // Recreate the GraphicsPipelineDesc
    const RenderStep* renderStep = rendererProvider->lookup(keyData.fRenderStepID);

    UniquePaintParamsID paintID = renderStep->performsShading() ? keyData.fPaintParamsID
                                                                : UniquePaintParamsID::Invalid();

    *pipelineDesc = GraphicsPipelineDesc(renderStep->renderStepID(), paintID);

    return true;
}

uint32_t MtlCaps::getRenderPassDescKey(const RenderPassDesc& renderPassDesc) const {
    static_assert(kTextureFormatCount <= 256);

    // Each attachment format + sample count fits in 16-bits. Load/store ops are ignored.
    auto attachmentKey = [](AttachmentDesc desc) {
        SkASSERT(desc.fFormat != TextureFormat::kUnsupported ||
                 desc.fSampleCount == SampleCount::k1);
        return (static_cast<uint32_t>(desc.fFormat) << 8) |
                static_cast<uint32_t>(desc.fSampleCount);
    };

    // The MtlRenderPassDescriptor requires no information about the resolve attachment
    return (attachmentKey(renderPassDesc.fColorAttachment) << 16) |
            attachmentKey(renderPassDesc.fDepthStencilAttachment);
}

UniqueKey MtlCaps::makeComputePipelineKey(const ComputePipelineDesc& pipelineDesc) const {
    UniqueKey pipelineKey;
    {
        static const skgpu::UniqueKey::Domain kComputePipelineDomain = UniqueKey::GenerateDomain();
        // The key is made up of a single uint32_t corresponding to the compute step ID.
        UniqueKey::Builder builder(&pipelineKey, kComputePipelineDomain, 1, "ComputePipeline");
        builder[0] = pipelineDesc.computeStep()->uniqueID();

        // TODO(b/240615224): The local work group size should factor into the key on platforms
        // that don't support specialization constants and require the workgroup/threadgroup size to
        // be specified in the shader text (D3D12, Vulkan 1.0, and OpenGL).

        builder.finish();
    }
    return pipelineKey;
}

void MtlCaps::buildKeyForTexture(SkISize dimensions,
                                 const TextureInfo& info,
                                 ResourceType type,
                                 GraphiteResourceKey* key) const {
    const auto& mtlInfo = TextureInfoPriv::Get<MtlTextureInfo>(info);

    SkASSERT(!dimensions.isEmpty());

    // A MTLPixelFormat is an NSUInteger type which is documented to be 32 bits in 32 bit
    // applications and 64 bits in 64 bit applications. So it should fit in an uint64_t, but adding
    // the assert heere to make sure.
    static_assert(sizeof(MTLPixelFormat) <= sizeof(uint64_t));
    SkASSERT(mtlInfo.fFormat != MTLPixelFormatInvalid);
    uint64_t formatKey = static_cast<uint64_t>(mtlInfo.fFormat);

    uint32_t samplesKey = SamplesToKey(info.sampleCount());
    // We don't have to key the number of mip levels because it is inherit in the combination of
    // isMipped and dimensions.
    bool isMipped = mtlInfo.fMipmapped == Mipmapped::kYes;
    Protected isProtected = info.isProtected();
    bool isFBOnly = mtlInfo.fFramebufferOnly;

    // Confirm all the below parts of the key can fit in a single uint32_t. The sum of the shift
    // amounts in the asserts must be less than or equal to 32.
    SkASSERT(samplesKey                         < (1u << kNumSampleKeyBits));
    SkASSERT(static_cast<uint32_t>(isMipped)    < (1u << 1));
    SkASSERT(static_cast<uint32_t>(isProtected) < (1u << 1));
    SkASSERT(mtlInfo.fUsage                     < (1u << 5));
    SkASSERT(mtlInfo.fStorageMode               < (1u << 2));
    SkASSERT(static_cast<uint32_t>(isFBOnly)    < (1u << 1));

    // We need two uint32_ts for dimensions, 2 for format, and 1 for the rest of the key;
    static uint16_t kNum32DataCnt = 2 + 2 + 1;

    GraphiteResourceKey::Builder builder(key, type, kNum32DataCnt);

    builder[0] = dimensions.width();
    builder[1] = dimensions.height();
    builder[2] = formatKey & 0xFFFFFFFF;
    builder[3] = (formatKey >> 32) & 0xFFFFFFFF;
    builder[4] = (samplesKey                                  << 0) |
                 (static_cast<uint32_t>(isMipped)             << kNumSampleKeyBits) |
                 (static_cast<uint32_t>(isProtected)          << 4) |
                 (static_cast<uint32_t>(mtlInfo.fUsage)       << 5) |
                 (static_cast<uint32_t>(mtlInfo.fStorageMode) << 10)|
                 (static_cast<uint32_t>(isFBOnly)             << 12);

}

} // namespace skgpu::graphite
