Skip to content

Commit 05d9d27

Browse files
committed
Main: factor out generic Buffer interface to use for dumb buffers
1 parent 9d64433 commit 05d9d27

File tree

1 file changed

+134
-100
lines changed

1 file changed

+134
-100
lines changed

OgreMain/include/OgreHardwareBuffer.h

+134-100
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,124 @@ namespace Ogre {
7575
*/
7676
HBU_CPU_TO_GPU = HBU_CPU_ONLY | HBU_DETAIL_WRITE_ONLY,
7777
};
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. Only
107+
allowed on buffers
108+
created with the HBU_DYNAMIC flag.
109+
*/
110+
HBL_DISCARD,
111+
/** Lock the buffer for reading only. Not allowed in buffers which are created with
112+
HBU_WRITE_ONLY.
113+
Mandatory on static buffers, i.e. those created without the HBU_DYNAMIC flag.
114+
*/
115+
HBL_READ_ONLY,
116+
/** As HBL_DISCARD, except the application guarantees not to overwrite any
117+
region of the buffer which has already been used in this frame, can allow
118+
some optimisation on some APIs.
119+
This is only useful on buffers with no shadow buffer.*/
120+
HBL_NO_OVERWRITE,
121+
/** Lock the buffer for writing only.*/
122+
HBL_WRITE_ONLY
123+
124+
};
125+
Buffer(size_t sizeInBytes, int usage) : mSizeInBytes(sizeInBytes), mUsage(usage) {}
126+
127+
virtual ~Buffer() {}
128+
/** Reads data from the buffer and places it in the memory pointed to by pDest.
129+
@param offset The byte offset from the start of the buffer to read
130+
@param length The size of the area to read, in bytes
131+
@param pDest The area of memory in which to place the data, must be large enough to
132+
accommodate the data!
133+
*/
134+
virtual void readData(size_t offset, size_t length, void* pDest) = 0;
135+
/** Writes data to the buffer from an area of system memory; note that you must
136+
ensure that your buffer is big enough.
137+
@param offset The byte offset from the start of the buffer to start writing
138+
@param length The size of the data to write to, in bytes
139+
@param pSource The source of the data to be written
140+
@param discardWholeBuffer If true, this allows the driver to discard the entire buffer when writing,
141+
such that DMA stalls can be avoided; use if you can.
142+
*/
143+
virtual void writeData(size_t offset, size_t length, const void* pSource, bool discardWholeBuffer = false) = 0;
144+
145+
/** Copy data from another buffer into this one.
146+
@remarks
147+
Note that the source buffer must not be created with the
148+
usage HBU_WRITE_ONLY otherwise this will fail.
149+
@param srcBuffer The buffer from which to read the copied data
150+
@param srcOffset Offset in the source buffer at which to start reading
151+
@param dstOffset Offset in the destination buffer to start writing
152+
@param length Length of the data to copy, in bytes.
153+
@param discardWholeBuffer If true, will discard the entire contents of this buffer before copying
154+
*/
155+
virtual void copyData(HardwareBuffer& srcBuffer, size_t srcOffset, size_t dstOffset, size_t length,
156+
bool discardWholeBuffer = false) = 0;
157+
158+
/** Lock the buffer for (potentially) reading / writing.
159+
@param offset The byte offset from the start of the buffer to lock
160+
@param length The size of the area to lock, in bytes
161+
@param options Locking options
162+
@return Pointer to the locked memory
163+
*/
164+
virtual void* lock(size_t offset, size_t length, LockOptions options) = 0;
165+
166+
/// @overload
167+
void* lock(LockOptions options) { return this->lock(0, mSizeInBytes, options); }
168+
169+
/** Releases the lock on this buffer.
170+
@remarks
171+
Locking and unlocking a buffer can, in some rare circumstances such as
172+
switching video modes whilst the buffer is locked, corrupt the
173+
contents of a buffer. This is pretty rare, but if it occurs,
174+
this method will throw an exception, meaning you
175+
must re-upload the data.
176+
@par
177+
Note that using the 'read' and 'write' forms of updating the buffer does not
178+
suffer from this problem, so if you want to be 100% sure your
179+
data will not be lost, use the 'read' and 'write' forms instead.
180+
*/
181+
virtual void unlock() = 0;
182+
183+
/// Returns whether or not this buffer is currently locked.
184+
virtual bool isLocked() const = 0;
185+
186+
/// Returns the size of this buffer in bytes
187+
size_t getSizeInBytes(void) const { return mSizeInBytes; }
188+
/// Returns the Usage flags with which this buffer was created
189+
int getUsage(void) const { return mUsage; }
190+
protected:
191+
size_t mSizeInBytes;
192+
int mUsage;
193+
};
194+
195+
78196
/** Abstract class defining common features of hardware buffers.
79197
@remarks
80198
A 'hardware buffer' is any area of memory held outside of core system ram,
@@ -106,7 +224,7 @@ namespace Ogre {
106224
You should look for the 'useShadowBuffer' parameter on the creation methods used to create
107225
the buffer of the type you require (see HardwareBufferManager) to enable this feature.
108226
*/
109-
class _OgreExport HardwareBuffer : public BufferAlloc
227+
class _OgreExport HardwareBuffer : public Buffer
110228
{
111229

112230
public:
@@ -129,47 +247,7 @@ namespace Ogre {
129247
/// @deprecated do not use
130248
HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE = HBU_CPU_TO_GPU,
131249
};
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. Only
152-
allowed on buffers
153-
created with the HBU_DYNAMIC flag.
154-
*/
155-
HBL_DISCARD,
156-
/** Lock the buffer for reading only. Not allowed in buffers which are created with
157-
HBU_WRITE_ONLY.
158-
Mandatory on static buffers, i.e. those created without the HBU_DYNAMIC flag.
159-
*/
160-
HBL_READ_ONLY,
161-
/** As HBL_DISCARD, except the application guarantees not to overwrite any
162-
region of the buffer which has already been used in this frame, can allow
163-
some optimisation on some APIs.
164-
This is only useful on buffers with no shadow buffer.*/
165-
HBL_NO_OVERWRITE,
166-
/** Lock the buffer for writing only.*/
167-
HBL_WRITE_ONLY
168-
169-
};
170250
protected:
171-
size_t mSizeInBytes;
172-
Usage mUsage;
173251
bool mIsLocked;
174252
size_t mLockStart;
175253
size_t mLockSize;
@@ -184,10 +262,10 @@ namespace Ogre {
184262
/// Internal implementation of unlock()
185263
virtual void unlockImpl(void) = 0;
186264

187-
public:
265+
public:
188266
/// Constructor, to be called by HardwareBufferManager only
189267
HardwareBuffer(Usage usage, bool systemMemory, bool useShadowBuffer)
190-
: mSizeInBytes(0), mUsage(usage), mIsLocked(false), mLockStart(0), mLockSize(0), mSystemMemory(systemMemory),
268+
: Buffer(0, usage), mIsLocked(false), mLockStart(0), mLockSize(0), mSystemMemory(systemMemory),
191269
mUseShadowBuffer(useShadowBuffer), mShadowUpdated(false),
192270
mSuppressHardwareUpdate(false)
193271
{
@@ -201,14 +279,10 @@ namespace Ogre {
201279
mUsage = HBU_STATIC_WRITE_ONLY;
202280
}
203281
}
204-
virtual ~HardwareBuffer() {}
205-
/** Lock the buffer for (potentially) reading / writing.
206-
@param offset The byte offset from the start of the buffer to lock
207-
@param length The size of the area to lock, in bytes
208-
@param options Locking options
209-
@return Pointer to the locked memory
210-
*/
211-
virtual void* lock(size_t offset, size_t length, LockOptions options)
282+
283+
using Buffer::lock;
284+
285+
void* lock(size_t offset, size_t length, LockOptions options) override
212286
{
213287
OgreAssert(!isLocked(), "Cannot lock this buffer: it is already locked");
214288
OgreAssert((length + offset) <= mSizeInBytes, "Lock request out of bounds");
@@ -236,24 +310,7 @@ namespace Ogre {
236310
return ret;
237311
}
238312

239-
/// @overload
240-
void* lock(LockOptions options)
241-
{
242-
return this->lock(0, mSizeInBytes, options);
243-
}
244-
/** Releases the lock on this buffer.
245-
@remarks
246-
Locking and unlocking a buffer can, in some rare circumstances such as
247-
switching video modes whilst the buffer is locked, corrupt the
248-
contents of a buffer. This is pretty rare, but if it occurs,
249-
this method will throw an exception, meaning you
250-
must re-upload the data.
251-
@par
252-
Note that using the 'read' and 'write' forms of updating the buffer does not
253-
suffer from this problem, so if you want to be 100% sure your
254-
data will not be lost, use the 'read' and 'write' forms instead.
255-
*/
256-
virtual void unlock(void)
313+
void unlock(void) override
257314
{
258315
OgreAssert(isLocked(), "Cannot unlock this buffer: it is not locked");
259316

@@ -273,24 +330,6 @@ namespace Ogre {
273330

274331
}
275332

276-
/** Reads data from the buffer and places it in the memory pointed to by pDest.
277-
@param offset The byte offset from the start of the buffer to read
278-
@param length The size of the area to read, in bytes
279-
@param pDest The area of memory in which to place the data, must be large enough to
280-
accommodate the data!
281-
*/
282-
virtual void readData(size_t offset, size_t length, void* pDest) = 0;
283-
/** Writes data to the buffer from an area of system memory; note that you must
284-
ensure that your buffer is big enough.
285-
@param offset The byte offset from the start of the buffer to start writing
286-
@param length The size of the data to write to, in bytes
287-
@param pSource The source of the data to be written
288-
@param discardWholeBuffer If true, this allows the driver to discard the entire buffer when writing,
289-
such that DMA stalls can be avoided; use if you can.
290-
*/
291-
virtual void writeData(size_t offset, size_t length, const void* pSource,
292-
bool discardWholeBuffer = false) = 0;
293-
294333
/** Copy data from another buffer into this one.
295334
@remarks
296335
Note that the source buffer must not be created with the
@@ -301,8 +340,8 @@ namespace Ogre {
301340
@param length Length of the data to copy, in bytes.
302341
@param discardWholeBuffer If true, will discard the entire contents of this buffer before copying
303342
*/
304-
virtual void copyData(HardwareBuffer& srcBuffer, size_t srcOffset,
305-
size_t dstOffset, size_t length, bool discardWholeBuffer = false)
343+
void copyData(HardwareBuffer& srcBuffer, size_t srcOffset, size_t dstOffset, size_t length,
344+
bool discardWholeBuffer = false) override
306345
{
307346
const void *srcData = srcBuffer.lock(
308347
srcOffset, length, HBL_READ_ONLY);
@@ -346,16 +385,11 @@ namespace Ogre {
346385
}
347386
}
348387

349-
/// Returns the size of this buffer in bytes
350-
size_t getSizeInBytes(void) const { return mSizeInBytes; }
351-
/// Returns the Usage flags with which this buffer was created
352-
Usage getUsage(void) const { return mUsage; }
353388
/// Returns whether this buffer is held in system memory
354389
bool isSystemMemory(void) const { return mSystemMemory; }
355390
/// Returns whether this buffer has a system memory shadow for quicker reading
356391
bool hasShadowBuffer(void) const { return mUseShadowBuffer; }
357-
/// Returns whether or not this buffer is currently locked.
358-
bool isLocked(void) const {
392+
bool isLocked(void) const override {
359393
return mIsLocked || (mUseShadowBuffer && mShadowBuffer->isLocked());
360394
}
361395
/// Pass true to suppress hardware upload of shadow buffer changes
@@ -376,10 +410,10 @@ namespace Ogre {
376410
{
377411
HardwareBufferLockGuard() : pBuf(0), pData(0) {}
378412

379-
HardwareBufferLockGuard(HardwareBuffer* p, HardwareBuffer::LockOptions options)
413+
HardwareBufferLockGuard(Buffer* p, HardwareBuffer::LockOptions options)
380414
: pBuf(0), pData(0) { lock(p, options); }
381415

382-
HardwareBufferLockGuard(HardwareBuffer* p, size_t offset, size_t length, HardwareBuffer::LockOptions options)
416+
HardwareBufferLockGuard(Buffer* p, size_t offset, size_t length, HardwareBuffer::LockOptions options)
383417
: pBuf(0), pData(0) { lock(p, offset, length, options); }
384418

385419
template <typename T>
@@ -402,15 +436,15 @@ namespace Ogre {
402436
}
403437
}
404438

405-
void lock(HardwareBuffer* p, HardwareBuffer::LockOptions options)
439+
void lock(Buffer* p, HardwareBuffer::LockOptions options)
406440
{
407441
assert(p);
408442
unlock();
409443
pBuf = p;
410444
pData = pBuf->lock(options);
411445
}
412446

413-
void lock(HardwareBuffer* p, size_t offset, size_t length, HardwareBuffer::LockOptions options)
447+
void lock(Buffer* p, size_t offset, size_t length, HardwareBuffer::LockOptions options)
414448
{
415449
assert(p);
416450
unlock();
@@ -426,7 +460,7 @@ namespace Ogre {
426460
void lock(const SharedPtr<T>& p, size_t offset, size_t length, HardwareBuffer::LockOptions options)
427461
{ lock(p.get(), offset, length, options); }
428462

429-
HardwareBuffer* pBuf;
463+
Buffer* pBuf;
430464
void* pData;
431465
};
432466

0 commit comments

Comments
 (0)