• 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/RenderPassTask.h"
9 
10 #include "src/gpu/graphite/CommandBuffer.h"
11 #include "src/gpu/graphite/ContextPriv.h"
12 #include "src/gpu/graphite/DrawPass.h"
13 #include "src/gpu/graphite/Log.h"
14 #include "src/gpu/graphite/ResourceProvider.h"
15 #include "src/gpu/graphite/Texture.h"
16 #include "src/gpu/graphite/TextureProxy.h"
17 
18 namespace skgpu::graphite {
19 
Make(std::vector<std::unique_ptr<DrawPass>> passes,const RenderPassDesc & desc,sk_sp<TextureProxy> target)20 sk_sp<RenderPassTask> RenderPassTask::Make(std::vector<std::unique_ptr<DrawPass>> passes,
21                                            const RenderPassDesc& desc,
22                                            sk_sp<TextureProxy> target) {
23     // For now we have one DrawPass per RenderPassTask
24     SkASSERT(passes.size() == 1);
25     if (!target) {
26         return nullptr;
27     }
28 
29     return sk_sp<RenderPassTask>(new RenderPassTask(std::move(passes), desc, target));
30 }
31 
RenderPassTask(std::vector<std::unique_ptr<DrawPass>> passes,const RenderPassDesc & desc,sk_sp<TextureProxy> target)32 RenderPassTask::RenderPassTask(std::vector<std::unique_ptr<DrawPass>> passes,
33                                const RenderPassDesc& desc,
34                                sk_sp<TextureProxy> target)
35         : fDrawPasses(std::move(passes))
36         , fRenderPassDesc(desc)
37         , fTarget(std::move(target)) {}
38 
39 RenderPassTask::~RenderPassTask() = default;
40 
prepareResources(ResourceProvider * resourceProvider,const RuntimeEffectDictionary * runtimeDict)41 bool RenderPassTask::prepareResources(ResourceProvider* resourceProvider,
42                                       const RuntimeEffectDictionary* runtimeDict) {
43     SkASSERT(fTarget);
44     if (!TextureProxy::InstantiateIfNotLazy(resourceProvider, fTarget.get())) {
45         SKGPU_LOG_W("Failed to instantiate RenderPassTask target. Will not create renderpass!");
46         SKGPU_LOG_W("Dimensions are (%d, %d).",
47                     fTarget->dimensions().width(), fTarget->dimensions().height());
48         return false;
49     }
50 
51     // Assuming one draw pass per renderpasstask for now
52     SkASSERT(fDrawPasses.size() == 1);
53     for (const auto& drawPass: fDrawPasses) {
54         if (!drawPass->prepareResources(resourceProvider, runtimeDict, fRenderPassDesc)) {
55             return false;
56         }
57     }
58     return true;
59 }
60 
addCommands(Context * context,CommandBuffer * commandBuffer,ReplayTargetData replayData)61 bool RenderPassTask::addCommands(Context* context,
62                                  CommandBuffer* commandBuffer,
63                                  ReplayTargetData replayData) {
64     // TBD: Expose the surfaces that will need to be attached within the renderpass?
65 
66     // TODO: for task execution, start the render pass, then iterate passes and
67     // possibly(?) start each subpass, and call DrawPass::addCommands() on the command buffer
68     // provided to the task. Then close the render pass and we should have pixels..
69 
70     // Instantiate the target
71     SkASSERT(fTarget && fTarget->isInstantiated());
72 
73     if (fTarget->texture() == replayData.fTarget) {
74         commandBuffer->setReplayTranslation(replayData.fTranslation);
75     } else {
76         commandBuffer->clearReplayTranslation();
77     }
78 
79     // We don't instantiate the MSAA or DS attachments in prepareResources because we want to use
80     // the discardable attachments from the Context.
81     ResourceProvider* resourceProvider = context->priv().resourceProvider();
82     sk_sp<Texture> colorAttachment;
83     sk_sp<Texture> resolveAttachment;
84     if (fRenderPassDesc.fColorResolveAttachment.fTextureInfo.isValid()) {
85         SkASSERT(fTarget->numSamples() == 1 &&
86                  fRenderPassDesc.fColorAttachment.fTextureInfo.numSamples() > 1);
87         colorAttachment = resourceProvider->findOrCreateDiscardableMSAAAttachment(
88                 fTarget->dimensions(), fRenderPassDesc.fColorAttachment.fTextureInfo);
89         if (!colorAttachment) {
90             SKGPU_LOG_W("Could not get Color attachment for RenderPassTask");
91             return false;
92         }
93         resolveAttachment = fTarget->refTexture();
94     } else {
95         colorAttachment = fTarget->refTexture();
96     }
97 
98     sk_sp<Texture> depthStencilAttachment;
99     if (fRenderPassDesc.fDepthStencilAttachment.fTextureInfo.isValid()) {
100         // TODO: ensure this is a scratch/recycled texture
101         depthStencilAttachment = resourceProvider->findOrCreateDepthStencilAttachment(
102                 fTarget->dimensions(), fRenderPassDesc.fDepthStencilAttachment.fTextureInfo);
103         if (!depthStencilAttachment) {
104             SKGPU_LOG_W("Could not get DepthStencil attachment for RenderPassTask");
105             return false;
106         }
107     }
108 
109     // TODO: We need to handle the case where we need to load the single sampled target's data into
110     // the discardable MSAA Surface. On different backends this will be done in various ways. On
111     // Metal we can simply insert a draw at the start of the render pass sampling the single target
112     // texture as normal. In Vulkan, we need to create a whole new subpass at the start, use the
113     // single sample resolve as an input attachment in that subpass, and then do a draw. The big
114     // thing with Vulkan is that this input attachment and subpass means we also need to update
115     // the fRenderPassDesc here.
116     return commandBuffer->addRenderPass(fRenderPassDesc,
117                                         std::move(colorAttachment),
118                                         std::move(resolveAttachment),
119                                         std::move(depthStencilAttachment),
120                                         SkRect::Make(fTarget->dimensions()),
121                                         fDrawPasses);
122 }
123 
124 } // namespace skgpu::graphite
125