blob: cc1d22b9627e89a40ca29e4b1e1f19f44a581ae8 [file] [log] [blame]
bsalomon75398562015-08-17 12:55:38 -07001/*
2 * Copyright 2015 Google Inc.
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
Brian Salomon09d994e2016-12-21 11:14:46 -05008#ifndef GrOpFlushState_DEFINED
9#define GrOpFlushState_DEFINED
bsalomon75398562015-08-17 12:55:38 -070010
Brian Salomonbfd18cd2017-08-09 16:27:09 -040011#include "GrAppliedClip.h"
bsalomon75398562015-08-17 12:55:38 -070012#include "GrBufferAllocPool.h"
Brian Salomon6d4b65e2017-05-03 17:06:09 -040013#include "SkArenaAlloc.h"
Brian Salomon89527432016-12-16 09:52:16 -050014#include "ops/GrMeshDrawOp.h"
bsalomon75398562015-08-17 12:55:38 -070015
Robert Phillips646e4292017-06-13 12:44:56 -040016class GrGpu;
egdaniel9cb63402016-06-23 08:37:05 -070017class GrGpuCommandBuffer;
bsalomon75398562015-08-17 12:55:38 -070018class GrResourceProvider;
19
Brian Salomon742e31d2016-12-07 17:06:19 -050020/** Tracks the state across all the GrOps (really just the GrDrawOps) in a GrOpList flush. */
21class GrOpFlushState {
bsalomon75398562015-08-17 12:55:38 -070022public:
Brian Salomon742e31d2016-12-07 17:06:19 -050023 GrOpFlushState(GrGpu*, GrResourceProvider*);
bsalomon75398562015-08-17 12:55:38 -070024
Brian Salomon742e31d2016-12-07 17:06:19 -050025 ~GrOpFlushState() { this->reset(); }
bsalomon75398562015-08-17 12:55:38 -070026
Brian Salomon742e31d2016-12-07 17:06:19 -050027 /** Inserts an upload to be executed after all ops in the flush prepared their draws but before
28 the draws are executed to the backend 3D API. */
Brian Salomon9afd3712016-12-01 10:59:09 -050029 void addASAPUpload(GrDrawOp::DeferredUploadFn&& upload) {
bsalomon342bfc22016-04-01 06:06:20 -070030 fAsapUploads.emplace_back(std::move(upload));
bsalomon75398562015-08-17 12:55:38 -070031 }
32
Robert Phillips646e4292017-06-13 12:44:56 -040033 const GrCaps& caps() const;
bsalomon75398562015-08-17 12:55:38 -070034 GrResourceProvider* resourceProvider() const { return fResourceProvider; }
35
36 /** Has the token been flushed to the backend 3D API. */
Brian Salomon9afd3712016-12-01 10:59:09 -050037 bool hasDrawBeenFlushed(GrDrawOpUploadToken token) const {
bsalomon342bfc22016-04-01 06:06:20 -070038 return token.fSequenceNumber <= fLastFlushedToken.fSequenceNumber;
39 }
bsalomon75398562015-08-17 12:55:38 -070040
bsalomon342bfc22016-04-01 06:06:20 -070041 /** Issue a token to an operation that is being enqueued. */
Brian Salomon9afd3712016-12-01 10:59:09 -050042 GrDrawOpUploadToken issueDrawToken() {
43 return GrDrawOpUploadToken(++fLastIssuedToken.fSequenceNumber);
bsalomon342bfc22016-04-01 06:06:20 -070044 }
45
46 /** Call every time a draw that was issued a token is flushed */
47 void flushToken() { ++fLastFlushedToken.fSequenceNumber; }
48
49 /** Gets the next draw token that will be issued. */
Brian Salomon9afd3712016-12-01 10:59:09 -050050 GrDrawOpUploadToken nextDrawToken() const {
51 return GrDrawOpUploadToken(fLastIssuedToken.fSequenceNumber + 1);
bsalomon342bfc22016-04-01 06:06:20 -070052 }
bsalomon75398562015-08-17 12:55:38 -070053
54 /** The last token flushed to all the way to the backend API. */
Brian Salomon9afd3712016-12-01 10:59:09 -050055 GrDrawOpUploadToken nextTokenToFlush() const {
56 return GrDrawOpUploadToken(fLastFlushedToken.fSequenceNumber + 1);
bsalomon342bfc22016-04-01 06:06:20 -070057 }
bsalomon75398562015-08-17 12:55:38 -070058
59 void* makeVertexSpace(size_t vertexSize, int vertexCount,
cdalton397536c2016-03-25 12:15:03 -070060 const GrBuffer** buffer, int* startVertex);
61 uint16_t* makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex);
bsalomon75398562015-08-17 12:55:38 -070062
Brian Osman49b7b6f2017-06-20 14:43:58 -040063 void* makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount, int fallbackVertexCount,
64 const GrBuffer** buffer, int* startVertex, int* actualVertexCount);
65 uint16_t* makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
66 const GrBuffer** buffer, int* startIndex,
67 int* actualIndexCount);
68
Brian Salomon742e31d2016-12-07 17:06:19 -050069 /** This is called after each op has a chance to prepare its draws and before the draws are
70 issued. */
bsalomon75398562015-08-17 12:55:38 -070071 void preIssueDraws() {
72 fVertexPool.unmap();
73 fIndexPool.unmap();
74 int uploadCount = fAsapUploads.count();
bsalomon342bfc22016-04-01 06:06:20 -070075
bsalomon75398562015-08-17 12:55:38 -070076 for (int i = 0; i < uploadCount; i++) {
bsalomon342bfc22016-04-01 06:06:20 -070077 this->doUpload(fAsapUploads[i]);
bsalomon75398562015-08-17 12:55:38 -070078 }
79 fAsapUploads.reset();
80 }
81
Brian Salomon9bada542017-06-12 12:09:30 -040082 void doUpload(GrDrawOp::DeferredUploadFn&);
bsalomon342bfc22016-04-01 06:06:20 -070083
bsalomon75398562015-08-17 12:55:38 -070084 void putBackIndices(size_t indices) { fIndexPool.putBack(indices * sizeof(uint16_t)); }
85
86 void putBackVertexSpace(size_t sizeInBytes) { fVertexPool.putBack(sizeInBytes); }
87
egdaniel9cb63402016-06-23 08:37:05 -070088 GrGpuCommandBuffer* commandBuffer() { return fCommandBuffer; }
89 void setCommandBuffer(GrGpuCommandBuffer* buffer) { fCommandBuffer = buffer; }
90
bsalomon75398562015-08-17 12:55:38 -070091 GrGpu* gpu() { return fGpu; }
92
joshualittf6d259b2015-10-02 11:27:14 -070093 void reset() {
94 fVertexPool.reset();
95 fIndexPool.reset();
Brian Salomon6d4b65e2017-05-03 17:06:09 -040096 fPipelines.reset();
joshualittf6d259b2015-10-02 11:27:14 -070097 }
98
Brian Salomon54d212e2017-03-21 14:22:38 -040099 /** Additional data required on a per-op basis when executing GrDrawOps. */
100 struct DrawOpArgs {
Robert Phillips2890fbf2017-07-26 15:48:41 -0400101 GrRenderTarget* renderTarget() const { return fProxy->priv().peekRenderTarget(); }
102
Robert Phillips19e51dc2017-08-09 09:30:51 -0400103 // TODO: do we still need the dst proxy here?
Brian Salomonbfd18cd2017-08-09 16:27:09 -0400104 GrRenderTargetProxy* fProxy;
105 GrAppliedClip* fAppliedClip;
Robert Phillipsbb581ce2017-05-29 15:05:15 -0400106 GrXferProcessor::DstProxy fDstProxy;
Brian Salomon54d212e2017-03-21 14:22:38 -0400107 };
108
109 void setDrawOpArgs(DrawOpArgs* opArgs) { fOpArgs = opArgs; }
110
111 const DrawOpArgs& drawOpArgs() const {
112 SkASSERT(fOpArgs);
113 return *fOpArgs;
114 }
115
Brian Salomonbfd18cd2017-08-09 16:27:09 -0400116 GrAppliedClip detachAppliedClip() {
117 SkASSERT(fOpArgs);
118 return fOpArgs->fAppliedClip ? std::move(*fOpArgs->fAppliedClip) : GrAppliedClip();
119 }
120
Brian Salomon6d4b65e2017-05-03 17:06:09 -0400121 template <typename... Args>
Brian Salomon91326c32017-08-09 16:02:19 -0400122 GrPipeline* allocPipeline(Args&&... args) {
Brian Salomon6d4b65e2017-05-03 17:06:09 -0400123 return fPipelines.make<GrPipeline>(std::forward<Args>(args)...);
124 }
125
bsalomon75398562015-08-17 12:55:38 -0700126private:
Brian Salomon6d4b65e2017-05-03 17:06:09 -0400127 GrGpu* fGpu;
128 GrResourceProvider* fResourceProvider;
129 GrGpuCommandBuffer* fCommandBuffer;
130 GrVertexBufferAllocPool fVertexPool;
131 GrIndexBufferAllocPool fIndexPool;
132 SkSTArray<4, GrDrawOp::DeferredUploadFn> fAsapUploads;
133 GrDrawOpUploadToken fLastIssuedToken;
134 GrDrawOpUploadToken fLastFlushedToken;
135 DrawOpArgs* fOpArgs;
136 SkArenaAlloc fPipelines{sizeof(GrPipeline) * 100};
bsalomon75398562015-08-17 12:55:38 -0700137};
138
139/**
Brian Salomon742e31d2016-12-07 17:06:19 -0500140 * A word about uploads and tokens: Ops should usually schedule their uploads to occur at the
bsalomon342bfc22016-04-01 06:06:20 -0700141 * begining of a frame whenever possible. These are called ASAP uploads. Of course, this requires
142 * that there are no draws that have yet to be flushed that rely on the old texture contents. In
143 * that case the ASAP upload would happen prior to the previous draw causing the draw to read the
144 * new (wrong) texture data. In that case they should schedule an inline upload.
145 *
Brian Salomon2ee084e2016-12-16 18:59:19 -0500146 * Ops, in conjunction with helpers such as GrDrawOpAtlas, can use the token system to know
bsalomon342bfc22016-04-01 06:06:20 -0700147 * what the most recent draw was that referenced a resource (or portion of a resource). Each draw
148 * is assigned a token. A resource (or portion) can be tagged with the most recent draw's
149 * token. The target provides a facility for testing whether the draw corresponding to the token
Brian Salomon742e31d2016-12-07 17:06:19 -0500150 * has been flushed. If it has not been flushed then the op must perform an inline upload instead.
151 * When scheduling an inline upload the op provides the token of the draw that the upload must occur
152 * before. The upload will then occur between the draw that requires the new data but after the
153 * token that requires the old data.
bsalomon342bfc22016-04-01 06:06:20 -0700154 *
Brian Salomondad29232016-12-01 16:40:24 -0500155 * TODO: Currently the token/upload interface is spread over GrDrawOp, GrMeshDrawOp,
156 * GrDrawOp::Target, and GrMeshDrawOp::Target. However, the interface at the GrDrawOp level is not
157 * complete and isn't useful. We should push it down to GrMeshDrawOp until it is required at the
158 * GrDrawOp level.
bsalomon342bfc22016-04-01 06:06:20 -0700159 */
Brian Salomondad29232016-12-01 16:40:24 -0500160
bsalomon342bfc22016-04-01 06:06:20 -0700161/**
Brian Salomon9afd3712016-12-01 10:59:09 -0500162 * GrDrawOp instances use this object to allocate space for their geometry and to issue the draws
Brian Salomon742e31d2016-12-07 17:06:19 -0500163 * that render their op.
bsalomon75398562015-08-17 12:55:38 -0700164 */
Brian Salomon9afd3712016-12-01 10:59:09 -0500165class GrDrawOp::Target {
bsalomon75398562015-08-17 12:55:38 -0700166public:
Brian Salomon742e31d2016-12-07 17:06:19 -0500167 Target(GrOpFlushState* state, GrDrawOp* op) : fState(state), fOp(op) {}
bsalomon75398562015-08-17 12:55:38 -0700168
bsalomon342bfc22016-04-01 06:06:20 -0700169 /** Returns the token of the draw that this upload will occur before. */
Brian Salomon9afd3712016-12-01 10:59:09 -0500170 GrDrawOpUploadToken addInlineUpload(DeferredUploadFn&& upload) {
Brian Salomon742e31d2016-12-07 17:06:19 -0500171 fOp->fInlineUploads.emplace_back(std::move(upload), fState->nextDrawToken());
172 return fOp->fInlineUploads.back().fUploadBeforeToken;
bsalomon75398562015-08-17 12:55:38 -0700173 }
174
bsalomon342bfc22016-04-01 06:06:20 -0700175 /** Returns the token of the draw that this upload will occur before. Since ASAP uploads
176 are done first during a flush, this will be the first token since the most recent
177 flush. */
Brian Salomon9afd3712016-12-01 10:59:09 -0500178 GrDrawOpUploadToken addAsapUpload(DeferredUploadFn&& upload) {
bsalomon342bfc22016-04-01 06:06:20 -0700179 fState->addASAPUpload(std::move(upload));
180 return fState->nextTokenToFlush();
bsalomon75398562015-08-17 12:55:38 -0700181 }
bsalomon342bfc22016-04-01 06:06:20 -0700182
Brian Salomon9afd3712016-12-01 10:59:09 -0500183 bool hasDrawBeenFlushed(GrDrawOpUploadToken token) const {
bsalomon342bfc22016-04-01 06:06:20 -0700184 return fState->hasDrawBeenFlushed(token);
185 }
186
Brian Salomon742e31d2016-12-07 17:06:19 -0500187 /** Gets the next draw token that will be issued by this target. This can be used by an op
bsalomon342bfc22016-04-01 06:06:20 -0700188 to record that the next draw it issues will use a resource (e.g. texture) while preparing
189 that draw. */
Brian Salomon9afd3712016-12-01 10:59:09 -0500190 GrDrawOpUploadToken nextDrawToken() const { return fState->nextDrawToken(); }
bsalomon75398562015-08-17 12:55:38 -0700191
192 const GrCaps& caps() const { return fState->caps(); }
193
194 GrResourceProvider* resourceProvider() const { return fState->resourceProvider(); }
195
196protected:
Brian Salomon742e31d2016-12-07 17:06:19 -0500197 GrDrawOp* op() { return fOp; }
198 GrOpFlushState* state() { return fState; }
Brian Salomon6d4b65e2017-05-03 17:06:09 -0400199 const GrOpFlushState* state() const { return fState; }
bsalomon75398562015-08-17 12:55:38 -0700200
201private:
Brian Salomon742e31d2016-12-07 17:06:19 -0500202 GrOpFlushState* fState;
203 GrDrawOp* fOp;
bsalomon75398562015-08-17 12:55:38 -0700204};
205
Brian Salomondad29232016-12-01 16:40:24 -0500206/** Extension of GrDrawOp::Target for use by GrMeshDrawOp. Adds the ability to create vertex
bsalomon75398562015-08-17 12:55:38 -0700207 draws. */
Brian Salomondad29232016-12-01 16:40:24 -0500208class GrMeshDrawOp::Target : public GrDrawOp::Target {
bsalomon75398562015-08-17 12:55:38 -0700209public:
Brian Salomon742e31d2016-12-07 17:06:19 -0500210 Target(GrOpFlushState* state, GrMeshDrawOp* op) : INHERITED(state, op) {}
bsalomon75398562015-08-17 12:55:38 -0700211
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400212 void draw(const GrGeometryProcessor* gp, const GrPipeline* pipeline, const GrMesh& mesh);
bsalomon75398562015-08-17 12:55:38 -0700213
214 void* makeVertexSpace(size_t vertexSize, int vertexCount,
cdalton397536c2016-03-25 12:15:03 -0700215 const GrBuffer** buffer, int* startVertex) {
bsalomon75398562015-08-17 12:55:38 -0700216 return this->state()->makeVertexSpace(vertexSize, vertexCount, buffer, startVertex);
217 }
218
cdalton397536c2016-03-25 12:15:03 -0700219 uint16_t* makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex) {
bsalomon75398562015-08-17 12:55:38 -0700220 return this->state()->makeIndexSpace(indexCount, buffer, startIndex);
221 }
222
Brian Osman49b7b6f2017-06-20 14:43:58 -0400223 void* makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount, int fallbackVertexCount,
224 const GrBuffer** buffer, int* startVertex,
225 int* actualVertexCount) {
226 return this->state()->makeVertexSpaceAtLeast(vertexSize, minVertexCount,
227 fallbackVertexCount, buffer, startVertex,
228 actualVertexCount);
229 }
230
231 uint16_t* makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
232 const GrBuffer** buffer, int* startIndex,
233 int* actualIndexCount) {
234 return this->state()->makeIndexSpaceAtLeast(minIndexCount, fallbackIndexCount, buffer,
235 startIndex, actualIndexCount);
236 }
237
Brian Salomon742e31d2016-12-07 17:06:19 -0500238 /** Helpers for ops which over-allocate and then return data to the pool. */
bsalomon75398562015-08-17 12:55:38 -0700239 void putBackIndices(int indices) { this->state()->putBackIndices(indices); }
240 void putBackVertices(int vertices, size_t vertexStride) {
241 this->state()->putBackVertexSpace(vertices * vertexStride);
242 }
243
Robert Phillips2890fbf2017-07-26 15:48:41 -0400244 GrRenderTargetProxy* proxy() const { return this->state()->drawOpArgs().fProxy; }
Brian Salomon6d4b65e2017-05-03 17:06:09 -0400245
246 const GrAppliedClip* clip() const { return this->state()->drawOpArgs().fAppliedClip; }
247
Brian Salomonbfd18cd2017-08-09 16:27:09 -0400248 GrAppliedClip detachAppliedClip() { return this->state()->detachAppliedClip(); }
249
Robert Phillipsbb581ce2017-05-29 15:05:15 -0400250 const GrXferProcessor::DstProxy& dstProxy() const {
251 return this->state()->drawOpArgs().fDstProxy;
Brian Salomon6d4b65e2017-05-03 17:06:09 -0400252 }
253
254 template <typename... Args>
Brian Salomon91326c32017-08-09 16:02:19 -0400255 GrPipeline* allocPipeline(Args&&... args) {
Brian Salomon6d4b65e2017-05-03 17:06:09 -0400256 return this->state()->allocPipeline(std::forward<Args>(args)...);
257 }
258
Brian Salomon05969092017-07-13 11:20:51 -0400259 /**
260 * Helper that makes a pipeline targeting the op's render target that incorporates the op's
261 * GrAppliedClip.
262 * */
Brian Salomonbfd18cd2017-08-09 16:27:09 -0400263 GrPipeline* makePipeline(uint32_t pipelineFlags, GrProcessorSet&& processorSet,
264 GrAppliedClip&& clip) {
Brian Salomon98222ac2017-07-12 15:27:54 -0400265 GrPipeline::InitArgs pipelineArgs;
266 pipelineArgs.fFlags = pipelineFlags;
Robert Phillips2890fbf2017-07-26 15:48:41 -0400267 pipelineArgs.fProxy = this->proxy();
Brian Salomon98222ac2017-07-12 15:27:54 -0400268 pipelineArgs.fDstProxy = this->dstProxy();
269 pipelineArgs.fCaps = &this->caps();
270 pipelineArgs.fResourceProvider = this->resourceProvider();
Brian Salomonbfd18cd2017-08-09 16:27:09 -0400271 return this->allocPipeline(pipelineArgs, std::move(processorSet), std::move(clip));
Brian Salomon98222ac2017-07-12 15:27:54 -0400272 }
273
bsalomon75398562015-08-17 12:55:38 -0700274private:
Brian Salomon742e31d2016-12-07 17:06:19 -0500275 GrMeshDrawOp* meshDrawOp() { return static_cast<GrMeshDrawOp*>(this->op()); }
Brian Salomon9afd3712016-12-01 10:59:09 -0500276 typedef GrDrawOp::Target INHERITED;
bsalomon75398562015-08-17 12:55:38 -0700277};
278
279#endif