Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(266)

Side by Side Diff: src/gpu/GrCmdBuffer.h

Issue 628453002: Create a single command buffer for GrInOrderDrawBuffer (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gyp/gpu.gypi ('k') | src/gpu/GrInOrderDrawBuffer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2014 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 GrCmdBuffer_DEFINED
9 #define GrCmdBuffer_DEFINED
10
11 #include "SkTemplates.h"
12 #include "SkTypes.h"
13
14 class GrDrawTarget;
15
16 /**
17 * Ordered list of commands for a GrDrawTarget.
18 *
19 * The commands are stored contiguously within large blocks of memory, in order avoid
20 * excessive calls to malloc().
21 *
22 * @param TAlign A type whose size is the desired alignment for command allocat ions.
23 * Using long double will always meet alignment requirements, but this may
24 * be smaller if the largest alignment requirement is know ahead of time.
25 */
26 template<typename TAlign = long double> class GrCmdBuffer : SkNoncopyable {
bsalomon 2014/10/03 15:04:45 Do long doubles require alignment? Wondering if vo
Chris Dalton 2014/10/03 16:16:24 According to this, long double gets aligned at 16
bsalomon 2014/10/03 18:43:03 Interesting. Maybe just have no default?
Chris Dalton 2014/10/03 19:38:40 Sure
Chris Dalton 2014/10/08 19:29:02 Done.
27 public:
28 class Cmd;
29 class Iter;
30
31 /**
32 * Create a command buffer
33 *
34 * @param initialSizeInBytes The amount of memory reserved by the command b uffer
35 * initially, and after calls to reset().
36 */
37 GrCmdBuffer(int initialSizeInBytes)
38 : fHeadBlock(bytes_to_length(initialSizeInBytes)),
39 fTailBlock(&fHeadBlock),
40 fBack(0),
41 fFirstCmd(NULL),
42 fLastCmd(NULL) {}
43
44 ~GrCmdBuffer() { this->reset(); }
45
46 bool empty() {
47 SkASSERT((NULL == fFirstCmd) == (NULL == fLastCmd));
48 return NULL == fFirstCmd;
49 }
50
51 Cmd& front() {
52 SkASSERT(!this->empty());
53 return *fFirstCmd;
54 }
55
56 Cmd& back() {
57 SkASSERT(!this->empty());
58 return *fLastCmd;
59 }
60
61 /**
62 * Destruct all commands in the command buffer and reset to empty.
63 */
64 void reset();
65
66 /**
67 * Push a command to the back of the buffer, with optional arguments to for its
68 * constructor. TCmd must be a subclass of GrCmdBuffer::Cmd.
69 */
70 template<typename TCmd>
71 TCmd& push_back() { return this->push_back_size<TCmd>(sizeof(TCmd)); }
bsalomon 2014/10/03 15:04:45 Instead of all these could we use something like a
Chris Dalton 2014/10/03 16:16:24 I did consider that approach. The only problem is
bsalomon 2014/10/03 18:43:03 In the other instances where we've done this we ju
Chris Dalton 2014/10/03 19:38:40 Ok, this will work now. (The issue used to be that
Chris Dalton 2014/10/08 19:29:02 Done.
72 template<typename TCmd, typename TArg1>
73 TCmd& push_back(const TArg1& a) { return this->push_back_size<TCmd>(sizeof(T Cmd), a); }
74 template<typename TCmd, typename TArg1, typename TArg2>
75 TCmd& push_back(const TArg1& a, const TArg2& b) { return this->push_back_siz e<TCmd>(sizeof(TCmd), a, b); }
76 template<typename TCmd, typename TArg1, typename TArg2, typename TArg3>
77 TCmd& push_back(const TArg1& a, const TArg2& b, const TArg3& c) { return thi s->push_back_size<TCmd>(sizeof(TCmd), a, b, c); }
78
79 /**
80 * Push a variable-size command to the back of the buffer, with optional arg uments for
81 * its constructor. TCmd must be a subclass of GrCmdBuffer::Cmd.
82 *
83 * @param sizeInBytes The amount of memory to allocate for the command. Thi s may be
bsalomon 2014/10/03 15:04:45 Wonder whether we should only take the extra paylo
Chris Dalton 2014/10/03 16:16:24 The Cmd base class could also maybe know where to
bsalomon 2014/10/03 18:43:03 Sure but then we need to store ptr. If it's a para
Chris Dalton 2014/10/03 19:38:40 So at execute time, the client code doesn't know w
Chris Dalton 2014/10/08 19:29:02 Left as-is for now, to resemble the way this would
84 * larger than sizeof(TCmd) to accomodate variable-lengt h arrays.
85 */
86 template<typename TCmd>
87 TCmd& push_back_size(int sizeInBytes);
88 template<typename TCmd, typename TArg1>
89 TCmd& push_back_size(int sizeInBytes, const TArg1&);
90 template<typename TCmd, typename TArg1, typename TArg2>
91 TCmd& push_back_size(int sizeInBytes, const TArg1&, const TArg2&);
92 template<typename TCmd, typename TArg1, typename TArg2, typename TArg3>
93 TCmd& push_back_size(int sizeInBytes, const TArg1&, const TArg2&, const TArg 3&);
94
95 private:
96 static int bytes_to_length(int bytes) { return (bytes + sizeof(TAlign) - 1) / sizeof(TAlign); }
97
98 void* push_back_raw(int sizeInBytes);
99 template<typename T> T& init_back(T* cmd);
100
101 struct Block {
102 Block(int length) : fLength(length), fBuffer(fLength) {}
103 const int fLength;
104 SkAutoTMalloc<TAlign> fBuffer;
105 SkAutoTDelete<Block> fNext;
106 };
107 Block fHeadBlock;
108 Block* fTailBlock;
109 int fBack;
110
111 Cmd* fFirstCmd;
112 Cmd* fLastCmd;
113
114 friend class Iter;
115 };
116
117 ////////////////////////////////////////////////////////////////////////////////
118
119 template<typename TAlign>
120 class GrCmdBuffer<TAlign>::Cmd : SkNoncopyable {
121 public:
122 Cmd() : fNext(NULL) {}
123 virtual ~Cmd() {}
124 virtual void execute(GrDrawTarget*) = 0;
125
126 uint8_t type() const { return fType; }
127 void resetType(uint8_t type) { fType = type; }
128
129 private:
130 Cmd* fNext;
131 uint8_t fType;
bsalomon 2014/10/03 15:04:45 Is the type really just just used to hang the debu
Chris Dalton 2014/10/03 16:16:24 At least for now, concatInstancedDraw() also check
bsalomon 2014/10/03 18:43:03 The GrIODB could just have a bool, fLastCmdWasDraw
Chris Dalton 2014/10/03 19:38:40 Oh, fLastCmdWasDraw, I like that
Chris Dalton 2014/10/08 19:29:02 I ended up leaving fType in the base Cmd class. It
132
133 friend class GrCmdBuffer;
134 };
135
136 template<typename TAlign>
137 class GrCmdBuffer<TAlign>::Iter {
138 public:
139 Iter(GrCmdBuffer& cmdBuffer) : fCmd(NULL), fNext(cmdBuffer.fFirstCmd) {}
140
141 bool next() {
142 if (NULL == fNext) {
143 return false;
144 }
145 fCmd = fNext;
146 fNext = fCmd->fNext;
147 return true;
148 }
149
150 Cmd* operator->() {
151 SkASSERT(fCmd);
152 return fCmd;
153 }
154
155 private:
156 Cmd* fCmd;
157 Cmd* fNext;
158 };
159
160 template<typename TAlign>
161 void GrCmdBuffer<TAlign>::reset() {
162 Iter iter(*this);
163 while (iter.next()) {
164 iter->~Cmd();
165 }
166 fHeadBlock.fNext.free();
167 fTailBlock = &fHeadBlock;
168 fBack = 0;
169 fFirstCmd = fLastCmd = NULL;
170 }
171
172 template<typename TAlign>
173 void* GrCmdBuffer<TAlign>::push_back_raw(int sizeInBytes) {
174 const int cmdLength = bytes_to_length(sizeInBytes);
175
176 if (fBack + cmdLength > fTailBlock->fLength) {
177 SkASSERT(NULL == fTailBlock->fNext.get());
178 Block* next = SkNEW_ARGS(Block, (SkTMax(2 * fTailBlock->fLength, cmdLeng th)));
179 fTailBlock->fNext.reset(next);
180 fTailBlock = next;
181 fBack = 0;
182 }
183
184 void* data = &fTailBlock->fBuffer[fBack];
185 fBack += cmdLength;
186 return data;
187 }
188
189 template<typename TAlign>
190 template<typename T>
191 T& GrCmdBuffer<TAlign>::init_back(T* cmd) {
192 cmd->fType = T::kCmdType;
193 if (NULL == fFirstCmd) {
194 SkASSERT(NULL == fLastCmd);
195 fFirstCmd = fLastCmd = cmd;
196 } else {
197 SkASSERT(NULL != fLastCmd);
198 fLastCmd->fNext = cmd;
199 fLastCmd = cmd;
200 }
201 return *cmd;
202 }
203
204 template<typename TAlign>
205 template<typename TCmd>
206 TCmd& GrCmdBuffer<TAlign>::push_back_size(int sizeInBytes) {
207 SkASSERT(sizeInBytes >= (int)sizeof(TCmd));
208 TCmd* cmd = SkNEW_PLACEMENT(this->push_back_raw(sizeInBytes), TCmd);
209 return this->init_back(cmd);
210 }
211
212 template<typename TAlign>
213 template<typename TCmd, typename TArg1>
214 TCmd& GrCmdBuffer<TAlign>::push_back_size(int sizeInBytes, const TArg1& a) {
215 SkASSERT(sizeInBytes >= (int)sizeof(TCmd));
216 TCmd* cmd = SkNEW_PLACEMENT_ARGS(this->push_back_raw(sizeInBytes), TCmd, (a) );
217 return this->init_back(cmd);
218 }
219
220 template<typename TAlign>
221 template<typename TCmd, typename TArg1, typename TArg2>
222 TCmd& GrCmdBuffer<TAlign>::push_back_size(int sizeInBytes, const TArg1& a, const TArg2& b) {
223 SkASSERT(sizeInBytes >= (int)sizeof(TCmd));
224 TCmd* cmd = SkNEW_PLACEMENT_ARGS(this->push_back_raw(sizeInBytes), TCmd, (a, b));
225 return this->init_back(cmd);
226 }
227
228 template<typename TAlign>
229 template<typename TCmd, typename TArg1, typename TArg2, typename TArg3>
230 TCmd& GrCmdBuffer<TAlign>::push_back_size(int sizeInBytes, const TArg1& a, const TArg2& b, const TArg3& c) {
231 SkASSERT(sizeInBytes >= (int)sizeof(TCmd));
232 TCmd* cmd = SkNEW_PLACEMENT_ARGS(this->push_back_raw(sizeInBytes), TCmd, (a, b, c));
233 return this->init_back(cmd);
234 }
235
236 #endif
OLDNEW
« no previous file with comments | « gyp/gpu.gypi ('k') | src/gpu/GrInOrderDrawBuffer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698