/*
 * 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->isRenderableWithMSRTSS(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 render pass.
        desc.fDepthStencilAttachment = {dsFormat,
                                        LoadOp::kClear,
                                        StoreOp::kDiscard,
                                        desc.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(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
