xref: /aosp_15_r20/external/skia/src/gpu/graphite/task/RenderPassTask.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2021 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/task/RenderPassTask.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Caps.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/CommandBuffer.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ContextPriv.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/DrawPass.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Log.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ResourceProvider.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ScratchResourceManager.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Texture.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/TextureProxy.h"
19*c8dee2aaSAndroid Build Coastguard Worker 
20*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
21*c8dee2aaSAndroid Build Coastguard Worker 
Make(DrawPassList passes,const RenderPassDesc & desc,sk_sp<TextureProxy> target,sk_sp<TextureProxy> dstCopy,SkIRect dstCopyBounds)22*c8dee2aaSAndroid Build Coastguard Worker sk_sp<RenderPassTask> RenderPassTask::Make(DrawPassList passes,
23*c8dee2aaSAndroid Build Coastguard Worker                                            const RenderPassDesc& desc,
24*c8dee2aaSAndroid Build Coastguard Worker                                            sk_sp<TextureProxy> target,
25*c8dee2aaSAndroid Build Coastguard Worker                                            sk_sp<TextureProxy> dstCopy,
26*c8dee2aaSAndroid Build Coastguard Worker                                            SkIRect dstCopyBounds) {
27*c8dee2aaSAndroid Build Coastguard Worker     // For now we have one DrawPass per RenderPassTask
28*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(passes.size() == 1);
29*c8dee2aaSAndroid Build Coastguard Worker     // We should only have dst copy bounds if we have a dst copy texture, and the texture should be
30*c8dee2aaSAndroid Build Coastguard Worker     // big enough to cover the copy bounds that will be sampled.
31*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(dstCopyBounds.isEmpty() == !dstCopy);
32*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!dstCopy || (dstCopy->dimensions().width() >= dstCopyBounds.width() &&
33*c8dee2aaSAndroid Build Coastguard Worker                           dstCopy->dimensions().height() >= dstCopyBounds.height()));
34*c8dee2aaSAndroid Build Coastguard Worker     if (!target) {
35*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
36*c8dee2aaSAndroid Build Coastguard Worker     }
37*c8dee2aaSAndroid Build Coastguard Worker 
38*c8dee2aaSAndroid Build Coastguard Worker     if (desc.fColorAttachment.fTextureInfo.isValid()) {
39*c8dee2aaSAndroid Build Coastguard Worker         // The color attachment's samples count must ether match the render pass's samples count
40*c8dee2aaSAndroid Build Coastguard Worker         // or be 1 (when multisampled render to single sampled is used).
41*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(desc.fSampleCount == desc.fColorAttachment.fTextureInfo.numSamples() ||
42*c8dee2aaSAndroid Build Coastguard Worker                  1 == desc.fColorAttachment.fTextureInfo.numSamples());
43*c8dee2aaSAndroid Build Coastguard Worker     }
44*c8dee2aaSAndroid Build Coastguard Worker 
45*c8dee2aaSAndroid Build Coastguard Worker     if (desc.fDepthStencilAttachment.fTextureInfo.isValid()) {
46*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(desc.fSampleCount == desc.fDepthStencilAttachment.fTextureInfo.numSamples());
47*c8dee2aaSAndroid Build Coastguard Worker     }
48*c8dee2aaSAndroid Build Coastguard Worker 
49*c8dee2aaSAndroid Build Coastguard Worker     return sk_sp<RenderPassTask>(new RenderPassTask(std::move(passes),
50*c8dee2aaSAndroid Build Coastguard Worker                                                     desc,
51*c8dee2aaSAndroid Build Coastguard Worker                                                     std::move(target),
52*c8dee2aaSAndroid Build Coastguard Worker                                                     std::move(dstCopy),
53*c8dee2aaSAndroid Build Coastguard Worker                                                     dstCopyBounds));
54*c8dee2aaSAndroid Build Coastguard Worker }
55*c8dee2aaSAndroid Build Coastguard Worker 
RenderPassTask(DrawPassList passes,const RenderPassDesc & desc,sk_sp<TextureProxy> target,sk_sp<TextureProxy> dstCopy,SkIRect dstCopyBounds)56*c8dee2aaSAndroid Build Coastguard Worker RenderPassTask::RenderPassTask(DrawPassList passes,
57*c8dee2aaSAndroid Build Coastguard Worker                                const RenderPassDesc& desc,
58*c8dee2aaSAndroid Build Coastguard Worker                                sk_sp<TextureProxy> target,
59*c8dee2aaSAndroid Build Coastguard Worker                                sk_sp<TextureProxy> dstCopy,
60*c8dee2aaSAndroid Build Coastguard Worker                                SkIRect dstCopyBounds)
61*c8dee2aaSAndroid Build Coastguard Worker         : fDrawPasses(std::move(passes))
62*c8dee2aaSAndroid Build Coastguard Worker         , fRenderPassDesc(desc)
63*c8dee2aaSAndroid Build Coastguard Worker         , fTarget(std::move(target))
64*c8dee2aaSAndroid Build Coastguard Worker         , fDstCopy(std::move(dstCopy))
65*c8dee2aaSAndroid Build Coastguard Worker         , fDstCopyBounds(dstCopyBounds) {}
66*c8dee2aaSAndroid Build Coastguard Worker 
67*c8dee2aaSAndroid Build Coastguard Worker RenderPassTask::~RenderPassTask() = default;
68*c8dee2aaSAndroid Build Coastguard Worker 
prepareResources(ResourceProvider * resourceProvider,ScratchResourceManager * scratchManager,const RuntimeEffectDictionary * runtimeDict)69*c8dee2aaSAndroid Build Coastguard Worker Task::Status RenderPassTask::prepareResources(ResourceProvider* resourceProvider,
70*c8dee2aaSAndroid Build Coastguard Worker                                               ScratchResourceManager* scratchManager,
71*c8dee2aaSAndroid Build Coastguard Worker                                               const RuntimeEffectDictionary* runtimeDict) {
72*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fTarget);
73*c8dee2aaSAndroid Build Coastguard Worker     if (!TextureProxy::InstantiateIfNotLazy(scratchManager, fTarget.get())) {
74*c8dee2aaSAndroid Build Coastguard Worker         SKGPU_LOG_W("Failed to instantiate RenderPassTask target. Will not create renderpass!");
75*c8dee2aaSAndroid Build Coastguard Worker         SKGPU_LOG_W("Dimensions are (%d, %d).",
76*c8dee2aaSAndroid Build Coastguard Worker                     fTarget->dimensions().width(), fTarget->dimensions().height());
77*c8dee2aaSAndroid Build Coastguard Worker         return Status::kFail;
78*c8dee2aaSAndroid Build Coastguard Worker     }
79*c8dee2aaSAndroid Build Coastguard Worker 
80*c8dee2aaSAndroid Build Coastguard Worker     // Assuming one draw pass per renderpasstask for now
81*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fDrawPasses.size() == 1);
82*c8dee2aaSAndroid Build Coastguard Worker     for (const auto& drawPass: fDrawPasses) {
83*c8dee2aaSAndroid Build Coastguard Worker         if (!drawPass->prepareResources(resourceProvider, runtimeDict, fRenderPassDesc)) {
84*c8dee2aaSAndroid Build Coastguard Worker             return Status::kFail;
85*c8dee2aaSAndroid Build Coastguard Worker         }
86*c8dee2aaSAndroid Build Coastguard Worker     }
87*c8dee2aaSAndroid Build Coastguard Worker 
88*c8dee2aaSAndroid Build Coastguard Worker     // Once all internal resources have been prepared and instantiated, reclaim any pending returns
89*c8dee2aaSAndroid Build Coastguard Worker     // from the scratch manager, since at the equivalent point in the task graph's addCommands()
90*c8dee2aaSAndroid Build Coastguard Worker     // phase, the renderpass will have sampled from any scratch textures and their contents no
91*c8dee2aaSAndroid Build Coastguard Worker     // longer have to be preserved.
92*c8dee2aaSAndroid Build Coastguard Worker     scratchManager->notifyResourcesConsumed();
93*c8dee2aaSAndroid Build Coastguard Worker     return Status::kSuccess;
94*c8dee2aaSAndroid Build Coastguard Worker }
95*c8dee2aaSAndroid Build Coastguard Worker 
addCommands(Context * context,CommandBuffer * commandBuffer,ReplayTargetData replayData)96*c8dee2aaSAndroid Build Coastguard Worker Task::Status RenderPassTask::addCommands(Context* context,
97*c8dee2aaSAndroid Build Coastguard Worker                                          CommandBuffer* commandBuffer,
98*c8dee2aaSAndroid Build Coastguard Worker                                          ReplayTargetData replayData) {
99*c8dee2aaSAndroid Build Coastguard Worker     // TBD: Expose the surfaces that will need to be attached within the renderpass?
100*c8dee2aaSAndroid Build Coastguard Worker 
101*c8dee2aaSAndroid Build Coastguard Worker     // Instantiate the target
102*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fTarget && fTarget->isInstantiated());
103*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!fDstCopy || fDstCopy->isInstantiated());
104*c8dee2aaSAndroid Build Coastguard Worker 
105*c8dee2aaSAndroid Build Coastguard Worker     // Set any replay translation and clip, as needed.
106*c8dee2aaSAndroid Build Coastguard Worker     // The clip set here will intersect with any scissor set during this render pass.
107*c8dee2aaSAndroid Build Coastguard Worker     const SkIRect renderTargetBounds = SkIRect::MakeSize(fTarget->dimensions());
108*c8dee2aaSAndroid Build Coastguard Worker     if (fTarget->texture() == replayData.fTarget) {
109*c8dee2aaSAndroid Build Coastguard Worker         // We're drawing to the final replay target, so apply replay translation and clip.
110*c8dee2aaSAndroid Build Coastguard Worker         if (replayData.fClip.isEmpty()) {
111*c8dee2aaSAndroid Build Coastguard Worker             // If no replay clip is defined, default to the render target bounds.
112*c8dee2aaSAndroid Build Coastguard Worker             commandBuffer->setReplayTranslationAndClip(replayData.fTranslation,
113*c8dee2aaSAndroid Build Coastguard Worker                                                        renderTargetBounds);
114*c8dee2aaSAndroid Build Coastguard Worker         } else {
115*c8dee2aaSAndroid Build Coastguard Worker             // If a replay clip is defined, intersect it with the render target bounds.
116*c8dee2aaSAndroid Build Coastguard Worker             // If the intersection is empty, we can skip this entire render pass.
117*c8dee2aaSAndroid Build Coastguard Worker             SkIRect replayClip = replayData.fClip;
118*c8dee2aaSAndroid Build Coastguard Worker             if (!replayClip.intersect(renderTargetBounds)) {
119*c8dee2aaSAndroid Build Coastguard Worker                 return Status::kSuccess;
120*c8dee2aaSAndroid Build Coastguard Worker             }
121*c8dee2aaSAndroid Build Coastguard Worker             commandBuffer->setReplayTranslationAndClip(replayData.fTranslation, replayClip);
122*c8dee2aaSAndroid Build Coastguard Worker         }
123*c8dee2aaSAndroid Build Coastguard Worker     } else {
124*c8dee2aaSAndroid Build Coastguard Worker         // We're not drawing to the final replay target, so don't apply replay translation or clip.
125*c8dee2aaSAndroid Build Coastguard Worker         // In this case as well, the clip we set defaults to the render target bounds.
126*c8dee2aaSAndroid Build Coastguard Worker         commandBuffer->setReplayTranslationAndClip({0, 0}, renderTargetBounds);
127*c8dee2aaSAndroid Build Coastguard Worker     }
128*c8dee2aaSAndroid Build Coastguard Worker 
129*c8dee2aaSAndroid Build Coastguard Worker     // We don't instantiate the MSAA or DS attachments in prepareResources because we want to use
130*c8dee2aaSAndroid Build Coastguard Worker     // the discardable attachments from the Context.
131*c8dee2aaSAndroid Build Coastguard Worker     ResourceProvider* resourceProvider = context->priv().resourceProvider();
132*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<Texture> colorAttachment;
133*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<Texture> resolveAttachment;
134*c8dee2aaSAndroid Build Coastguard Worker     if (fRenderPassDesc.fColorResolveAttachment.fTextureInfo.isValid()) {
135*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fTarget->numSamples() == 1 &&
136*c8dee2aaSAndroid Build Coastguard Worker                  fRenderPassDesc.fColorAttachment.fTextureInfo.numSamples() > 1);
137*c8dee2aaSAndroid Build Coastguard Worker         colorAttachment = resourceProvider->findOrCreateDiscardableMSAAAttachment(
138*c8dee2aaSAndroid Build Coastguard Worker                 fTarget->dimensions(), fRenderPassDesc.fColorAttachment.fTextureInfo);
139*c8dee2aaSAndroid Build Coastguard Worker         if (!colorAttachment) {
140*c8dee2aaSAndroid Build Coastguard Worker             SKGPU_LOG_W("Could not get Color attachment for RenderPassTask");
141*c8dee2aaSAndroid Build Coastguard Worker             return Status::kFail;
142*c8dee2aaSAndroid Build Coastguard Worker         }
143*c8dee2aaSAndroid Build Coastguard Worker         resolveAttachment = fTarget->refTexture();
144*c8dee2aaSAndroid Build Coastguard Worker     } else {
145*c8dee2aaSAndroid Build Coastguard Worker         colorAttachment = fTarget->refTexture();
146*c8dee2aaSAndroid Build Coastguard Worker     }
147*c8dee2aaSAndroid Build Coastguard Worker 
148*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<Texture> depthStencilAttachment;
149*c8dee2aaSAndroid Build Coastguard Worker     if (fRenderPassDesc.fDepthStencilAttachment.fTextureInfo.isValid()) {
150*c8dee2aaSAndroid Build Coastguard Worker         // TODO: ensure this is a scratch/recycled texture
151*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fTarget->isInstantiated());
152*c8dee2aaSAndroid Build Coastguard Worker         SkISize dimensions = context->priv().caps()->getDepthAttachmentDimensions(
153*c8dee2aaSAndroid Build Coastguard Worker                 fTarget->texture()->textureInfo(), fTarget->dimensions());
154*c8dee2aaSAndroid Build Coastguard Worker         depthStencilAttachment = resourceProvider->findOrCreateDepthStencilAttachment(
155*c8dee2aaSAndroid Build Coastguard Worker                 dimensions, fRenderPassDesc.fDepthStencilAttachment.fTextureInfo);
156*c8dee2aaSAndroid Build Coastguard Worker         if (!depthStencilAttachment) {
157*c8dee2aaSAndroid Build Coastguard Worker             SKGPU_LOG_W("Could not get DepthStencil attachment for RenderPassTask");
158*c8dee2aaSAndroid Build Coastguard Worker             return Status::kFail;
159*c8dee2aaSAndroid Build Coastguard Worker         }
160*c8dee2aaSAndroid Build Coastguard Worker     }
161*c8dee2aaSAndroid Build Coastguard Worker 
162*c8dee2aaSAndroid Build Coastguard Worker     // TODO(b/313629288) we always pass in the render target's dimensions as the viewport here.
163*c8dee2aaSAndroid Build Coastguard Worker     // Using the dimensions of the logical device that we're drawing to could reduce flakiness in
164*c8dee2aaSAndroid Build Coastguard Worker     // rendering.
165*c8dee2aaSAndroid Build Coastguard Worker     if (commandBuffer->addRenderPass(fRenderPassDesc,
166*c8dee2aaSAndroid Build Coastguard Worker                                      std::move(colorAttachment),
167*c8dee2aaSAndroid Build Coastguard Worker                                      std::move(resolveAttachment),
168*c8dee2aaSAndroid Build Coastguard Worker                                      std::move(depthStencilAttachment),
169*c8dee2aaSAndroid Build Coastguard Worker                                      fDstCopy ? fDstCopy->texture() : nullptr,
170*c8dee2aaSAndroid Build Coastguard Worker                                      fDstCopyBounds,
171*c8dee2aaSAndroid Build Coastguard Worker                                      fTarget->dimensions(),
172*c8dee2aaSAndroid Build Coastguard Worker                                      fDrawPasses)) {
173*c8dee2aaSAndroid Build Coastguard Worker         return Status::kSuccess;
174*c8dee2aaSAndroid Build Coastguard Worker     } else {
175*c8dee2aaSAndroid Build Coastguard Worker         return Status::kFail;
176*c8dee2aaSAndroid Build Coastguard Worker     }
177*c8dee2aaSAndroid Build Coastguard Worker }
178*c8dee2aaSAndroid Build Coastguard Worker 
179*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
180