• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/gpu/graphite/task/RenderPassTask.h"
9 
10 #include "src/gpu/graphite/Caps.h"
11 #include "src/gpu/graphite/CommandBuffer.h"
12 #include "src/gpu/graphite/ContextPriv.h"
13 #include "src/gpu/graphite/DrawPass.h"
14 #include "src/gpu/graphite/Log.h"
15 #include "src/gpu/graphite/ResourceProvider.h"
16 #include "src/gpu/graphite/ScratchResourceManager.h"
17 #include "src/gpu/graphite/Texture.h"
18 #include "src/gpu/graphite/TextureProxy.h"
19 
20 namespace skgpu::graphite {
21 
Make(DrawPassList passes,const RenderPassDesc & desc,sk_sp<TextureProxy> target)22 sk_sp<RenderPassTask> RenderPassTask::Make(DrawPassList passes,
23                                            const RenderPassDesc& desc,
24                                            sk_sp<TextureProxy> target) {
25     // For now we have one DrawPass per RenderPassTask
26     SkASSERT(passes.size() == 1);
27     if (!target) {
28         return nullptr;
29     }
30 
31     if (desc.fColorAttachment.fTextureInfo.isValid()) {
32         // The color attachment's samples count must ether match the render pass's samples count
33         // or be 1 (when multisampled render to single sampled is used).
34         SkASSERT(desc.fSampleCount == desc.fColorAttachment.fTextureInfo.numSamples() ||
35                  1 == desc.fColorAttachment.fTextureInfo.numSamples());
36     }
37 
38     if (desc.fDepthStencilAttachment.fTextureInfo.isValid()) {
39         SkASSERT(desc.fSampleCount == desc.fDepthStencilAttachment.fTextureInfo.numSamples());
40     }
41 
42     return sk_sp<RenderPassTask>(new RenderPassTask(std::move(passes), desc, target));
43 }
44 
RenderPassTask(DrawPassList passes,const RenderPassDesc & desc,sk_sp<TextureProxy> target)45 RenderPassTask::RenderPassTask(DrawPassList passes,
46                                const RenderPassDesc& desc,
47                                sk_sp<TextureProxy> target)
48         : fDrawPasses(std::move(passes)), fRenderPassDesc(desc), fTarget(std::move(target)) {}
49 
50 RenderPassTask::~RenderPassTask() = default;
51 
prepareResources(ResourceProvider * resourceProvider,ScratchResourceManager * scratchManager,const RuntimeEffectDictionary * runtimeDict)52 Task::Status RenderPassTask::prepareResources(ResourceProvider* resourceProvider,
53                                               ScratchResourceManager* scratchManager,
54                                               const RuntimeEffectDictionary* runtimeDict) {
55     SkASSERT(fTarget);
56     if (!TextureProxy::InstantiateIfNotLazy(scratchManager, fTarget.get())) {
57         SKGPU_LOG_W("Failed to instantiate RenderPassTask target. Will not create renderpass!");
58         SKGPU_LOG_W("Dimensions are (%d, %d).",
59                     fTarget->dimensions().width(), fTarget->dimensions().height());
60         return Status::kFail;
61     }
62 
63     // Assuming one draw pass per renderpasstask for now
64     SkASSERT(fDrawPasses.size() == 1);
65     for (const auto& drawPass: fDrawPasses) {
66         if (!drawPass->prepareResources(resourceProvider, runtimeDict, fRenderPassDesc)) {
67             return Status::kFail;
68         }
69     }
70 
71     // Once all internal resources have been prepared and instantiated, reclaim any pending returns
72     // from the scratch manager, since at the equivalent point in the task graph's addCommands()
73     // phase, the renderpass will have sampled from any scratch textures and their contents no
74     // longer have to be preserved.
75     scratchManager->notifyResourcesConsumed();
76     return Status::kSuccess;
77 }
78 
addCommands(Context * context,CommandBuffer * commandBuffer,ReplayTargetData replayData)79 Task::Status RenderPassTask::addCommands(Context* context,
80                                          CommandBuffer* commandBuffer,
81                                          ReplayTargetData replayData) {
82     // TBD: Expose the surfaces that will need to be attached within the renderpass?
83 
84     // TODO: for task execution, start the render pass, then iterate passes and
85     // possibly(?) start each subpass, and call DrawPass::addCommands() on the command buffer
86     // provided to the task. Then close the render pass and we should have pixels..
87 
88     // Instantiate the target
89     SkASSERT(fTarget && fTarget->isInstantiated());
90 
91     if (fTarget->texture() == replayData.fTarget) {
92         commandBuffer->setReplayTranslation(replayData.fTranslation);
93     } else {
94         commandBuffer->clearReplayTranslation();
95     }
96 
97     // We don't instantiate the MSAA or DS attachments in prepareResources because we want to use
98     // the discardable attachments from the Context.
99     ResourceProvider* resourceProvider = context->priv().resourceProvider();
100     sk_sp<Texture> colorAttachment;
101     sk_sp<Texture> resolveAttachment;
102     if (fRenderPassDesc.fColorResolveAttachment.fTextureInfo.isValid()) {
103         SkASSERT(fTarget->numSamples() == 1 &&
104                  fRenderPassDesc.fColorAttachment.fTextureInfo.numSamples() > 1);
105         colorAttachment = resourceProvider->findOrCreateDiscardableMSAAAttachment(
106                 fTarget->dimensions(), fRenderPassDesc.fColorAttachment.fTextureInfo);
107         if (!colorAttachment) {
108             SKGPU_LOG_W("Could not get Color attachment for RenderPassTask");
109             return Status::kFail;
110         }
111         resolveAttachment = fTarget->refTexture();
112     } else {
113         colorAttachment = fTarget->refTexture();
114     }
115 
116     sk_sp<Texture> depthStencilAttachment;
117     if (fRenderPassDesc.fDepthStencilAttachment.fTextureInfo.isValid()) {
118         // TODO: ensure this is a scratch/recycled texture
119         SkASSERT(fTarget->isInstantiated());
120         SkISize dimensions = context->priv().caps()->getDepthAttachmentDimensions(
121                 fTarget->texture()->textureInfo(), fTarget->dimensions());
122         depthStencilAttachment = resourceProvider->findOrCreateDepthStencilAttachment(
123                 dimensions, fRenderPassDesc.fDepthStencilAttachment.fTextureInfo);
124         if (!depthStencilAttachment) {
125             SKGPU_LOG_W("Could not get DepthStencil attachment for RenderPassTask");
126             return Status::kFail;
127         }
128     }
129 
130     // TODO(b/313629288) we always pass in the render target's dimensions as the viewport here.
131     // Using the dimensions of the logical device that we're drawing to could reduce flakiness in
132     // rendering.
133     if (commandBuffer->addRenderPass(fRenderPassDesc,
134                                      std::move(colorAttachment),
135                                      std::move(resolveAttachment),
136                                      std::move(depthStencilAttachment),
137                                      SkRect::Make(fTarget->dimensions()),
138                                      fDrawPasses)) {
139         return Status::kSuccess;
140     } else {
141         return Status::kFail;
142     }
143 }
144 
145 } // namespace skgpu::graphite
146