@@ -75,6 +75,140 @@ namespace Ogre {
75
75
*/
76
76
HBU_CPU_TO_GPU = HBU_CPU_ONLY | HBU_DETAIL_WRITE_ONLY,
77
77
};
78
+ /* * Abstract class defining common features of unstructured memory
79
+
80
+ This class defines the core interface which is common to all
81
+ buffers, whether it be vertex buffers, index buffers, texture memory
82
+ or framebuffer memory etc.
83
+ */
84
+ class _OgreExport Buffer
85
+ {
86
+ public:
87
+ // / Locking options
88
+ enum LockOptions
89
+ {
90
+ /* * Normal mode, ie allows read/write and contents are preserved.
91
+ This kind of lock allows reading and writing from the buffer - it’s also the least
92
+ optimal because basically you’re telling the card you could be doing anything at
93
+ all. If you’re not using a shadow buffer, it requires the buffer to be transferred
94
+ from the card and back again. If you’re using a shadow buffer the effect is
95
+ minimal.
96
+ */
97
+ HBL_NORMAL,
98
+ /* * Discards the <em>entire</em> buffer while locking.
99
+ This means you are happy for the card to discard the entire current contents of the
100
+ buffer. Implicitly this means you are not going to read the data - it also means
101
+ that the card can avoid any stalls if the buffer is currently being rendered from,
102
+ because it will actually give you an entirely different one. Use this wherever
103
+ possible when you are locking a buffer which was not created with a shadow buffer.
104
+ If you are using a shadow buffer it matters less, although with a shadow buffer it’s
105
+ preferable to lock the entire buffer at once, because that allows the shadow buffer
106
+ to use HBL_DISCARD when it uploads the updated contents to the real buffer.
107
+ @note Only useful on buffers created with the HBU_CPU_TO_GPU flag.
108
+ */
109
+ HBL_DISCARD,
110
+ /* * Lock the buffer for reading only. Not allowed in buffers which are created with
111
+ HBU_WRITE_ONLY.
112
+ Mandatory on static buffers, i.e. those created without the HBU_DYNAMIC flag.
113
+ */
114
+ HBL_READ_ONLY,
115
+ /* * As HBL_DISCARD, except the application guarantees not to overwrite any
116
+ region of the buffer which has already been used in this frame, can allow
117
+ some optimisation on some APIs.
118
+ @note Only useful on buffers with no shadow buffer.*/
119
+ HBL_NO_OVERWRITE,
120
+ /* * Lock the buffer for writing only.*/
121
+ HBL_WRITE_ONLY
122
+ };
123
+ Buffer (size_t sizeInBytes, int usage) : mSizeInBytes (sizeInBytes), mUsage (usage), mIsLocked (false ) {}
124
+
125
+ virtual ~Buffer () {}
126
+ /* * Reads data from the buffer and places it in the memory pointed to by pDest.
127
+ @param offset The byte offset from the start of the buffer to read
128
+ @param length The size of the area to read, in bytes
129
+ @param pDest The area of memory in which to place the data, must be large enough to
130
+ accommodate the data!
131
+ */
132
+ virtual void readData (size_t offset, size_t length, void * pDest) /* const */ = 0;
133
+ /* * Writes data to the buffer from an area of system memory; note that you must
134
+ ensure that your buffer is big enough.
135
+ @param offset The byte offset from the start of the buffer to start writing
136
+ @param length The size of the data to write to, in bytes
137
+ @param pSource The source of the data to be written
138
+ @param discardWholeBuffer If true, this allows the driver to discard the entire buffer when writing,
139
+ such that DMA stalls can be avoided; use if you can.
140
+ */
141
+ virtual void writeData (size_t offset, size_t length, const void * pSource, bool discardWholeBuffer = false ) = 0;
142
+
143
+ /* * Copy data from another buffer into this one.
144
+ @remarks
145
+ Note that the source buffer must not be created with the
146
+ usage HBU_WRITE_ONLY otherwise this will fail.
147
+ @param srcBuffer The buffer from which to read the copied data
148
+ @param srcOffset Offset in the source buffer at which to start reading
149
+ @param dstOffset Offset in the destination buffer to start writing
150
+ @param length Length of the data to copy, in bytes.
151
+ @param discardWholeBuffer If true, will discard the entire contents of this buffer before copying
152
+ */
153
+ virtual void copyData (HardwareBuffer& _srcBuffer, size_t srcOffset, size_t dstOffset, size_t length,
154
+ bool discardWholeBuffer = false )
155
+ {
156
+ auto & srcBuffer = (Buffer&)_srcBuffer; // backward compat
157
+ const void * srcData = srcBuffer.lock (srcOffset, length, HBL_READ_ONLY);
158
+ this ->writeData (dstOffset, length, srcData, discardWholeBuffer);
159
+ srcBuffer.unlock ();
160
+ }
161
+
162
+ /* * Copy all data from another buffer into this one.
163
+ @remarks
164
+ Normally these buffers should be of identical size, but if they're
165
+ not, the routine will use the smallest of the two sizes.
166
+ */
167
+ void copyData (HardwareBuffer& _srcBuffer)
168
+ {
169
+ auto & srcBuffer = (Buffer&)_srcBuffer; // backward compat
170
+ size_t sz = std::min (getSizeInBytes (), srcBuffer.getSizeInBytes ());
171
+ copyData (_srcBuffer, 0 , 0 , sz, true );
172
+ }
173
+
174
+ /* * Lock the buffer for (potentially) reading / writing.
175
+ @param offset The byte offset from the start of the buffer to lock
176
+ @param length The size of the area to lock, in bytes
177
+ @param options Locking options
178
+ @return Pointer to the locked memory
179
+ */
180
+ virtual void * lock (size_t offset, size_t length, LockOptions options) = 0;
181
+
182
+ // / @overload
183
+ void * lock (LockOptions options) { return this ->lock (0 , mSizeInBytes , options); }
184
+
185
+ /* * Releases the lock on this buffer.
186
+ @remarks
187
+ Locking and unlocking a buffer can, in some rare circumstances such as
188
+ switching video modes whilst the buffer is locked, corrupt the
189
+ contents of a buffer. This is pretty rare, but if it occurs,
190
+ this method will throw an exception, meaning you
191
+ must re-upload the data.
192
+ @par
193
+ Note that using the 'read' and 'write' forms of updating the buffer does not
194
+ suffer from this problem, so if you want to be 100% sure your
195
+ data will not be lost, use the 'read' and 'write' forms instead.
196
+ */
197
+ virtual void unlock () = 0;
198
+
199
+ // / Returns whether or not this buffer is currently locked.
200
+ virtual bool isLocked () const { return mIsLocked ; }
201
+ // / Returns the size of this buffer in bytes
202
+ size_t getSizeInBytes (void ) const { return mSizeInBytes ; }
203
+ // / Returns the Usage flags with which this buffer was created
204
+ int getUsage (void ) const { return mUsage ; }
205
+ protected:
206
+ size_t mSizeInBytes ;
207
+ int mUsage ;
208
+ bool mIsLocked ;
209
+ };
210
+
211
+
78
212
/* * Abstract class defining common features of hardware buffers.
79
213
@remarks
80
214
A 'hardware buffer' is any area of memory held outside of core system ram,
@@ -106,7 +240,7 @@ namespace Ogre {
106
240
You should look for the 'useShadowBuffer' parameter on the creation methods used to create
107
241
the buffer of the type you require (see HardwareBufferManager) to enable this feature.
108
242
*/
109
- class _OgreExport HardwareBuffer : public BufferAlloc
243
+ class _OgreExport HardwareBuffer : public Buffer
110
244
{
111
245
112
246
public:
@@ -129,50 +263,10 @@ namespace Ogre {
129
263
// / @deprecated do not use
130
264
HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE = HBU_CPU_TO_GPU,
131
265
};
132
- // / Locking options
133
- enum LockOptions
134
- {
135
- /* * Normal mode, ie allows read/write and contents are preserved.
136
- This kind of lock allows reading and writing from the buffer - it’s also the least
137
- optimal because basically you’re telling the card you could be doing anything at
138
- all. If you’re not using a shadow buffer, it requires the buffer to be transferred
139
- from the card and back again. If you’re using a shadow buffer the effect is
140
- minimal.
141
- */
142
- HBL_NORMAL,
143
- /* * Discards the <em>entire</em> buffer while locking.
144
- This means you are happy for the card to discard the entire current contents of the
145
- buffer. Implicitly this means you are not going to read the data - it also means
146
- that the card can avoid any stalls if the buffer is currently being rendered from,
147
- because it will actually give you an entirely different one. Use this wherever
148
- possible when you are locking a buffer which was not created with a shadow buffer.
149
- If you are using a shadow buffer it matters less, although with a shadow buffer it’s
150
- preferable to lock the entire buffer at once, because that allows the shadow buffer
151
- to use HBL_DISCARD when it uploads the updated contents to the real buffer.
152
- @note Only useful on buffers created with the HBU_CPU_TO_GPU flag.
153
- */
154
- HBL_DISCARD,
155
- /* * Lock the buffer for reading only. Not allowed in buffers which are created with
156
- HBU_WRITE_ONLY.
157
- Mandatory on static buffers, i.e. those created without the HBU_DYNAMIC flag.
158
- */
159
- HBL_READ_ONLY,
160
- /* * As HBL_DISCARD, except the application guarantees not to overwrite any
161
- region of the buffer which has already been used in this frame, can allow
162
- some optimisation on some APIs.
163
- @note Only useful on buffers with no shadow buffer.*/
164
- HBL_NO_OVERWRITE,
165
- /* * Lock the buffer for writing only.*/
166
- HBL_WRITE_ONLY
167
-
168
- };
169
266
protected:
170
- size_t mSizeInBytes ;
171
- Usage mUsage ;
172
- bool mIsLocked ;
173
267
size_t mLockStart ;
174
268
size_t mLockSize ;
175
- std::unique_ptr<HardwareBuffer > mShadowBuffer ;
269
+ std::unique_ptr<Buffer > mShadowBuffer ;
176
270
bool mSystemMemory ;
177
271
bool mUseShadowBuffer ;
178
272
bool mShadowUpdated ;
@@ -186,7 +280,7 @@ namespace Ogre {
186
280
public:
187
281
// / Constructor, to be called by HardwareBufferManager only
188
282
HardwareBuffer (Usage usage, bool systemMemory, bool useShadowBuffer)
189
- : mSizeInBytes ( 0 ), mUsage ( usage), mIsLocked ( false ), mLockStart (0 ), mLockSize (0 ), mSystemMemory (systemMemory),
283
+ : Buffer( 0 , usage), mLockStart (0 ), mLockSize (0 ), mSystemMemory (systemMemory),
190
284
mUseShadowBuffer (useShadowBuffer), mShadowUpdated(false ),
191
285
mSuppressHardwareUpdate(false )
192
286
{
@@ -200,14 +294,10 @@ namespace Ogre {
200
294
mUsage = HBU_STATIC_WRITE_ONLY;
201
295
}
202
296
}
203
- virtual ~HardwareBuffer () {}
204
- /* * Lock the buffer for (potentially) reading / writing.
205
- @param offset The byte offset from the start of the buffer to lock
206
- @param length The size of the area to lock, in bytes
207
- @param options Locking options
208
- @return Pointer to the locked memory
209
- */
210
- virtual void * lock (size_t offset, size_t length, LockOptions options)
297
+
298
+ using Buffer::lock;
299
+
300
+ void * lock (size_t offset, size_t length, LockOptions options) override
211
301
{
212
302
OgreAssert (!isLocked (), " Cannot lock this buffer: it is already locked" );
213
303
OgreAssert ((length + offset) <= mSizeInBytes , " Lock request out of bounds" );
@@ -235,24 +325,7 @@ namespace Ogre {
235
325
return ret;
236
326
}
237
327
238
- // / @overload
239
- void * lock (LockOptions options)
240
- {
241
- return this ->lock (0 , mSizeInBytes , options);
242
- }
243
- /* * Releases the lock on this buffer.
244
- @remarks
245
- Locking and unlocking a buffer can, in some rare circumstances such as
246
- switching video modes whilst the buffer is locked, corrupt the
247
- contents of a buffer. This is pretty rare, but if it occurs,
248
- this method will throw an exception, meaning you
249
- must re-upload the data.
250
- @par
251
- Note that using the 'read' and 'write' forms of updating the buffer does not
252
- suffer from this problem, so if you want to be 100% sure your
253
- data will not be lost, use the 'read' and 'write' forms instead.
254
- */
255
- virtual void unlock (void )
328
+ void unlock (void ) override
256
329
{
257
330
OgreAssert (isLocked (), " Cannot unlock this buffer: it is not locked" );
258
331
@@ -272,89 +345,27 @@ namespace Ogre {
272
345
273
346
}
274
347
275
- /* * Reads data from the buffer and places it in the memory pointed to by pDest.
276
- @param offset The byte offset from the start of the buffer to read
277
- @param length The size of the area to read, in bytes
278
- @param pDest The area of memory in which to place the data, must be large enough to
279
- accommodate the data!
280
- */
281
- virtual void readData (size_t offset, size_t length, void * pDest) = 0;
282
- /* * Writes data to the buffer from an area of system memory; note that you must
283
- ensure that your buffer is big enough.
284
- @param offset The byte offset from the start of the buffer to start writing
285
- @param length The size of the data to write to, in bytes
286
- @param pSource The source of the data to be written
287
- @param discardWholeBuffer If true, this allows the driver to discard the entire buffer when writing,
288
- such that DMA stalls can be avoided; use if you can.
289
- */
290
- virtual void writeData (size_t offset, size_t length, const void * pSource,
291
- bool discardWholeBuffer = false ) = 0;
292
-
293
- /* * Copy data from another buffer into this one.
294
- @remarks
295
- Note that the source buffer must not be created with the
296
- usage HBU_WRITE_ONLY otherwise this will fail.
297
- @param srcBuffer The buffer from which to read the copied data
298
- @param srcOffset Offset in the source buffer at which to start reading
299
- @param dstOffset Offset in the destination buffer to start writing
300
- @param length Length of the data to copy, in bytes.
301
- @param discardWholeBuffer If true, will discard the entire contents of this buffer before copying
302
- */
303
- virtual void copyData (HardwareBuffer& srcBuffer, size_t srcOffset,
304
- size_t dstOffset, size_t length, bool discardWholeBuffer = false )
305
- {
306
- const void *srcData = srcBuffer.lock (
307
- srcOffset, length, HBL_READ_ONLY);
308
- this ->writeData (dstOffset, length, srcData, discardWholeBuffer);
309
- srcBuffer.unlock ();
310
- }
311
-
312
- /* * Copy all data from another buffer into this one.
313
- @remarks
314
- Normally these buffers should be of identical size, but if they're
315
- not, the routine will use the smallest of the two sizes.
316
- */
317
- virtual void copyData (HardwareBuffer& srcBuffer)
318
- {
319
- size_t sz = std::min (getSizeInBytes (), srcBuffer.getSizeInBytes ());
320
- copyData (srcBuffer, 0 , 0 , sz, true );
321
- }
322
-
323
348
// / Updates the real buffer from the shadow buffer, if required
324
349
virtual void _updateFromShadow (void )
325
350
{
326
351
if (mUseShadowBuffer && mShadowUpdated && !mSuppressHardwareUpdate )
327
352
{
328
- // Do this manually to avoid locking problems
329
- const void *srcData = mShadowBuffer ->lockImpl (
330
- mLockStart , mLockSize , HBL_READ_ONLY);
331
353
// Lock with discard if the whole buffer was locked, otherwise w/o
332
- LockOptions lockOpt;
333
- if (mLockStart == 0 && mLockSize == mSizeInBytes )
334
- lockOpt = HBL_DISCARD;
335
- else
336
- lockOpt = HBL_WRITE_ONLY;
337
-
338
- void *destData = this ->lockImpl (
339
- mLockStart , mLockSize , lockOpt);
354
+ LockOptions lockOpt = mLockSize == mSizeInBytes ? HBL_DISCARD : HBL_WRITE_ONLY;
355
+ // Do this manually to avoid locking problems
356
+ void * destData = this ->lockImpl (mLockStart , mLockSize , lockOpt);
340
357
// Copy shadow to real
341
- memcpy (destData, srcData, mLockSize );
358
+ mShadowBuffer -> readData ( mLockStart , mLockSize , destData );
342
359
this ->unlockImpl ();
343
- mShadowBuffer ->unlockImpl ();
344
360
mShadowUpdated = false ;
345
361
}
346
362
}
347
363
348
- // / Returns the size of this buffer in bytes
349
- size_t getSizeInBytes (void ) const { return mSizeInBytes ; }
350
- // / Returns the Usage flags with which this buffer was created
351
- Usage getUsage (void ) const { return mUsage ; }
352
364
// / Returns whether this buffer is held in system memory
353
365
bool isSystemMemory (void ) const { return mSystemMemory ; }
354
366
// / Returns whether this buffer has a system memory shadow for quicker reading
355
367
bool hasShadowBuffer (void ) const { return mUseShadowBuffer ; }
356
- // / Returns whether or not this buffer is currently locked.
357
- bool isLocked (void ) const {
368
+ bool isLocked (void ) const override {
358
369
return mIsLocked || (mUseShadowBuffer && mShadowBuffer ->isLocked ());
359
370
}
360
371
// / Pass true to suppress hardware upload of shadow buffer changes
@@ -375,10 +386,10 @@ namespace Ogre {
375
386
{
376
387
HardwareBufferLockGuard () : pBuf(0 ), pData(0 ) {}
377
388
378
- HardwareBufferLockGuard (HardwareBuffer * p, HardwareBuffer::LockOptions options)
389
+ HardwareBufferLockGuard (Buffer * p, HardwareBuffer::LockOptions options)
379
390
: pBuf(0 ), pData(0 ) { lock (p, options); }
380
391
381
- HardwareBufferLockGuard (HardwareBuffer * p, size_t offset, size_t length, HardwareBuffer::LockOptions options)
392
+ HardwareBufferLockGuard (Buffer * p, size_t offset, size_t length, HardwareBuffer::LockOptions options)
382
393
: pBuf(0 ), pData(0 ) { lock (p, offset, length, options); }
383
394
384
395
template <typename T>
@@ -401,15 +412,15 @@ namespace Ogre {
401
412
}
402
413
}
403
414
404
- void lock (HardwareBuffer * p, HardwareBuffer::LockOptions options)
415
+ void lock (Buffer * p, HardwareBuffer::LockOptions options)
405
416
{
406
417
assert (p);
407
418
unlock ();
408
419
pBuf = p;
409
420
pData = pBuf->lock (options);
410
421
}
411
422
412
- void lock (HardwareBuffer * p, size_t offset, size_t length, HardwareBuffer::LockOptions options)
423
+ void lock (Buffer * p, size_t offset, size_t length, HardwareBuffer::LockOptions options)
413
424
{
414
425
assert (p);
415
426
unlock ();
@@ -425,7 +436,7 @@ namespace Ogre {
425
436
void lock (const SharedPtr<T>& p, size_t offset, size_t length, HardwareBuffer::LockOptions options)
426
437
{ lock (p.get (), offset, length, options); }
427
438
428
- HardwareBuffer * pBuf;
439
+ Buffer * pBuf;
429
440
void * pData;
430
441
};
431
442
0 commit comments