blob: ed77c3b4680d1de67c6610b835bc3093f4e3f69a [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
11#include "GrBufferAllocPool.h"
Greg Daniel77b53f62016-10-18 11:48:51 -040012#include "GrGpu.h"
Brian Salomon89527432016-12-16 09:52:16 -050013#include "ops/GrMeshDrawOp.h"
bsalomon75398562015-08-17 12:55:38 -070014
egdaniel9cb63402016-06-23 08:37:05 -070015class GrGpuCommandBuffer;
bsalomon75398562015-08-17 12:55:38 -070016class GrResourceProvider;
17
Brian Salomon742e31d2016-12-07 17:06:19 -050018/** Tracks the state across all the GrOps (really just the GrDrawOps) in a GrOpList flush. */
19class GrOpFlushState {
bsalomon75398562015-08-17 12:55:38 -070020public:
Brian Salomon742e31d2016-12-07 17:06:19 -050021 GrOpFlushState(GrGpu*, GrResourceProvider*);
bsalomon75398562015-08-17 12:55:38 -070022
Brian Salomon742e31d2016-12-07 17:06:19 -050023 ~GrOpFlushState() { this->reset(); }
bsalomon75398562015-08-17 12:55:38 -070024
Brian Salomon742e31d2016-12-07 17:06:19 -050025 /** Inserts an upload to be executed after all ops in the flush prepared their draws but before
26 the draws are executed to the backend 3D API. */
Brian Salomon9afd3712016-12-01 10:59:09 -050027 void addASAPUpload(GrDrawOp::DeferredUploadFn&& upload) {
bsalomon342bfc22016-04-01 06:06:20 -070028 fAsapUploads.emplace_back(std::move(upload));
bsalomon75398562015-08-17 12:55:38 -070029 }
30
31 const GrCaps& caps() const { return *fGpu->caps(); }
32 GrResourceProvider* resourceProvider() const { return fResourceProvider; }
33
34 /** Has the token been flushed to the backend 3D API. */
Brian Salomon9afd3712016-12-01 10:59:09 -050035 bool hasDrawBeenFlushed(GrDrawOpUploadToken token) const {
bsalomon342bfc22016-04-01 06:06:20 -070036 return token.fSequenceNumber <= fLastFlushedToken.fSequenceNumber;
37 }
bsalomon75398562015-08-17 12:55:38 -070038
bsalomon342bfc22016-04-01 06:06:20 -070039 /** Issue a token to an operation that is being enqueued. */
Brian Salomon9afd3712016-12-01 10:59:09 -050040 GrDrawOpUploadToken issueDrawToken() {
41 return GrDrawOpUploadToken(++fLastIssuedToken.fSequenceNumber);
bsalomon342bfc22016-04-01 06:06:20 -070042 }
43
44 /** Call every time a draw that was issued a token is flushed */
45 void flushToken() { ++fLastFlushedToken.fSequenceNumber; }
46
47 /** Gets the next draw token that will be issued. */
Brian Salomon9afd3712016-12-01 10:59:09 -050048 GrDrawOpUploadToken nextDrawToken() const {
49 return GrDrawOpUploadToken(fLastIssuedToken.fSequenceNumber + 1);
bsalomon342bfc22016-04-01 06:06:20 -070050 }
bsalomon75398562015-08-17 12:55:38 -070051
52 /** The last token flushed to all the way to the backend API. */
Brian Salomon9afd3712016-12-01 10:59:09 -050053 GrDrawOpUploadToken nextTokenToFlush() const {
54 return GrDrawOpUploadToken(fLastFlushedToken.fSequenceNumber + 1);
bsalomon342bfc22016-04-01 06:06:20 -070055 }
bsalomon75398562015-08-17 12:55:38 -070056
57 void* makeVertexSpace(size_t vertexSize, int vertexCount,
cdalton397536c2016-03-25 12:15:03 -070058 const GrBuffer** buffer, int* startVertex);
59 uint16_t* makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex);
bsalomon75398562015-08-17 12:55:38 -070060
Brian Salomon742e31d2016-12-07 17:06:19 -050061 /** This is called after each op has a chance to prepare its draws and before the draws are
62 issued. */
bsalomon75398562015-08-17 12:55:38 -070063 void preIssueDraws() {
64 fVertexPool.unmap();
65 fIndexPool.unmap();
66 int uploadCount = fAsapUploads.count();
bsalomon342bfc22016-04-01 06:06:20 -070067
bsalomon75398562015-08-17 12:55:38 -070068 for (int i = 0; i < uploadCount; i++) {
bsalomon342bfc22016-04-01 06:06:20 -070069 this->doUpload(fAsapUploads[i]);
bsalomon75398562015-08-17 12:55:38 -070070 }
71 fAsapUploads.reset();
72 }
73
Brian Salomon9afd3712016-12-01 10:59:09 -050074 void doUpload(GrDrawOp::DeferredUploadFn& upload) {
75 GrDrawOp::WritePixelsFn wp = [this] (GrSurface* surface,
bsalomon342bfc22016-04-01 06:06:20 -070076 int left, int top, int width, int height,
77 GrPixelConfig config, const void* buffer,
78 size_t rowBytes) -> bool {
79 return this->fGpu->writePixels(surface, left, top, width, height, config, buffer,
80 rowBytes);
81 };
jvanverthc3d706f2016-04-20 10:33:27 -070082 upload(wp);
bsalomon342bfc22016-04-01 06:06:20 -070083 }
84
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; }
90 void setCommandBuffer(GrGpuCommandBuffer* buffer) { fCommandBuffer = buffer; }
91
bsalomon75398562015-08-17 12:55:38 -070092 GrGpu* gpu() { return fGpu; }
93
joshualittf6d259b2015-10-02 11:27:14 -070094 void reset() {
95 fVertexPool.reset();
96 fIndexPool.reset();
97 }
98
bsalomon75398562015-08-17 12:55:38 -070099private:
bsalomon75398562015-08-17 12:55:38 -0700100
Brian Salomon9afd3712016-12-01 10:59:09 -0500101 GrGpu* fGpu;
bsalomon75398562015-08-17 12:55:38 -0700102
Brian Salomon9afd3712016-12-01 10:59:09 -0500103 GrResourceProvider* fResourceProvider;
bsalomon75398562015-08-17 12:55:38 -0700104
Brian Salomon9afd3712016-12-01 10:59:09 -0500105 GrGpuCommandBuffer* fCommandBuffer;
egdaniel9cb63402016-06-23 08:37:05 -0700106
Brian Salomon9afd3712016-12-01 10:59:09 -0500107 GrVertexBufferAllocPool fVertexPool;
108 GrIndexBufferAllocPool fIndexPool;
bsalomon75398562015-08-17 12:55:38 -0700109
Brian Salomon9afd3712016-12-01 10:59:09 -0500110 SkSTArray<4, GrDrawOp::DeferredUploadFn> fAsapUploads;
bsalomon75398562015-08-17 12:55:38 -0700111
Brian Salomon9afd3712016-12-01 10:59:09 -0500112 GrDrawOpUploadToken fLastIssuedToken;
bsalomon342bfc22016-04-01 06:06:20 -0700113
Brian Salomon9afd3712016-12-01 10:59:09 -0500114 GrDrawOpUploadToken fLastFlushedToken;
bsalomon75398562015-08-17 12:55:38 -0700115};
116
117/**
Brian Salomon742e31d2016-12-07 17:06:19 -0500118 * A word about uploads and tokens: Ops should usually schedule their uploads to occur at the
bsalomon342bfc22016-04-01 06:06:20 -0700119 * begining of a frame whenever possible. These are called ASAP uploads. Of course, this requires
120 * that there are no draws that have yet to be flushed that rely on the old texture contents. In
121 * that case the ASAP upload would happen prior to the previous draw causing the draw to read the
122 * new (wrong) texture data. In that case they should schedule an inline upload.
123 *
Brian Salomon2ee084e2016-12-16 18:59:19 -0500124 * Ops, in conjunction with helpers such as GrDrawOpAtlas, can use the token system to know
bsalomon342bfc22016-04-01 06:06:20 -0700125 * what the most recent draw was that referenced a resource (or portion of a resource). Each draw
126 * is assigned a token. A resource (or portion) can be tagged with the most recent draw's
127 * token. The target provides a facility for testing whether the draw corresponding to the token
Brian Salomon742e31d2016-12-07 17:06:19 -0500128 * has been flushed. If it has not been flushed then the op must perform an inline upload instead.
129 * When scheduling an inline upload the op provides the token of the draw that the upload must occur
130 * before. The upload will then occur between the draw that requires the new data but after the
131 * token that requires the old data.
bsalomon342bfc22016-04-01 06:06:20 -0700132 *
Brian Salomondad29232016-12-01 16:40:24 -0500133 * TODO: Currently the token/upload interface is spread over GrDrawOp, GrMeshDrawOp,
134 * GrDrawOp::Target, and GrMeshDrawOp::Target. However, the interface at the GrDrawOp level is not
135 * complete and isn't useful. We should push it down to GrMeshDrawOp until it is required at the
136 * GrDrawOp level.
bsalomon342bfc22016-04-01 06:06:20 -0700137 */
Brian Salomondad29232016-12-01 16:40:24 -0500138
bsalomon342bfc22016-04-01 06:06:20 -0700139/**
Brian Salomon9afd3712016-12-01 10:59:09 -0500140 * GrDrawOp instances use this object to allocate space for their geometry and to issue the draws
Brian Salomon742e31d2016-12-07 17:06:19 -0500141 * that render their op.
bsalomon75398562015-08-17 12:55:38 -0700142 */
Brian Salomon9afd3712016-12-01 10:59:09 -0500143class GrDrawOp::Target {
bsalomon75398562015-08-17 12:55:38 -0700144public:
Brian Salomon742e31d2016-12-07 17:06:19 -0500145 Target(GrOpFlushState* state, GrDrawOp* op) : fState(state), fOp(op) {}
bsalomon75398562015-08-17 12:55:38 -0700146
bsalomon342bfc22016-04-01 06:06:20 -0700147 /** Returns the token of the draw that this upload will occur before. */
Brian Salomon9afd3712016-12-01 10:59:09 -0500148 GrDrawOpUploadToken addInlineUpload(DeferredUploadFn&& upload) {
Brian Salomon742e31d2016-12-07 17:06:19 -0500149 fOp->fInlineUploads.emplace_back(std::move(upload), fState->nextDrawToken());
150 return fOp->fInlineUploads.back().fUploadBeforeToken;
bsalomon75398562015-08-17 12:55:38 -0700151 }
152
bsalomon342bfc22016-04-01 06:06:20 -0700153 /** Returns the token of the draw that this upload will occur before. Since ASAP uploads
154 are done first during a flush, this will be the first token since the most recent
155 flush. */
Brian Salomon9afd3712016-12-01 10:59:09 -0500156 GrDrawOpUploadToken addAsapUpload(DeferredUploadFn&& upload) {
bsalomon342bfc22016-04-01 06:06:20 -0700157 fState->addASAPUpload(std::move(upload));
158 return fState->nextTokenToFlush();
bsalomon75398562015-08-17 12:55:38 -0700159 }
bsalomon342bfc22016-04-01 06:06:20 -0700160
Brian Salomon9afd3712016-12-01 10:59:09 -0500161 bool hasDrawBeenFlushed(GrDrawOpUploadToken token) const {
bsalomon342bfc22016-04-01 06:06:20 -0700162 return fState->hasDrawBeenFlushed(token);
163 }
164
Brian Salomon742e31d2016-12-07 17:06:19 -0500165 /** 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 -0700166 to record that the next draw it issues will use a resource (e.g. texture) while preparing
167 that draw. */
Brian Salomon9afd3712016-12-01 10:59:09 -0500168 GrDrawOpUploadToken nextDrawToken() const { return fState->nextDrawToken(); }
bsalomon75398562015-08-17 12:55:38 -0700169
170 const GrCaps& caps() const { return fState->caps(); }
171
172 GrResourceProvider* resourceProvider() const { return fState->resourceProvider(); }
173
174protected:
Brian Salomon742e31d2016-12-07 17:06:19 -0500175 GrDrawOp* op() { return fOp; }
176 GrOpFlushState* state() { return fState; }
bsalomon75398562015-08-17 12:55:38 -0700177
178private:
Brian Salomon742e31d2016-12-07 17:06:19 -0500179 GrOpFlushState* fState;
180 GrDrawOp* fOp;
bsalomon75398562015-08-17 12:55:38 -0700181};
182
Brian Salomondad29232016-12-01 16:40:24 -0500183/** Extension of GrDrawOp::Target for use by GrMeshDrawOp. Adds the ability to create vertex
bsalomon75398562015-08-17 12:55:38 -0700184 draws. */
Brian Salomondad29232016-12-01 16:40:24 -0500185class GrMeshDrawOp::Target : public GrDrawOp::Target {
bsalomon75398562015-08-17 12:55:38 -0700186public:
Brian Salomon742e31d2016-12-07 17:06:19 -0500187 Target(GrOpFlushState* state, GrMeshDrawOp* op) : INHERITED(state, op) {}
bsalomon75398562015-08-17 12:55:38 -0700188
bsalomon342bfc22016-04-01 06:06:20 -0700189 void draw(const GrGeometryProcessor* gp, const GrMesh& mesh);
bsalomon75398562015-08-17 12:55:38 -0700190
191 void* makeVertexSpace(size_t vertexSize, int vertexCount,
cdalton397536c2016-03-25 12:15:03 -0700192 const GrBuffer** buffer, int* startVertex) {
bsalomon75398562015-08-17 12:55:38 -0700193 return this->state()->makeVertexSpace(vertexSize, vertexCount, buffer, startVertex);
194 }
195
cdalton397536c2016-03-25 12:15:03 -0700196 uint16_t* makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex) {
bsalomon75398562015-08-17 12:55:38 -0700197 return this->state()->makeIndexSpace(indexCount, buffer, startIndex);
198 }
199
Brian Salomon742e31d2016-12-07 17:06:19 -0500200 /** Helpers for ops which over-allocate and then return data to the pool. */
bsalomon75398562015-08-17 12:55:38 -0700201 void putBackIndices(int indices) { this->state()->putBackIndices(indices); }
202 void putBackVertices(int vertices, size_t vertexStride) {
203 this->state()->putBackVertexSpace(vertices * vertexStride);
204 }
205
206private:
Brian Salomon742e31d2016-12-07 17:06:19 -0500207 GrMeshDrawOp* meshDrawOp() { return static_cast<GrMeshDrawOp*>(this->op()); }
Brian Salomon9afd3712016-12-01 10:59:09 -0500208 typedef GrDrawOp::Target INHERITED;
bsalomon75398562015-08-17 12:55:38 -0700209};
210
211#endif