/*
 * 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/task/RenderPassTask.h"

#include "include/core/SkPoint.h"
#include "include/core/SkSize.h"
#include "include/core/SkSpan.h"
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/TextureInfo.h"
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkLog.h"
#include "src/gpu/SkBackingFit.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/CommandBuffer.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/DrawPass.h"
#include "src/gpu/graphite/ResourceProvider.h"
#include "src/gpu/graphite/ResourceTypes.h"
#include "src/gpu/graphite/ScratchResourceManager.h"
#include "src/gpu/graphite/Texture.h"
#include "src/gpu/graphite/TextureFormat.h"
#include "src/gpu/graphite/TextureProxy.h"

#include <tuple>
#include <utility>

namespace skgpu::graphite {

class GraphicsPipeline;

namespace {

// Get the required MSAA size for the render pass.
// In some scenarios, the MSAA size can be smaller than the target texture. As long as it is big
// enough to contain the draws' bounds.
std::pair<SkISize, SkIPoint> get_msaa_size_and_resolve_offset(const SkISize& targetSize,
                                                              const SkIRect& drawBounds,
                                                              const Caps& caps,
                                                              LoadOp loadOp) {
    if (caps.differentResolveAttachmentSizeSupport()) {
        // If possible, use approx size that can fit all draws. This reduces the MSAA texture size
        // and also reuses the textures better.
        // Note: we don't do this if loadOp=Clear because it's supposed to update the whole target
        // texture.
        auto smallEnoughBounds = drawBounds;
        if (loadOp != LoadOp::kClear && !smallEnoughBounds.isEmpty() &&
            smallEnoughBounds.intersect(SkIRect::MakeSize(targetSize))) {
            SkIPoint resolveOffset = smallEnoughBounds.topLeft();
            return {GetApproxSize(smallEnoughBounds.size()), resolveOffset};
        } else {
            return {GetApproxSize(targetSize), {0, 0}};
        }
    }

    return {targetSize, {0, 0}};
}

}  // anonymous namespace

sk_sp<RenderPassTask> RenderPassTask::Make(DrawPassList passes,
                                           const RenderPassDesc& desc,
                                           sk_sp<TextureProxy> target,
                                           sk_sp<TextureProxy> dstCopy,
                                           SkIRect dstReadBounds) {
    // For now we have one DrawPass per RenderPassTask
    SkASSERT(passes.size() == 1);
    // If we have a dst copy texture, ensure it is big enough to cover the copy bounds that
    // will be sampled.
    SkASSERT(!dstCopy || (dstCopy->dimensions().width() >= dstReadBounds.width() &&
                          dstCopy->dimensions().height() >= dstReadBounds.height()));
    if (!target) {
        return nullptr;
    }

    if (desc.fColorResolveAttachment.fFormat != TextureFormat::kUnsupported) {
        // The resolve attachment must match `target`, since that is what's resolved to.
        SkASSERT(desc.fColorResolveAttachment.isCompatible(target->textureInfo()));
        // The resolve attachment should be single sampled and not depth/stencil
        SkASSERT(desc.fColorResolveAttachment.fSampleCount == SampleCount::k1);
        SkASSERT(!TextureFormatIsDepthOrStencil(desc.fColorResolveAttachment.fFormat));
        // If there's a resolve attachment, the color attachment should have the same format and
        // more samples than the resolve.
        SkASSERT(desc.fColorAttachment.fFormat == desc.fColorResolveAttachment.fFormat);
        SkASSERT(desc.fColorAttachment.fSampleCount > SampleCount::k1);
        // The render pass's sample count must match the color attachment's sample count
        SkASSERT(desc.fSampleCount == desc.fColorAttachment.fSampleCount);
    } else {
        // The color attachment must match `target`, as it will be used to render directly into.
        SkASSERT(desc.fColorAttachment.isCompatible(target->textureInfo()));
        // The render pass's sample count must match or the color attachment's must be 1 and
        // the render pass has a higher sample count for msaa-render-to-single-sampled extensions.
        SkASSERT(desc.fColorAttachment.fSampleCount == desc.fSampleCount ||
                 (desc.fColorAttachment.fSampleCount == SampleCount::k1 &&
                  desc.fSampleCount > SampleCount::k1));
    }

    if (desc.fDepthStencilAttachment.fFormat != TextureFormat::kUnsupported) {
        // The sample count for any depth/stencil buffer must match the render pass.
        SkASSERT(TextureFormatIsDepthOrStencil(desc.fDepthStencilAttachment.fFormat));
        SkASSERT(desc.fDepthStencilAttachment.fSampleCount == desc.fSampleCount);
    }

    return sk_sp<RenderPassTask>(new RenderPassTask(std::move(passes),
                                                    desc,
                                                    std::move(target),
                                                    std::move(dstCopy),
                                                    dstReadBounds));
}

RenderPassTask::RenderPassTask(DrawPassList passes,
                               const RenderPassDesc& desc,
                               sk_sp<TextureProxy> target,
                               sk_sp<TextureProxy> dstCopy,
                               SkIRect dstReadBounds)
        : fDrawPasses(std::move(passes))
        , fRenderPassDesc(desc)
        , fTarget(std::move(target))
        , fDstCopy(std::move(dstCopy))
        , fDstReadBounds(dstReadBounds) {}

RenderPassTask::~RenderPassTask() = default;

Task::Status RenderPassTask::prepareResources(ResourceProvider* resourceProvider,
                                              ScratchResourceManager* scratchManager,
                                              sk_sp<const RuntimeEffectDictionary> runtimeDict) {
    SkASSERT(fTarget);

    bool instantiated;
    if (scratchManager->pendingReadCount(fTarget.get()) == 0) {
        // TODO(b/389908339, b/338976898): If there are no pending reads on a scratch texture
        // instantiation request, it means that the scratch Device was caught by a
        // Recorder::flushTrackedDevices() event but hasn't actually been restored to its parent. In
        // this case, the eventual read of the surface will be in another Recording and it can't be
        // allocated as a true scratch resource.
        //
        // Without pending reads, DrawTask does not track its lifecycle to return the scratch
        // resource, so we need to match that and instantiate with a regular non-shareable resource.
        instantiated = TextureProxy::InstantiateIfNotLazy(resourceProvider, fTarget.get());
    } else {
        instantiated = TextureProxy::InstantiateIfNotLazy(scratchManager, fTarget.get());
    }
    if (!instantiated) {
        SKIA_LOG_W("Failed to instantiate RenderPassTask target. Will not create renderpass!");
        SKIA_LOG_W("Dimensions are (%d, %d).",
                    fTarget->dimensions().width(), fTarget->dimensions().height());
        return Status::kFail;
    }

    // Assuming one draw pass per renderpasstask for now
    SkASSERT(fDrawPasses.size() == 1);
    for (const auto& drawPass: fDrawPasses) {
        if (!drawPass->prepareResources(resourceProvider, runtimeDict, fRenderPassDesc)) {
            return Status::kFail;
        }
    }

    // Once all internal resources have been prepared and instantiated, reclaim any pending returns
    // from the scratch manager, since at the equivalent point in the task graph's addCommands()
    // phase, the renderpass will have sampled from any scratch textures and their contents no
    // longer have to be preserved.
    scratchManager->notifyResourcesConsumed();
    return Status::kSuccess;
}

Task::Status RenderPassTask::addCommands(Context* context,
                                         CommandBuffer* commandBuffer,
                                         ReplayTargetData replayData) {
    // TBD: Expose the surfaces that will need to be attached within the renderpass?

    // Instantiate the target
    SkASSERT(fTarget && fTarget->isInstantiated());
    SkASSERT(!fDstCopy || fDstCopy->isInstantiated());

    // Assuming one draw pass per renderpasstask for now
    SkASSERT(fDrawPasses.size() == 1);
    const auto& drawBounds = fDrawPasses[0]->bounds();

    // Only apply the replay translation and clip if we're drawing to the final replay target.
    SkIVector replayTranslation = {0, 0};
    SkIRect replayClip = SkIRect::MakeEmpty();
    if (fTarget->texture() == replayData.fTarget) {
        replayTranslation = replayData.fTranslation;
        replayClip = replayData.fClip;
    }

    // We don't instantiate the MSAA or DS attachments in prepareResources because we want to use
    // the discardable attachments from the Context.
    ResourceProvider* resourceProvider = context->priv().resourceProvider();
    sk_sp<Texture> colorAttachment;
    sk_sp<Texture> resolveAttachment;
    SkIPoint resolveOffset = SkIPoint::Make(0, 0);
    if (fRenderPassDesc.fColorResolveAttachment.fFormat != TextureFormat::kUnsupported) {
        // We always make color msaa attachments shareable. Between any render pass we discard
        // the values of the MSAA texture. Thus it is safe to be used by multiple different render
        // passes without worry of stomping on each other's data. CommandBuffer::addRenderPass is
        // responsible for loading this attachment with the resolve target's original contents.
        TextureInfo colorInfo = context->priv().caps()->getDefaultAttachmentTextureInfo(
                fRenderPassDesc.fColorAttachment, fTarget->isProtected(), Discardable::kYes);

        SkISize msaaSize;
        std::tie(msaaSize, resolveOffset) =
                get_msaa_size_and_resolve_offset(fTarget->dimensions(),
                                                 drawBounds.makeOffset(replayTranslation),
                                                 *context->priv().caps(),
                                                 fRenderPassDesc.fColorAttachment.fLoadOp);
        colorAttachment = resourceProvider->findOrCreateShareableTexture(
                msaaSize, colorInfo, "DiscardableMSAAAttachment");
        if (!colorAttachment) {
            SKIA_LOG_W("Could not get Color attachment for RenderPassTask");
            return Status::kFail;
        }
        resolveAttachment = fTarget->refTexture();
    } else {
        colorAttachment = fTarget->refTexture();
    }

    sk_sp<Texture> depthStencilAttachment;
    if (fRenderPassDesc.fDepthStencilAttachment.fFormat != TextureFormat::kUnsupported) {
        // We always make depth and stencil attachments shareable. Between any render pass the
        // values are reset. Thus it is safe to be used by multiple different render passes without
        // worry of stomping on each other's data.
        TextureInfo dsInfo = context->priv().caps()->getDefaultAttachmentTextureInfo(
                fRenderPassDesc.fDepthStencilAttachment, fTarget->isProtected(), Discardable::kYes);
        SkISize dimensions = context->priv().caps()->getDepthAttachmentDimensions(
                colorAttachment->textureInfo(), colorAttachment->dimensions());

        depthStencilAttachment = resourceProvider->findOrCreateShareableTexture(
                dimensions, dsInfo, "DepthStencilAttachment");
        if (!depthStencilAttachment) {
            SKIA_LOG_W("Could not get DepthStencil attachment for RenderPassTask");
            return Status::kFail;
        }
    }

    // The clip set here will intersect with the render target bounds, and then any scissor set
    // during this render pass. If there is no intersection between the clip and the render target
    // bounds, we can skip this entire render pass.
    // Note: if the MSAA texture is allocated smaller than the target texture, we need to apply an
    // additional translation (-resolveOffset) so that the draws' bounds' top left corner
    // will be at (0, 0) on the MSAA texture
    const SkIRect renderTargetBounds = SkIRect::MakeSize(colorAttachment->dimensions());
    if (!commandBuffer->setReplayTranslationAndClip(
                replayTranslation - resolveOffset, replayClip, renderTargetBounds)) {
        return Status::kSuccess;
    }

    // TODO(b/313629288) we always pass in the render target's dimensions as the viewport here.
    // Using the dimensions of the logical device that we're drawing to could reduce flakiness in
    // rendering.
    if (commandBuffer->addRenderPass(fRenderPassDesc,
                                     std::move(colorAttachment),
                                     std::move(resolveAttachment),
                                     std::move(depthStencilAttachment),
                                     fDstCopy ? fDstCopy->texture() : nullptr,
                                     fDstReadBounds,
                                     resolveOffset,
                                     fTarget->dimensions(),
                                     fDrawPasses)) {
        return Status::kSuccess;
    } else {
        return Status::kFail;
    }
}

bool RenderPassTask::visitPipelines(const std::function<bool(const GraphicsPipeline*)>& visitor) {
    for (const std::unique_ptr<DrawPass>& pass : fDrawPasses) {
        for (const sk_sp<GraphicsPipeline>& pipeline : pass->pipelines()) {
            if (!visitor(pipeline.get())) {
                return false;
            }
        }
    }

    return true;
}

bool RenderPassTask::visitProxies(const std::function<bool(const TextureProxy*)>& visitor,
                                                           bool readsOnly) {
    for (const std::unique_ptr<DrawPass>& pass : fDrawPasses) {
        for (const sk_sp<TextureProxy>& proxy : pass->sampledTextures()) {
            if (!visitor(proxy.get())) {
                return false;
            }
        }

        if (fDstCopy && !visitor(fDstCopy.get())) {
            return false;
        }

        // Skip visiting the target if we're only visiting read textures
        if (!readsOnly && fTarget && !visitor(fTarget.get())) {
            return false;
        }
    }

    return true;
}

} // namespace skgpu::graphite
