blob: d2d9a4b488908bb0d5f5a24910e1b5826e7490ec [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
8#ifndef GrBatchBuffer_DEFINED
9#define GrBatchBuffer_DEFINED
10
11#include "GrBufferAllocPool.h"
12#include "batches/GrVertexBatch.h"
13
egdaniel9cb63402016-06-23 08:37:05 -070014class GrGpuCommandBuffer;
bsalomon75398562015-08-17 12:55:38 -070015class GrResourceProvider;
16
bsalomon75398562015-08-17 12:55:38 -070017/** Tracks the state across all the GrBatches in a GrDrawTarget flush. */
18class GrBatchFlushState {
19public:
robertphillips1f0e3502015-11-10 10:19:50 -080020 GrBatchFlushState(GrGpu*, GrResourceProvider*);
bsalomon75398562015-08-17 12:55:38 -070021
joshualittf6d259b2015-10-02 11:27:14 -070022 ~GrBatchFlushState() { this->reset(); }
bsalomon75398562015-08-17 12:55:38 -070023
bsalomon342bfc22016-04-01 06:06:20 -070024 /** Inserts an upload to be executed after all batches in the flush prepared their draws
bsalomon75398562015-08-17 12:55:38 -070025 but before the draws are executed to the backend 3D API. */
bsalomon342bfc22016-04-01 06:06:20 -070026 void addASAPUpload(GrDrawBatch::DeferredUploadFn&& upload) {
27 fAsapUploads.emplace_back(std::move(upload));
bsalomon75398562015-08-17 12:55:38 -070028 }
29
30 const GrCaps& caps() const { return *fGpu->caps(); }
31 GrResourceProvider* resourceProvider() const { return fResourceProvider; }
32
33 /** Has the token been flushed to the backend 3D API. */
bsalomon342bfc22016-04-01 06:06:20 -070034 bool hasDrawBeenFlushed(GrBatchDrawToken token) const {
35 return token.fSequenceNumber <= fLastFlushedToken.fSequenceNumber;
36 }
bsalomon75398562015-08-17 12:55:38 -070037
bsalomon342bfc22016-04-01 06:06:20 -070038 /** Issue a token to an operation that is being enqueued. */
39 GrBatchDrawToken issueDrawToken() {
40 return GrBatchDrawToken(++fLastIssuedToken.fSequenceNumber);
41 }
42
43 /** Call every time a draw that was issued a token is flushed */
44 void flushToken() { ++fLastFlushedToken.fSequenceNumber; }
45
46 /** Gets the next draw token that will be issued. */
47 GrBatchDrawToken nextDrawToken() const {
48 return GrBatchDrawToken(fLastIssuedToken.fSequenceNumber + 1);
49 }
bsalomon75398562015-08-17 12:55:38 -070050
51 /** The last token flushed to all the way to the backend API. */
bsalomon342bfc22016-04-01 06:06:20 -070052 GrBatchDrawToken nextTokenToFlush() const {
53 return GrBatchDrawToken(fLastFlushedToken.fSequenceNumber + 1);
54 }
bsalomon75398562015-08-17 12:55:38 -070055
56 void* makeVertexSpace(size_t vertexSize, int vertexCount,
cdalton397536c2016-03-25 12:15:03 -070057 const GrBuffer** buffer, int* startVertex);
58 uint16_t* makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex);
bsalomon75398562015-08-17 12:55:38 -070059
60 /** This is called after each batch has a chance to prepare its draws and before the draws
61 are issued. */
62 void preIssueDraws() {
63 fVertexPool.unmap();
64 fIndexPool.unmap();
65 int uploadCount = fAsapUploads.count();
bsalomon342bfc22016-04-01 06:06:20 -070066
bsalomon75398562015-08-17 12:55:38 -070067 for (int i = 0; i < uploadCount; i++) {
bsalomon342bfc22016-04-01 06:06:20 -070068 this->doUpload(fAsapUploads[i]);
bsalomon75398562015-08-17 12:55:38 -070069 }
70 fAsapUploads.reset();
71 }
72
bsalomon342bfc22016-04-01 06:06:20 -070073 void doUpload(GrDrawBatch::DeferredUploadFn& upload) {
74 GrDrawBatch::WritePixelsFn wp = [this] (GrSurface* surface,
75 int left, int top, int width, int height,
76 GrPixelConfig config, const void* buffer,
77 size_t rowBytes) -> bool {
78 return this->fGpu->writePixels(surface, left, top, width, height, config, buffer,
79 rowBytes);
80 };
jvanverthc3d706f2016-04-20 10:33:27 -070081 upload(wp);
bsalomon342bfc22016-04-01 06:06:20 -070082 }
83
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();
96 }
97
bsalomon75398562015-08-17 12:55:38 -070098private:
bsalomon75398562015-08-17 12:55:38 -070099
bsalomon342bfc22016-04-01 06:06:20 -0700100 GrGpu* fGpu;
bsalomon75398562015-08-17 12:55:38 -0700101
bsalomon342bfc22016-04-01 06:06:20 -0700102 GrResourceProvider* fResourceProvider;
bsalomon75398562015-08-17 12:55:38 -0700103
egdaniel9cb63402016-06-23 08:37:05 -0700104 GrGpuCommandBuffer* fCommandBuffer;
105
bsalomon342bfc22016-04-01 06:06:20 -0700106 GrVertexBufferAllocPool fVertexPool;
107 GrIndexBufferAllocPool fIndexPool;
bsalomon75398562015-08-17 12:55:38 -0700108
bsalomon342bfc22016-04-01 06:06:20 -0700109 SkSTArray<4, GrDrawBatch::DeferredUploadFn> fAsapUploads;
bsalomon75398562015-08-17 12:55:38 -0700110
bsalomon342bfc22016-04-01 06:06:20 -0700111 GrBatchDrawToken fLastIssuedToken;
112
113 GrBatchDrawToken fLastFlushedToken;
bsalomon75398562015-08-17 12:55:38 -0700114};
115
116/**
bsalomon342bfc22016-04-01 06:06:20 -0700117 * A word about uploads and tokens: Batches should usually schedule their uploads to occur at the
118 * begining of a frame whenever possible. These are called ASAP uploads. Of course, this requires
119 * that there are no draws that have yet to be flushed that rely on the old texture contents. In
120 * that case the ASAP upload would happen prior to the previous draw causing the draw to read the
121 * new (wrong) texture data. In that case they should schedule an inline upload.
122 *
123 * Batches, in conjunction with helpers such as GrBatchAtlas, can use the token system to know
124 * what the most recent draw was that referenced a resource (or portion of a resource). Each draw
125 * is assigned a token. A resource (or portion) can be tagged with the most recent draw's
126 * token. The target provides a facility for testing whether the draw corresponding to the token
127 * has been flushed. If it has not been flushed then the batch must perform an inline upload
128 * instead. When scheduling an inline upload the batch provides the token of the draw that the
129 * upload must occur before. The upload will then occur between the draw that requires the new
130 * data but after the token that requires the old data.
131 *
132 * TODO: Currently the token/upload interface is spread over GrDrawBatch, GrVertexBatch,
133 * GrDrawBatch::Target, and GrVertexBatch::Target. However, the interface at the GrDrawBatch
134 * level is not complete and isn't useful. We should push it down to GrVertexBatch until it
135 * is required at the GrDrawBatch level.
136 */
137
138/**
bsalomon75398562015-08-17 12:55:38 -0700139 * GrDrawBatch instances use this object to allocate space for their geometry and to issue the draws
140 * that render their batch.
141 */
142class GrDrawBatch::Target {
143public:
144 Target(GrBatchFlushState* state, GrDrawBatch* batch) : fState(state), fBatch(batch) {}
145
bsalomon342bfc22016-04-01 06:06:20 -0700146 /** Returns the token of the draw that this upload will occur before. */
147 GrBatchDrawToken addInlineUpload(DeferredUploadFn&& upload) {
148 fBatch->fInlineUploads.emplace_back(std::move(upload), fState->nextDrawToken());
149 return fBatch->fInlineUploads.back().fUploadBeforeToken;
bsalomon75398562015-08-17 12:55:38 -0700150 }
151
bsalomon342bfc22016-04-01 06:06:20 -0700152 /** Returns the token of the draw that this upload will occur before. Since ASAP uploads
153 are done first during a flush, this will be the first token since the most recent
154 flush. */
155 GrBatchDrawToken addAsapUpload(DeferredUploadFn&& upload) {
156 fState->addASAPUpload(std::move(upload));
157 return fState->nextTokenToFlush();
bsalomon75398562015-08-17 12:55:38 -0700158 }
bsalomon342bfc22016-04-01 06:06:20 -0700159
160 bool hasDrawBeenFlushed(GrBatchDrawToken token) const {
161 return fState->hasDrawBeenFlushed(token);
162 }
163
164 /** Gets the next draw token that will be issued by this target. This can be used by a batch
165 to record that the next draw it issues will use a resource (e.g. texture) while preparing
166 that draw. */
167 GrBatchDrawToken nextDrawToken() const { return fState->nextDrawToken(); }
bsalomon75398562015-08-17 12:55:38 -0700168
169 const GrCaps& caps() const { return fState->caps(); }
170
171 GrResourceProvider* resourceProvider() const { return fState->resourceProvider(); }
172
173protected:
174 GrDrawBatch* batch() { return fBatch; }
175 GrBatchFlushState* state() { return fState; }
176
177private:
178 GrBatchFlushState* fState;
179 GrDrawBatch* fBatch;
180};
181
182/** Extension of GrDrawBatch::Target for use by GrVertexBatch. Adds the ability to create vertex
183 draws. */
184class GrVertexBatch::Target : public GrDrawBatch::Target {
185public:
186 Target(GrBatchFlushState* state, GrVertexBatch* batch) : INHERITED(state, batch) {}
187
bsalomon342bfc22016-04-01 06:06:20 -0700188 void draw(const GrGeometryProcessor* gp, const GrMesh& mesh);
bsalomon75398562015-08-17 12:55:38 -0700189
190 void* makeVertexSpace(size_t vertexSize, int vertexCount,
cdalton397536c2016-03-25 12:15:03 -0700191 const GrBuffer** buffer, int* startVertex) {
bsalomon75398562015-08-17 12:55:38 -0700192 return this->state()->makeVertexSpace(vertexSize, vertexCount, buffer, startVertex);
193 }
194
cdalton397536c2016-03-25 12:15:03 -0700195 uint16_t* makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex) {
bsalomon75398562015-08-17 12:55:38 -0700196 return this->state()->makeIndexSpace(indexCount, buffer, startIndex);
197 }
198
199 /** Helpers for batches which over-allocate and then return data to the pool. */
200 void putBackIndices(int indices) { this->state()->putBackIndices(indices); }
201 void putBackVertices(int vertices, size_t vertexStride) {
202 this->state()->putBackVertexSpace(vertices * vertexStride);
203 }
204
205private:
206 GrVertexBatch* vertexBatch() { return static_cast<GrVertexBatch*>(this->batch()); }
207 typedef GrDrawBatch::Target INHERITED;
208};
209
210#endif