Skip to content

Commit cc4ea5a

Browse files
committed
Main: add lightweight DefaultBuffer class for shadow buffering
1 parent 8aa3028 commit cc4ea5a

8 files changed

+84
-59
lines changed

OgreMain/include/OgreDefaultHardwareBufferManager.h

+16
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,22 @@ namespace Ogre {
4343
* @{
4444
*/
4545

46+
/// Specialisation of Buffer using malloc e.g. for use as shadow buffer
47+
class _OgreExport DefaultBuffer : public Buffer
48+
{
49+
protected:
50+
unsigned char* mData;
51+
void* lockImpl(size_t offset, size_t length, LockOptions options);
52+
void unlockImpl(void);
53+
public:
54+
explicit DefaultBuffer(size_t sizeInBytes);
55+
~DefaultBuffer();
56+
void readData(size_t offset, size_t length, void* pDest);
57+
void writeData(size_t offset, size_t length, const void* pSource, bool discardWholeBuffer = false);
58+
void* lock(size_t offset, size_t length, LockOptions options);
59+
void unlock(void);
60+
};
61+
4662
/// Specialisation of HardwareVertexBuffer for emulation
4763
class _OgreExport DefaultHardwareVertexBuffer : public HardwareVertexBuffer
4864
{

OgreMain/include/OgreHardwareBuffer.h

+30-52
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ namespace Ogre {
143143
HBL_WRITE_ONLY
144144

145145
};
146-
Buffer(size_t sizeInBytes, Usage usage) : mSizeInBytes(sizeInBytes), mUsage(usage) {}
146+
Buffer(size_t sizeInBytes, Usage usage) : mSizeInBytes(sizeInBytes), mUsage(usage), mIsLocked(false) {}
147147

148148
virtual ~Buffer() {}
149149
/** Reads data from the buffer and places it in the memory pointed to by pDest.
@@ -152,7 +152,7 @@ namespace Ogre {
152152
@param pDest The area of memory in which to place the data, must be large enough to
153153
accommodate the data!
154154
*/
155-
virtual void readData(size_t offset, size_t length, void* pDest) = 0;
155+
virtual void readData(size_t offset, size_t length, void* pDest) /* const */ = 0;
156156
/** Writes data to the buffer from an area of system memory; note that you must
157157
ensure that your buffer is big enough.
158158
@param offset The byte offset from the start of the buffer to start writing
@@ -173,8 +173,26 @@ namespace Ogre {
173173
@param length Length of the data to copy, in bytes.
174174
@param discardWholeBuffer If true, will discard the entire contents of this buffer before copying
175175
*/
176-
virtual void copyData(HardwareBuffer& srcBuffer, size_t srcOffset, size_t dstOffset, size_t length,
177-
bool discardWholeBuffer = false) = 0;
176+
virtual void copyData(HardwareBuffer& _srcBuffer, size_t srcOffset, size_t dstOffset, size_t length,
177+
bool discardWholeBuffer = false)
178+
{
179+
auto& srcBuffer = (Buffer&)_srcBuffer; // backward compat
180+
const void* srcData = srcBuffer.lock(srcOffset, length, HBL_READ_ONLY);
181+
this->writeData(dstOffset, length, srcData, discardWholeBuffer);
182+
srcBuffer.unlock();
183+
}
184+
185+
/** Copy all data from another buffer into this one.
186+
@remarks
187+
Normally these buffers should be of identical size, but if they're
188+
not, the routine will use the smallest of the two sizes.
189+
*/
190+
void copyData(HardwareBuffer& _srcBuffer)
191+
{
192+
auto& srcBuffer = (Buffer&)_srcBuffer; // backward compat
193+
size_t sz = std::min(getSizeInBytes(), srcBuffer.getSizeInBytes());
194+
copyData(_srcBuffer, 0, 0, sz, true);
195+
}
178196

179197
/** Lock the buffer for (potentially) reading / writing.
180198
@param offset The byte offset from the start of the buffer to lock
@@ -202,15 +220,15 @@ namespace Ogre {
202220
virtual void unlock() = 0;
203221

204222
/// Returns whether or not this buffer is currently locked.
205-
virtual bool isLocked() const = 0;
206-
223+
virtual bool isLocked() const { return mIsLocked; }
207224
/// Returns the size of this buffer in bytes
208225
size_t getSizeInBytes(void) const { return mSizeInBytes; }
209226
/// Returns the Usage flags with which this buffer was created
210227
Usage getUsage(void) const { return mUsage; }
211228
protected:
212229
size_t mSizeInBytes;
213230
Usage mUsage;
231+
bool mIsLocked;
214232
};
215233

216234
/** Abstract class defining common features of hardware buffers.
@@ -247,10 +265,9 @@ namespace Ogre {
247265
class _OgreExport HardwareBuffer : public Buffer
248266
{
249267
protected:
250-
bool mIsLocked;
251268
size_t mLockStart;
252269
size_t mLockSize;
253-
std::unique_ptr<HardwareBuffer> mShadowBuffer;
270+
std::unique_ptr<Buffer> mShadowBuffer;
254271
bool mSystemMemory;
255272
bool mUseShadowBuffer;
256273
bool mShadowUpdated;
@@ -264,7 +281,7 @@ namespace Ogre {
264281
public:
265282
/// Constructor, to be called by HardwareBufferManager only
266283
HardwareBuffer(Usage usage, bool systemMemory, bool useShadowBuffer)
267-
: Buffer(0, usage), mIsLocked(false), mLockStart(0), mLockSize(0), mSystemMemory(systemMemory),
284+
: Buffer(0, usage), mLockStart(0), mLockSize(0), mSystemMemory(systemMemory),
268285
mUseShadowBuffer(useShadowBuffer), mShadowUpdated(false),
269286
mSuppressHardwareUpdate(false)
270287
{
@@ -333,58 +350,19 @@ namespace Ogre {
333350
}
334351

335352
}
336-
337-
/** Copy data from another buffer into this one.
338-
@remarks
339-
Note that the source buffer must not be created with the
340-
usage HBU_WRITE_ONLY otherwise this will fail.
341-
@param srcBuffer The buffer from which to read the copied data
342-
@param srcOffset Offset in the source buffer at which to start reading
343-
@param dstOffset Offset in the destination buffer to start writing
344-
@param length Length of the data to copy, in bytes.
345-
@param discardWholeBuffer If true, will discard the entire contents of this buffer before copying
346-
*/
347-
void copyData(HardwareBuffer& srcBuffer, size_t srcOffset, size_t dstOffset, size_t length,
348-
bool discardWholeBuffer = false) override
349-
{
350-
const void *srcData = srcBuffer.lock(
351-
srcOffset, length, HBL_READ_ONLY);
352-
this->writeData(dstOffset, length, srcData, discardWholeBuffer);
353-
srcBuffer.unlock();
354-
}
355-
356-
/** Copy all data from another buffer into this one.
357-
@remarks
358-
Normally these buffers should be of identical size, but if they're
359-
not, the routine will use the smallest of the two sizes.
360-
*/
361-
virtual void copyData(HardwareBuffer& srcBuffer)
362-
{
363-
size_t sz = std::min(getSizeInBytes(), srcBuffer.getSizeInBytes());
364-
copyData(srcBuffer, 0, 0, sz, true);
365-
}
366353

367354
/// Updates the real buffer from the shadow buffer, if required
368355
virtual void _updateFromShadow(void)
369356
{
370357
if (mUseShadowBuffer && mShadowUpdated && !mSuppressHardwareUpdate)
371358
{
372-
// Do this manually to avoid locking problems
373-
const void *srcData = mShadowBuffer->lockImpl(
374-
mLockStart, mLockSize, HBL_READ_ONLY);
375359
// Lock with discard if the whole buffer was locked, otherwise w/o
376-
LockOptions lockOpt;
377-
if (mLockStart == 0 && mLockSize == mSizeInBytes)
378-
lockOpt = HBL_DISCARD;
379-
else
380-
lockOpt = HBL_WRITE_ONLY;
381-
382-
void *destData = this->lockImpl(
383-
mLockStart, mLockSize, lockOpt);
360+
LockOptions lockOpt = mLockSize == mSizeInBytes ? HBL_DISCARD : HBL_WRITE_ONLY;
361+
// Do this manually to avoid locking problems
362+
void* destData = this->lockImpl(mLockStart, mLockSize, lockOpt);
384363
// Copy shadow to real
385-
memcpy(destData, srcData, mLockSize);
364+
mShadowBuffer->readData(mLockStart, mLockSize, destData);
386365
this->unlockImpl();
387-
mShadowBuffer->unlockImpl();
388366
mShadowUpdated = false;
389367
}
390368
}

OgreMain/src/OgreDefaultHardwareBufferManager.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,39 @@ THE SOFTWARE.
2929
#include "OgreDefaultHardwareBufferManager.h"
3030

3131
namespace Ogre {
32+
DefaultBuffer::DefaultBuffer(size_t sizeInBytes)
33+
: Buffer(sizeInBytes, HBU_DYNAMIC)
34+
{
35+
// Allocate aligned memory for better SIMD processing friendly.
36+
mData = static_cast<unsigned char*>(AlignedMemory::allocate(mSizeInBytes));
37+
}
38+
//-----------------------------------------------------------------------
39+
DefaultBuffer::~DefaultBuffer() { AlignedMemory::deallocate(mData); }
40+
//-----------------------------------------------------------------------
41+
void* DefaultBuffer::lockImpl(size_t offset, size_t length, LockOptions options) { return mData + offset; }
42+
//-----------------------------------------------------------------------
43+
void DefaultBuffer::unlockImpl() {}
44+
//-----------------------------------------------------------------------
45+
void* DefaultBuffer::lock(size_t offset, size_t length, LockOptions options)
46+
{
47+
mIsLocked = true;
48+
return mData + offset;
49+
}
50+
void DefaultBuffer::unlock(void) { mIsLocked = false; }
51+
//-----------------------------------------------------------------------
52+
void DefaultBuffer::readData(size_t offset, size_t length, void* pDest)
53+
{
54+
assert((offset + length) <= mSizeInBytes);
55+
memcpy(pDest, mData + offset, length);
56+
}
57+
//-----------------------------------------------------------------------
58+
void DefaultBuffer::writeData(size_t offset, size_t length, const void* pSource, bool discardWholeBuffer)
59+
{
60+
assert((offset + length) <= mSizeInBytes);
61+
// ignore discard, memory is not guaranteed to be zeroised
62+
memcpy(mData + offset, pSource, length);
63+
}
64+
3265

3366
DefaultHardwareVertexBuffer::DefaultHardwareVertexBuffer(size_t vertexSize, size_t numVertices,
3467
HardwareBuffer::Usage usage)

OgreMain/src/OgreHardwareIndexBuffer.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ namespace Ogre {
5656
// Create a shadow buffer if required
5757
if (mUseShadowBuffer)
5858
{
59-
mShadowBuffer.reset(new DefaultHardwareIndexBuffer(mIndexType,
60-
mNumIndexes, HardwareBuffer::HBU_DYNAMIC));
59+
mShadowBuffer.reset(new DefaultBuffer(mSizeInBytes));
6160
}
6261

6362

OgreMain/src/OgreHardwareUniformBuffer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ namespace Ogre {
4444
// Create a shadow buffer if required
4545
if (mUseShadowBuffer)
4646
{
47-
mShadowBuffer.reset(new DefaultHardwareUniformBuffer(mMgr, sizeBytes, HardwareBuffer::HBU_DYNAMIC, false));
47+
mShadowBuffer.reset(new DefaultBuffer(sizeBytes));
4848
}
4949
}
5050

OgreMain/src/OgreHardwareVertexBuffer.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ namespace Ogre {
4848
// Create a shadow buffer if required
4949
if (mUseShadowBuffer)
5050
{
51-
mShadowBuffer.reset(new DefaultHardwareVertexBuffer(mMgr, mVertexSize,
52-
mNumVertices, HardwareBuffer::HBU_DYNAMIC));
51+
mShadowBuffer.reset(new DefaultBuffer(mSizeInBytes));
5352
}
5453

5554
}

RenderSystems/Direct3D11/include/OgreD3D11HardwareBuffer.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ namespace Ogre {
7474
/** See HardwareBuffer. We perform a hardware copy here. */
7575
void copyData(HardwareBuffer& srcBuffer, size_t srcOffset,
7676
size_t dstOffset, size_t length, bool discardWholeBuffer = false);
77-
void copyDataImpl(HardwareBuffer& srcBuffer, size_t srcOffset,
77+
void copyDataImpl(Buffer& srcBuffer, size_t srcOffset,
7878
size_t dstOffset, size_t length, bool discardWholeBuffer = false);
7979
/// Updates the real buffer from the shadow buffer, if required
8080
virtual void _updateFromShadow(void);

RenderSystems/Direct3D11/src/OgreD3D11HardwareBuffer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ namespace Ogre {
237237
copyDataImpl(srcBuffer, srcOffset, dstOffset, length, discardWholeBuffer);
238238
}
239239
//---------------------------------------------------------------------
240-
void D3D11HardwareBuffer::copyDataImpl(HardwareBuffer& srcBuffer, size_t srcOffset,
240+
void D3D11HardwareBuffer::copyDataImpl(Buffer& srcBuffer, size_t srcOffset,
241241
size_t dstOffset, size_t length, bool discardWholeBuffer)
242242
{
243243
// If we're copying same-size buffers in their entirety...

0 commit comments

Comments
 (0)