• 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 #ifndef skgpu_DrawPass_DEFINED
9 #define skgpu_DrawPass_DEFINED
10 
11 #include "experimental/graphite/src/DrawTypes.h"
12 #include "experimental/graphite/src/GraphicsPipelineDesc.h"
13 #include "experimental/graphite/src/ResourceTypes.h"
14 #include "include/core/SkColor.h"
15 #include "include/core/SkRect.h"
16 #include "include/core/SkRefCnt.h"
17 #include "src/core/SkTBlockList.h"
18 
19 #include <memory>
20 
21 namespace skgpu {
22 
23 class BoundsManager;
24 class CommandBuffer;
25 class DrawList;
26 class Recorder;
27 struct RenderPassDesc;
28 class ResourceProvider;
29 class TextureProxy;
30 enum class UniformSlot;
31 
32 /**
33  * DrawPass is analogous to a subpass, storing the drawing operations in the order they are stored
34  * in the eventual command buffer, as well as the surface proxy the operations are intended for.
35  * DrawPasses are grouped into a RenderPassTask for execution within a single render pass if the
36  * subpasses are compatible with each other.
37  *
38  * Unlike DrawList, DrawPasses are immutable and represent as closely as possible what will be
39  * stored in the command buffer while being flexible as to how the pass is incorporated. Depending
40  * on the backend, it may even be able to write accumulated vertex and uniform data directly to
41  * mapped GPU memory, although that is the extent of the CPU->GPU work they perform before they are
42  * executed by a RenderPassTask.
43  */
44 class DrawPass {
45 public:
46     ~DrawPass();
47 
48     // TODO: Replace SDC with the SDC's surface proxy view
49     static std::unique_ptr<DrawPass> Make(Recorder*,
50                                           std::unique_ptr<DrawList>,
51                                           sk_sp<TextureProxy>,
52                                           std::pair<LoadOp, StoreOp>,
53                                           std::array<float, 4> clearColor,
54                                           const BoundsManager* occlusionCuller);
55 
56     // Defined relative to the top-left corner of the surface the DrawPass renders to, and is
57     // contained within its dimensions.
bounds()58     const SkIRect&      bounds() const { return fBounds;       }
target()59     TextureProxy* target() const { return fTarget.get(); }
ops()60     std::pair<LoadOp, StoreOp> ops() const { return fOps; }
clearColor()61     std::array<float, 4> clearColor() const { return fClearColor; }
62 
requiresDstTexture()63     bool requiresDstTexture() const { return false;            }
requiresMSAA()64     bool requiresMSAA()       const { return fRequiresMSAA;    }
65 
depthStencilFlags()66     Mask<DepthStencilFlags> depthStencilFlags() const { return fDepthStencilFlags; }
67 
vertexBufferSize()68     size_t vertexBufferSize()  const { return 0; }
uniformBufferSize()69     size_t uniformBufferSize() const { return 0; }
70 
71     // TODO: Real return types, but it seems useful for DrawPass to report these as sets so that
72     // task execution can compile necessary programs and track resources within a render pass.
73     // Maybe these won't need to be exposed and RenderPassTask can do it per command as needed when
74     // it iterates over the DrawPass contents.
samplers()75     void samplers() const {}
programs()76     void programs() const {}
77 
78     // Transform this DrawPass into commands issued to the CommandBuffer. Assumes that the buffer
79     // has already begun a correctly configured render pass matching this pass's target.
80     void addCommands(ResourceProvider*, CommandBuffer*, const RenderPassDesc&) const;
81 
82 private:
83     class SortKey;
84     class Drawer;
85 
86     struct BindGraphicsPipeline {
87         // Points to a GraphicsPipelineDesc in DrawPass's fPipelineDescs array. It will also
88         // index into a parallel array of full GraphicsPipelines when commands are added to the CB.
89         uint32_t fPipelineIndex;
90     };
91     struct BindUniformBuffer {
92         BindBufferInfo fInfo;
93         UniformSlot fSlot;
94     };
95     struct BindDrawBuffers {
96         BindBufferInfo fVertices;
97         BindBufferInfo fInstances;
98         BindBufferInfo fIndices;
99     };
100     struct Draw {
101         PrimitiveType fType;
102         uint32_t fBaseVertex;
103         uint32_t fVertexCount;
104     };
105     struct DrawIndexed {
106         PrimitiveType fType;
107         uint32_t fBaseIndex;
108         uint32_t fIndexCount;
109         uint32_t fBaseVertex;
110     };
111     struct DrawInstanced {
112         PrimitiveType fType;
113         uint32_t fBaseVertex;
114         uint32_t fVertexCount;
115         uint32_t fBaseInstance;
116         uint32_t fInstanceCount;
117     };
118     struct DrawIndexedInstanced {
119         PrimitiveType fType;
120         uint32_t fBaseIndex;
121         uint32_t fIndexCount;
122         uint32_t fBaseVertex;
123         uint32_t fBaseInstance;
124         uint32_t fInstanceCount;
125     };
126     struct SetScissor {
127         SkIRect fScissor;
128     };
129 
130     // TODO: BindSampler
131 
132     enum class CommandType {
133         kBindGraphicsPipeline,
134         kBindUniformBuffer,
135         kBindDrawBuffers,
136         kDraw,
137         kDrawIndexed,
138         kDrawInstanced,
139         kDrawIndexedInstanced,
140         kSetScissor,
141         // kBindSampler
142     };
143     // TODO: The goal is keep all command data in line, vs. type + void* to another data array, but
144     // the current union is memory inefficient. It would be better to have a byte buffer with per
145     // type advances, but then we need to work out alignment etc. so that will be easier to add
146     // once we have something up and running.
147     struct Command {
148         CommandType fType;
149         union {
150             BindGraphicsPipeline fBindGraphicsPipeline;
151             BindUniformBuffer    fBindUniformBuffer;
152             BindDrawBuffers      fBindDrawBuffers;
153             Draw                 fDraw;
154             DrawIndexed          fDrawIndexed;
155             DrawInstanced        fDrawInstanced;
156             DrawIndexedInstanced fDrawIndexedInstanced;
157             SetScissor           fSetScissor;
158         };
159 
CommandCommand160         explicit Command(BindGraphicsPipeline d)
161                 : fType(CommandType::kBindGraphicsPipeline), fBindGraphicsPipeline(d) {}
CommandCommand162         explicit Command(BindUniformBuffer d)
163                 : fType(CommandType::kBindUniformBuffer), fBindUniformBuffer(d) {}
CommandCommand164         explicit Command(BindDrawBuffers d)
165                 : fType(CommandType::kBindDrawBuffers), fBindDrawBuffers(d) {}
CommandCommand166         explicit Command(Draw d)
167                 : fType(CommandType::kDraw), fDraw(d) {}
CommandCommand168         explicit Command(DrawIndexed d)
169                 : fType(CommandType::kDrawIndexed), fDrawIndexed(d) {}
CommandCommand170         explicit Command(DrawInstanced d)
171                 : fType(CommandType::kDrawInstanced), fDrawInstanced(d) {}
CommandCommand172         explicit Command(DrawIndexedInstanced d)
173                 : fType(CommandType::kDrawIndexedInstanced), fDrawIndexedInstanced(d) {}
CommandCommand174         explicit Command(SetScissor d)
175                 : fType(CommandType::kSetScissor), fSetScissor(d) {}
176     };
177     // Not strictly necessary, but keeping Command trivially destructible means the command list
178     // can be cleaned up efficiently once it's converted to a command buffer.
179     static_assert(std::is_trivially_destructible<Command>::value);
180 
181     DrawPass(sk_sp<TextureProxy> target,
182              std::pair<LoadOp, StoreOp> ops,
183              std::array<float, 4> clearColor,
184              int renderStepCount);
185 
186     SkTBlockList<Command, 32> fCommands;
187     // The pipelines are referenced by index in BindGraphicsPipeline, but that will index into a
188     // an array of actual GraphicsPipelines. fPipelineDescs only needs to accumulate encountered
189     // GraphicsPipelineDescs and provide stable pointers, hence SkTBlockList.
190     SkTBlockList<GraphicsPipelineDesc, 32> fPipelineDescs;
191 
192     sk_sp<TextureProxy> fTarget;
193     SkIRect             fBounds;
194 
195     std::pair<LoadOp, StoreOp> fOps;
196     std::array<float, 4>       fClearColor;
197 
198     Mask<DepthStencilFlags> fDepthStencilFlags = DepthStencilFlags::kNone;
199     bool                    fRequiresMSAA = false;
200 };
201 
202 } // namespace skgpu
203 
204 #endif // skgpu_DrawPass_DEFINED
205