/*
 * Copyright 2024 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/RenderPassDesc.h"

#include "include/gpu/graphite/TextureInfo.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/TextureInfoPriv.h"

namespace skgpu::graphite {

namespace {

const char* to_str(LoadOp op) {
    switch (op) {
        case LoadOp::kLoad:    return "load";
        case LoadOp::kClear:   return "clear";
        case LoadOp::kDiscard: return "discard";
    }

    SkUNREACHABLE;
}

const char* to_str(StoreOp op) {
    switch (op) {
        case StoreOp::kStore:   return "store";
        case StoreOp::kDiscard: return "discard";
    }

    SkUNREACHABLE;
}

} // anonymous namespace

RenderPassDesc RenderPassDesc::Make(const Caps* caps,
                                    const TextureInfo& targetInfo,
                                    LoadOp loadOp,
                                    StoreOp storeOp,
                                    SkEnumBitMask<DepthStencilFlags> depthStencilFlags,
                                    const std::array<float, 4>& clearColor,
                                    bool requiresMSAA,
                                    Swizzle writeSwizzle,
                                    const DstReadStrategy dstReadStrategy) {
    // It doesn't make sense to have a storeOp for our main target not be store. Why are we doing
    // this DrawPass then
    SkASSERT(storeOp == StoreOp::kStore);

    RenderPassDesc desc;
    desc.fClearColor = clearColor;
    // Depth and stencil is currently always cleared to 1.f or 0 if it's used. Depth is 1.0 and
    // counts down as painter's order increases due to HW preference for historic OpenGL defaults
    // of a fast hi-z clear value of 1.0 with depth test of lesser.
    desc.fClearDepth = 1.f;
    desc.fClearStencil = 0;
    desc.fWriteSwizzle = writeSwizzle;
    desc.fDstReadStrategy = dstReadStrategy;

    TextureFormat colorFormat = TextureInfoPriv::ViewFormat(targetInfo);
    // The render pass's overall sample count will either be the target's sample count
    // (when single-sampling or already multisampled), or the default sample count (which will then
    // be either the implicit sample count for msaa-render-to-single-sample or the explicit sample
    // count of a separate color attachment).
    //
    // Higher-level logic should ensure the default MSAA sample count is supported if using either
    // msaa-render-to-single-sample or with separate attachments, and select non-MSAA techniques if
    // they weren't supported. getCompatibleMSAASampleCount() downgrades to single-sampled if we got
    // here and MSAA isn't supported.
    const bool msaaRenderToSingleSampledSupport =
            caps->msaaTextureRenderToSingleSampledSupport(targetInfo);
    desc.fSampleCount = requiresMSAA ? caps->getCompatibleMSAASampleCount(targetInfo)
                                     : targetInfo.sampleCount();

    // We need to handle MSAA with an extra color attachment if:
    const bool needsMSAAColorAttachment =
            desc.fSampleCount > SampleCount::k1 &&         // using MSAA for the render pass,
            targetInfo.sampleCount() == SampleCount::k1 && // the target isn't already MSAA'ed,
            !msaaRenderToSingleSampledSupport;             // can't use an MSAA->single extension.
    if (needsMSAAColorAttachment) {
        // We set the color and resolve attachments up the same regardless of if the backend ends up
        // using msaaRenderToSingleSampledSupport() to skip explicitly creating the MSAA attachment.
        // The color attachment (and any depth/stencil attachment) will use `sampleCount` and the
        // resolve attachment will be single-sampled.
        desc.fColorAttachment = {colorFormat,
                                 loadOp != LoadOp::kClear ? LoadOp::kDiscard : LoadOp::kClear,
                                 StoreOp::kDiscard,
                                 desc.fSampleCount};
        desc.fColorResolveAttachment = {colorFormat,
                                        loadOp != LoadOp::kLoad ? LoadOp::kDiscard : LoadOp::kLoad,
                                        storeOp,
                                        SampleCount::k1};
    } else {
        // The target will be the color attachment and skip configuring the resolve attachment.
        SkASSERT(desc.fColorResolveAttachment.fFormat == TextureFormat::kUnsupported);
        desc.fColorAttachment = {colorFormat,
                                 loadOp,
                                 storeOp,
                                 targetInfo.sampleCount()};
    }

    if (depthStencilFlags != DepthStencilFlags::kNone) {
        // To reduce pipeline compiles and attachment creations, if we need multisampling and need
        // a depth or stencil attachment, we always choose a depth-AND-stencil format.
        if (desc.fColorAttachment.fSampleCount > SampleCount::k1) {
            depthStencilFlags = DepthStencilFlags::kDepthStencil;
        }
        TextureFormat dsFormat = caps->getDepthStencilFormat(depthStencilFlags);
        SkASSERT(dsFormat != TextureFormat::kUnsupported);
        // Depth and stencil values are currently always cleared and don't need to persist.
        // The sample count should always match the color attachment.
        desc.fDepthStencilAttachment = {dsFormat,
                                        LoadOp::kClear,
                                        StoreOp::kDiscard,
                                        desc.fColorAttachment.fSampleCount};
    } else {
        SkASSERT(desc.fDepthStencilAttachment.fFormat == TextureFormat::kUnsupported);
    }

    return desc;
}

SkString RenderPassDesc::toString() const {
    return SkStringPrintf("RP(color: %s, resolve: %s, ds: %s, samples: %u, swizzle: %s, "
                          "clear: c(%f,%f,%f,%f), d(%f), s(0x%02x), dst read: %u)",
                          fColorAttachment.toString().c_str(),
                          fColorResolveAttachment.toString().c_str(),
                          fDepthStencilAttachment.toString().c_str(),
                          (unsigned)fSampleCount,
                          fWriteSwizzle.asString().c_str(),
                          fClearColor[0], fClearColor[1], fClearColor[2], fClearColor[3],
                          fClearDepth,
                          fClearStencil,
                          (unsigned)fDstReadStrategy);
}

SkString RenderPassDesc::toPipelineLabel() const {
    // Given current policies, these assumptions should hold and mean the conciseness in the label
    // is still unambiguous.
    SkASSERT(fColorAttachment.fFormat != TextureFormat::kUnsupported);
    SkASSERT(fColorResolveAttachment.fFormat == TextureFormat::kUnsupported ||
             fColorResolveAttachment.fFormat == fColorAttachment.fFormat);
    SkASSERT(fDepthStencilAttachment.fFormat == TextureFormat::kUnsupported ||
             fDepthStencilAttachment.fSampleCount == fColorAttachment.fSampleCount);
    SkASSERT(fColorResolveAttachment.fFormat == TextureFormat::kUnsupported ||
             fColorResolveAttachment.fSampleCount == SampleCount::k1);
    SkASSERT(fColorAttachment.fSampleCount == fSampleCount ||
             (fColorAttachment.fSampleCount == SampleCount::k1 && fSampleCount > SampleCount::k1));

    const char* colorFormatStr = TextureFormatName(fColorAttachment.fFormat);
    const char* dsFormatStr = "{}";
    if (fDepthStencilAttachment.fFormat != TextureFormat::kUnsupported) {
        dsFormatStr = TextureFormatName(fDepthStencilAttachment.fFormat);
    }

    // This intentionally only includes the fixed state that impacts pipeline compilation.
    // We include the load op of the color attachment when there is a resolve attachment because
    // the load may trigger a different renderpass description.
    const char* colorLoadStr = "";
    const bool loadMsaaFromResolve =
            fColorResolveAttachment.fFormat != TextureFormat::kUnsupported &&
            fColorResolveAttachment.fLoadOp == LoadOp::kLoad;

    // This should, technically, check Caps::loadOpAffectsMSAAPipelines before adding the extra
    // string. Only the Metal backend doesn't set that flag, however, so we just assume it is set
    // to reduce plumbing. Since the Metal backend doesn't differentiate its UniqueKeys wrt
    // resolve-loads, this can lead to instances where two Metal Pipeline labels will map to the
    // same UniqueKey (i.e., one with "w/ msaa load" and one without it).
    if (loadMsaaFromResolve /* && Caps::loadOpAffectsMSAAPipelines() */) {
        colorLoadStr = " w/ msaa load";
    }

    // There are three supported ways of achieving MSAA rendering that we distinguish compactly.
    // 1. Direct sampling w/ N samples (includes single sample)
    // 2. MSAA render to single-sampled extensions
    // 3. Explicit MSAA color attachment w/ resolve
    // Since we don't expect to be mixing case 2 and 3 on the same device, treating them the same
    // in the pipeline labels makes it more convenient when writing test expectations.
    SkString sampleCountStr;
    if (fColorResolveAttachment.fFormat == TextureFormat::kUnsupported &&
        fSampleCount == fColorAttachment.fSampleCount) {
        // Case 1: "xN"
        sampleCountStr = SkStringPrintf("x%u", (unsigned)fSampleCount);
    } else {
        // Case 2 and 3: "xN->1"
        sampleCountStr = SkStringPrintf("x%u->1", (unsigned)fSampleCount);
    }
    // NOTE: This label does not differentiate between explicitly resolved MSAA color attachments
    // and MSAA-render-to-single-sample renderpasses. For a given set of Caps, we currently only
    // expect to generate one or the other variety.
    return SkStringPrintf("RP((%s+%s %s).%s%s)",
                          colorFormatStr,
                          dsFormatStr,
                          sampleCountStr.c_str(),
                          fWriteSwizzle.asString().c_str(),
                          colorLoadStr);
}

SkString AttachmentDesc::toString() const {
    if (fFormat == TextureFormat::kUnsupported) {
        return SkString("{}");
    } else {
        return SkStringPrintf("{f: %s x%u, ops: %s->%s}",
                              TextureFormatName(fFormat),
                              (unsigned)fSampleCount,
                              to_str(fLoadOp),
                              to_str(fStoreOp));
    }
}

bool AttachmentDesc::isCompatible(const TextureInfo& texInfo) const {
    return fFormat == TextureInfoPriv::ViewFormat(texInfo) && fSampleCount == texInfo.sampleCount();
}

} // namespace skgpu::graphite
