blob: a5a5f82c31b955dbf45ee5c2b57840062479ed24 [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;
Greg Daniel500d58b2017-08-24 15:59:33 -040018class GrGpuRTCommandBuffer;
bsalomon75398562015-08-17 12:55:38 -070019class GrResourceProvider;
20
Brian Salomon742e31d2016-12-07 17:06:19 -050021/** Tracks the state across all the GrOps (really just the GrDrawOps) in a GrOpList flush. */
22class GrOpFlushState {
bsalomon75398562015-08-17 12:55:38 -070023public:
Brian Salomon742e31d2016-12-07 17:06:19 -050024 GrOpFlushState(GrGpu*, GrResourceProvider*);
bsalomon75398562015-08-17 12:55:38 -070025
Brian Salomon742e31d2016-12-07 17:06:19 -050026 ~GrOpFlushState() { this->reset(); }
bsalomon75398562015-08-17 12:55:38 -070027
Brian Salomon742e31d2016-12-07 17:06:19 -050028 /** Inserts an upload to be executed after all ops in the flush prepared their draws but before
29 the draws are executed to the backend 3D API. */
Brian Salomon9afd3712016-12-01 10:59:09 -050030 void addASAPUpload(GrDrawOp::DeferredUploadFn&& upload) {
bsalomon342bfc22016-04-01 06:06:20 -070031 fAsapUploads.emplace_back(std::move(upload));
bsalomon75398562015-08-17 12:55:38 -070032 }
33
Robert Phillips646e4292017-06-13 12:44:56 -040034 const GrCaps& caps() const;
bsalomon75398562015-08-17 12:55:38 -070035 GrResourceProvider* resourceProvider() const { return fResourceProvider; }
36
37 /** Has the token been flushed to the backend 3D API. */
Brian Salomon9afd3712016-12-01 10:59:09 -050038 bool hasDrawBeenFlushed(GrDrawOpUploadToken token) const {
bsalomon342bfc22016-04-01 06:06:20 -070039 return token.fSequenceNumber <= fLastFlushedToken.fSequenceNumber;
40 }
bsalomon75398562015-08-17 12:55:38 -070041
bsalomon342bfc22016-04-01 06:06:20 -070042 /** Issue a token to an operation that is being enqueued. */
Brian Salomon9afd3712016-12-01 10:59:09 -050043 GrDrawOpUploadToken issueDrawToken() {
44 return GrDrawOpUploadToken(++fLastIssuedToken.fSequenceNumber);
bsalomon342bfc22016-04-01 06:06:20 -070045 }
46
47 /** Call every time a draw that was issued a token is flushed */
48 void flushToken() { ++fLastFlushedToken.fSequenceNumber; }
49
50 /** Gets the next draw token that will be issued. */
Brian Salomon9afd3712016-12-01 10:59:09 -050051 GrDrawOpUploadToken nextDrawToken() const {
52 return GrDrawOpUploadToken(fLastIssuedToken.fSequenceNumber + 1);
bsalomon342bfc22016-04-01 06:06:20 -070053 }
bsalomon75398562015-08-17 12:55:38 -070054
55 /** The last token flushed to all the way to the backend API. */
Brian Salomon9afd3712016-12-01 10:59:09 -050056 GrDrawOpUploadToken nextTokenToFlush() const {
57 return GrDrawOpUploadToken(fLastFlushedToken.fSequenceNumber + 1);
bsalomon342bfc22016-04-01 06:06:20 -070058 }
bsalomon75398562015-08-17 12:55:38 -070059
60 void* makeVertexSpace(size_t vertexSize, int vertexCount,
cdalton397536c2016-03-25 12:15:03 -070061 const GrBuffer** buffer, int* startVertex);
62 uint16_t* makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex);
bsalomon75398562015-08-17 12:55:38 -070063
Brian Osman49b7b6f2017-06-20 14:43:58 -040064 void* makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount, int fallbackVertexCount,
65 const GrBuffer** buffer, int* startVertex, int* actualVertexCount);
66 uint16_t* makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
67 const GrBuffer** buffer, int* startIndex,
68 int* actualIndexCount);
69
Brian Salomon742e31d2016-12-07 17:06:19 -050070 /** This is called after each op has a chance to prepare its draws and before the draws are
71 issued. */
bsalomon75398562015-08-17 12:55:38 -070072 void preIssueDraws() {
73 fVertexPool.unmap();
74 fIndexPool.unmap();
75 int uploadCount = fAsapUploads.count();
bsalomon342bfc22016-04-01 06:06:20 -070076
bsalomon75398562015-08-17 12:55:38 -070077 for (int i = 0; i < uploadCount; i++) {
bsalomon342bfc22016-04-01 06:06:20 -070078 this->doUpload(fAsapUploads[i]);
bsalomon75398562015-08-17 12:55:38 -070079 }
80 fAsapUploads.reset();
81 }
82
Brian Salomon9bada542017-06-12 12:09:30 -040083 void doUpload(GrDrawOp::DeferredUploadFn&);
bsalomon342bfc22016-04-01 06:06:20 -070084
bsalomon75398562015-08-17 12:55:38 -070085 void putBackIndices(size_t indices) { fIndexPool.putBack(indices * sizeof(uint16_t)); }
86
87 void putBackVertexSpace(size_t sizeInBytes) { fVertexPool.putBack(sizeInBytes); }
88
egdaniel9cb63402016-06-23 08:37:05 -070089 GrGpuCommandBuffer* commandBuffer() { return fCommandBuffer; }
Greg Daniel500d58b2017-08-24 15:59:33 -040090 // Helper function used by Ops that are only called via RenderTargetOpLists
91 GrGpuRTCommandBuffer* rtCommandBuffer();
egdaniel9cb63402016-06-23 08:37:05 -070092 void setCommandBuffer(GrGpuCommandBuffer* buffer) { fCommandBuffer = buffer; }
93
bsalomon75398562015-08-17 12:55:38 -070094 GrGpu* gpu() { return fGpu; }
95
joshualittf6d259b2015-10-02 11:27:14 -070096 void reset() {
97 fVertexPool.reset();
98 fIndexPool.reset();
Brian Salomon6d4b65e2017-05-03 17:06:09 -040099 fPipelines.reset();
joshualittf6d259b2015-10-02 11:27:14 -0700100 }
101
Brian Salomon54d212e2017-03-21 14:22:38 -0400102 /** Additional data required on a per-op basis when executing GrDrawOps. */
103 struct DrawOpArgs {
Robert Phillips2890fbf2017-07-26 15:48:41 -0400104 GrRenderTarget* renderTarget() const { return fProxy->priv().peekRenderTarget(); }
105
Robert Phillips19e51dc2017-08-09 09:30:51 -0400106 // TODO: do we still need the dst proxy here?
Brian Salomonbfd18cd2017-08-09 16:27:09 -0400107 GrRenderTargetProxy* fProxy;
108 GrAppliedClip* fAppliedClip;
Robert Phillipsbb581ce2017-05-29 15:05:15 -0400109 GrXferProcessor::DstProxy fDstProxy;
Brian Salomon54d212e2017-03-21 14:22:38 -0400110 };
111
112 void setDrawOpArgs(DrawOpArgs* opArgs) { fOpArgs = opArgs; }
113
114 const DrawOpArgs& drawOpArgs() const {
115 SkASSERT(fOpArgs);
116 return *fOpArgs;
117 }
118
Brian Salomonbfd18cd2017-08-09 16:27:09 -0400119 GrAppliedClip detachAppliedClip() {
120 SkASSERT(fOpArgs);
121 return fOpArgs->fAppliedClip ? std::move(*fOpArgs->fAppliedClip) : GrAppliedClip();
122 }
123
Brian Salomon6d4b65e2017-05-03 17:06:09 -0400124 template <typename... Args>
Brian Salomon91326c32017-08-09 16:02:19 -0400125 GrPipeline* allocPipeline(Args&&... args) {
Brian Salomon6d4b65e2017-05-03 17:06:09 -0400126 return fPipelines.make<GrPipeline>(std::forward<Args>(args)...);
127 }
128
bsalomon75398562015-08-17 12:55:38 -0700129private:
Brian Salomon6d4b65e2017-05-03 17:06:09 -0400130 GrGpu* fGpu;
131 GrResourceProvider* fResourceProvider;
132 GrGpuCommandBuffer* fCommandBuffer;
133 GrVertexBufferAllocPool fVertexPool;
134 GrIndexBufferAllocPool fIndexPool;
135 SkSTArray<4, GrDrawOp::DeferredUploadFn> fAsapUploads;
136 GrDrawOpUploadToken fLastIssuedToken;
137 GrDrawOpUploadToken fLastFlushedToken;
138 DrawOpArgs* fOpArgs;
139 SkArenaAlloc fPipelines{sizeof(GrPipeline) * 100};
bsalomon75398562015-08-17 12:55:38 -0700140};
141
142/**
Brian Salomon742e31d2016-12-07 17:06:19 -0500143 * A word about uploads and tokens: Ops should usually schedule their uploads to occur at the
bsalomon342bfc22016-04-01 06:06:20 -0700144 * begining of a frame whenever possible. These are called ASAP uploads. Of course, this requires
145 * that there are no draws that have yet to be flushed that rely on the old texture contents. In
146 * that case the ASAP upload would happen prior to the previous draw causing the draw to read the
147 * new (wrong) texture data. In that case they should schedule an inline upload.
148 *
Brian Salomon2ee084e2016-12-16 18:59:19 -0500149 * Ops, in conjunction with helpers such as GrDrawOpAtlas, can use the token system to know
bsalomon342bfc22016-04-01 06:06:20 -0700150 * what the most recent draw was that referenced a resource (or portion of a resource). Each draw
151 * is assigned a token. A resource (or portion) can be tagged with the most recent draw's
152 * token. The target provides a facility for testing whether the draw corresponding to the token
Brian Salomon742e31d2016-12-07 17:06:19 -0500153 * has been flushed. If it has not been flushed then the op must perform an inline upload instead.
154 * When scheduling an inline upload the op provides the token of the draw that the upload must occur
155 * before. The upload will then occur between the draw that requires the new data but after the
156 * token that requires the old data.
bsalomon342bfc22016-04-01 06:06:20 -0700157 *
Brian Salomondad29232016-12-01 16:40:24 -0500158 * TODO: Currently the token/upload interface is spread over GrDrawOp, GrMeshDrawOp,
159 * GrDrawOp::Target, and GrMeshDrawOp::Target. However, the interface at the GrDrawOp level is not
160 * complete and isn't useful. We should push it down to GrMeshDrawOp until it is required at the
161 * GrDrawOp level.
bsalomon342bfc22016-04-01 06:06:20 -0700162 */
Brian Salomondad29232016-12-01 16:40:24 -0500163
bsalomon342bfc22016-04-01 06:06:20 -0700164/**
Brian Salomon9afd3712016-12-01 10:59:09 -0500165 * GrDrawOp instances use this object to allocate space for their geometry and to issue the draws
Brian Salomon742e31d2016-12-07 17:06:19 -0500166 * that render their op.
bsalomon75398562015-08-17 12:55:38 -0700167 */
Brian Salomon9afd3712016-12-01 10:59:09 -0500168class GrDrawOp::Target {
bsalomon75398562015-08-17 12:55:38 -0700169public:
Brian Salomon742e31d2016-12-07 17:06:19 -0500170 Target(GrOpFlushState* state, GrDrawOp* op) : fState(state), fOp(op) {}
bsalomon75398562015-08-17 12:55:38 -0700171
bsalomon342bfc22016-04-01 06:06:20 -0700172 /** Returns the token of the draw that this upload will occur before. */
Brian Salomon9afd3712016-12-01 10:59:09 -0500173 GrDrawOpUploadToken addInlineUpload(DeferredUploadFn&& upload) {
Brian Salomon742e31d2016-12-07 17:06:19 -0500174 fOp->fInlineUploads.emplace_back(std::move(upload), fState->nextDrawToken());
175 return fOp->fInlineUploads.back().fUploadBeforeToken;
bsalomon75398562015-08-17 12:55:38 -0700176 }
177
bsalomon342bfc22016-04-01 06:06:20 -0700178 /** Returns the token of the draw that this upload will occur before. Since ASAP uploads
179 are done first during a flush, this will be the first token since the most recent
180 flush. */
Brian Salomon9afd3712016-12-01 10:59:09 -0500181 GrDrawOpUploadToken addAsapUpload(DeferredUploadFn&& upload) {
bsalomon342bfc22016-04-01 06:06:20 -0700182 fState->addASAPUpload(std::move(upload));
183 return fState->nextTokenToFlush();
bsalomon75398562015-08-17 12:55:38 -0700184 }
bsalomon342bfc22016-04-01 06:06:20 -0700185
Brian Salomon9afd3712016-12-01 10:59:09 -0500186 bool hasDrawBeenFlushed(GrDrawOpUploadToken token) const {
bsalomon342bfc22016-04-01 06:06:20 -0700187 return fState->hasDrawBeenFlushed(token);
188 }
189
Brian Salomon742e31d2016-12-07 17:06:19 -0500190 /** 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 -0700191 to record that the next draw it issues will use a resource (e.g. texture) while preparing
192 that draw. */
Brian Salomon9afd3712016-12-01 10:59:09 -0500193 GrDrawOpUploadToken nextDrawToken() const { return fState->nextDrawToken(); }
bsalomon75398562015-08-17 12:55:38 -0700194
195 const GrCaps& caps() const { return fState->caps(); }
196
197 GrResourceProvider* resourceProvider() const { return fState->resourceProvider(); }
198
199protected:
Brian Salomon742e31d2016-12-07 17:06:19 -0500200 GrDrawOp* op() { return fOp; }
201 GrOpFlushState* state() { return fState; }
Brian Salomon6d4b65e2017-05-03 17:06:09 -0400202 const GrOpFlushState* state() const { return fState; }
bsalomon75398562015-08-17 12:55:38 -0700203
204private:
Brian Salomon742e31d2016-12-07 17:06:19 -0500205 GrOpFlushState* fState;
206 GrDrawOp* fOp;
bsalomon75398562015-08-17 12:55:38 -0700207};
208
Brian Salomondad29232016-12-01 16:40:24 -0500209/** Extension of GrDrawOp::Target for use by GrMeshDrawOp. Adds the ability to create vertex
bsalomon75398562015-08-17 12:55:38 -0700210 draws. */
Brian Salomondad29232016-12-01 16:40:24 -0500211class GrMeshDrawOp::Target : public GrDrawOp::Target {
bsalomon75398562015-08-17 12:55:38 -0700212public:
Brian Salomon742e31d2016-12-07 17:06:19 -0500213 Target(GrOpFlushState* state, GrMeshDrawOp* op) : INHERITED(state, op) {}
bsalomon75398562015-08-17 12:55:38 -0700214
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400215 void draw(const GrGeometryProcessor* gp, const GrPipeline* pipeline, const GrMesh& mesh);
bsalomon75398562015-08-17 12:55:38 -0700216
217 void* makeVertexSpace(size_t vertexSize, int vertexCount,
cdalton397536c2016-03-25 12:15:03 -0700218 const GrBuffer** buffer, int* startVertex) {
bsalomon75398562015-08-17 12:55:38 -0700219 return this->state()->makeVertexSpace(vertexSize, vertexCount, buffer, startVertex);
220 }
221
cdalton397536c2016-03-25 12:15:03 -0700222 uint16_t* makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex) {
bsalomon75398562015-08-17 12:55:38 -0700223 return this->state()->makeIndexSpace(indexCount, buffer, startIndex);
224 }
225
Brian Osman49b7b6f2017-06-20 14:43:58 -0400226 void* makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount, int fallbackVertexCount,
227 const GrBuffer** buffer, int* startVertex,
228 int* actualVertexCount) {
229 return this->state()->makeVertexSpaceAtLeast(vertexSize, minVertexCount,
230 fallbackVertexCount, buffer, startVertex,
231 actualVertexCount);
232 }
233
234 uint16_t* makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
235 const GrBuffer** buffer, int* startIndex,
236 int* actualIndexCount) {
237 return this->state()->makeIndexSpaceAtLeast(minIndexCount, fallbackIndexCount, buffer,
238 startIndex, actualIndexCount);
239 }
240
Brian Salomon742e31d2016-12-07 17:06:19 -0500241 /** Helpers for ops which over-allocate and then return data to the pool. */
bsalomon75398562015-08-17 12:55:38 -0700242 void putBackIndices(int indices) { this->state()->putBackIndices(indices); }
243 void putBackVertices(int vertices, size_t vertexStride) {
244 this->state()->putBackVertexSpace(vertices * vertexStride);
245 }
246
Robert Phillips2890fbf2017-07-26 15:48:41 -0400247 GrRenderTargetProxy* proxy() const { return this->state()->drawOpArgs().fProxy; }
Brian Salomon6d4b65e2017-05-03 17:06:09 -0400248
249 const GrAppliedClip* clip() const { return this->state()->drawOpArgs().fAppliedClip; }
250
Brian Salomonbfd18cd2017-08-09 16:27:09 -0400251 GrAppliedClip detachAppliedClip() { return this->state()->detachAppliedClip(); }
252
Robert Phillipsbb581ce2017-05-29 15:05:15 -0400253 const GrXferProcessor::DstProxy& dstProxy() const {
254 return this->state()->drawOpArgs().fDstProxy;
Brian Salomon6d4b65e2017-05-03 17:06:09 -0400255 }
256
257 template <typename... Args>
Brian Salomon91326c32017-08-09 16:02:19 -0400258 GrPipeline* allocPipeline(Args&&... args) {
Brian Salomon6d4b65e2017-05-03 17:06:09 -0400259 return this->state()->allocPipeline(std::forward<Args>(args)...);
260 }
261
Brian Salomon05969092017-07-13 11:20:51 -0400262 /**
263 * Helper that makes a pipeline targeting the op's render target that incorporates the op's
264 * GrAppliedClip.
265 * */
Brian Salomonbfd18cd2017-08-09 16:27:09 -0400266 GrPipeline* makePipeline(uint32_t pipelineFlags, GrProcessorSet&& processorSet,
267 GrAppliedClip&& clip) {
Brian Salomon98222ac2017-07-12 15:27:54 -0400268 GrPipeline::InitArgs pipelineArgs;
269 pipelineArgs.fFlags = pipelineFlags;
Robert Phillips2890fbf2017-07-26 15:48:41 -0400270 pipelineArgs.fProxy = this->proxy();
Brian Salomon98222ac2017-07-12 15:27:54 -0400271 pipelineArgs.fDstProxy = this->dstProxy();
272 pipelineArgs.fCaps = &this->caps();
273 pipelineArgs.fResourceProvider = this->resourceProvider();
Brian Salomonbfd18cd2017-08-09 16:27:09 -0400274 return this->allocPipeline(pipelineArgs, std::move(processorSet), std::move(clip));
Brian Salomon98222ac2017-07-12 15:27:54 -0400275 }
276
bsalomon75398562015-08-17 12:55:38 -0700277private:
Brian Salomon742e31d2016-12-07 17:06:19 -0500278 GrMeshDrawOp* meshDrawOp() { return static_cast<GrMeshDrawOp*>(this->op()); }
Brian Salomon9afd3712016-12-01 10:59:09 -0500279 typedef GrDrawOp::Target INHERITED;
bsalomon75398562015-08-17 12:55:38 -0700280};
281
282#endif