Skip to content

Commit bda92ed

Browse files
committed
Main: add lightweight DefaultBuffer class for shadow buffering
1 parent aeaeeb4 commit bda92ed

8 files changed

+84
-59
lines changed

Diff for: 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
{

Diff for: OgreMain/include/OgreHardwareBuffer.h

+30-52
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ namespace Ogre {
122122
HBL_WRITE_ONLY
123123

124124
};
125-
Buffer(size_t sizeInBytes, int usage) : mSizeInBytes(sizeInBytes), mUsage(usage) {}
125+
Buffer(size_t sizeInBytes, int usage) : mSizeInBytes(sizeInBytes), mUsage(usage), mIsLocked(false) {}
126126

127127
virtual ~Buffer() {}
128128
/** Reads data from the buffer and places it in the memory pointed to by pDest.
@@ -131,7 +131,7 @@ namespace Ogre {
131131
@param pDest The area of memory in which to place the data, must be large enough to
132132
accommodate the data!
133133
*/
134-
virtual void readData(size_t offset, size_t length, void* pDest) = 0;
134+
virtual void readData(size_t offset, size_t length, void* pDest) /* const */ = 0;
135135
/** Writes data to the buffer from an area of system memory; note that you must
136136
ensure that your buffer is big enough.
137137
@param offset The byte offset from the start of the buffer to start writing
@@ -152,8 +152,26 @@ namespace Ogre {
152152
@param length Length of the data to copy, in bytes.
153153
@param discardWholeBuffer If true, will discard the entire contents of this buffer before copying
154154
*/
155-
virtual void copyData(HardwareBuffer& srcBuffer, size_t srcOffset, size_t dstOffset, size_t length,
156-
bool discardWholeBuffer = false) = 0;
155+
virtual void copyData(HardwareBuffer& _srcBuffer, size_t srcOffset, size_t dstOffset, size_t length,
156+
bool discardWholeBuffer = false)
157+
{
158+
auto& srcBuffer = (Buffer&)_srcBuffer; // backward compat
159+
const void* srcData = srcBuffer.lock(srcOffset, length, HBL_READ_ONLY);
160+
this->writeData(dstOffset, length, srcData, discardWholeBuffer);
161+
srcBuffer.unlock();
162+
}
163+
164+
/** Copy all data from another buffer into this one.
165+
@remarks
166+
Normally these buffers should be of identical size, but if they're
167+
not, the routine will use the smallest of the two sizes.
168+
*/
169+
void copyData(HardwareBuffer& _srcBuffer)
170+
{
171+
auto& srcBuffer = (Buffer&)_srcBuffer; // backward compat
172+
size_t sz = std::min(getSizeInBytes(), srcBuffer.getSizeInBytes());
173+
copyData(_srcBuffer, 0, 0, sz, true);
174+
}
157175

158176
/** Lock the buffer for (potentially) reading / writing.
159177
@param offset The byte offset from the start of the buffer to lock
@@ -181,15 +199,15 @@ namespace Ogre {
181199
virtual void unlock() = 0;
182200

183201
/// Returns whether or not this buffer is currently locked.
184-
virtual bool isLocked() const = 0;
185-
202+
virtual bool isLocked() const { return mIsLocked; }
186203
/// Returns the size of this buffer in bytes
187204
size_t getSizeInBytes(void) const { return mSizeInBytes; }
188205
/// Returns the Usage flags with which this buffer was created
189206
int getUsage(void) const { return mUsage; }
190207
protected:
191208
size_t mSizeInBytes;
192209
int mUsage;
210+
bool mIsLocked;
193211
};
194212

195213

@@ -248,10 +266,9 @@ namespace Ogre {
248266
HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE = HBU_CPU_TO_GPU,
249267
};
250268
protected:
251-
bool mIsLocked;
252269
size_t mLockStart;
253270
size_t mLockSize;
254-
std::unique_ptr<HardwareBuffer> mShadowBuffer;
271+
std::unique_ptr<Buffer> mShadowBuffer;
255272
bool mSystemMemory;
256273
bool mUseShadowBuffer;
257274
bool mShadowUpdated;
@@ -265,7 +282,7 @@ namespace Ogre {
265282
public:
266283
/// Constructor, to be called by HardwareBufferManager only
267284
HardwareBuffer(Usage usage, bool systemMemory, bool useShadowBuffer)
268-
: Buffer(0, usage), mIsLocked(false), mLockStart(0), mLockSize(0), mSystemMemory(systemMemory),
285+
: Buffer(0, usage), mLockStart(0), mLockSize(0), mSystemMemory(systemMemory),
269286
mUseShadowBuffer(useShadowBuffer), mShadowUpdated(false),
270287
mSuppressHardwareUpdate(false)
271288
{
@@ -330,57 +347,18 @@ namespace Ogre {
330347

331348
}
332349

333-
/** Copy data from another buffer into this one.
334-
@remarks
335-
Note that the source buffer must not be created with the
336-
usage HBU_WRITE_ONLY otherwise this will fail.
337-
@param srcBuffer The buffer from which to read the copied data
338-
@param srcOffset Offset in the source buffer at which to start reading
339-
@param dstOffset Offset in the destination buffer to start writing
340-
@param length Length of the data to copy, in bytes.
341-
@param discardWholeBuffer If true, will discard the entire contents of this buffer before copying
342-
*/
343-
void copyData(HardwareBuffer& srcBuffer, size_t srcOffset, size_t dstOffset, size_t length,
344-
bool discardWholeBuffer = false) override
345-
{
346-
const void *srcData = srcBuffer.lock(
347-
srcOffset, length, HBL_READ_ONLY);
348-
this->writeData(dstOffset, length, srcData, discardWholeBuffer);
349-
srcBuffer.unlock();
350-
}
351-
352-
/** Copy all data from another buffer into this one.
353-
@remarks
354-
Normally these buffers should be of identical size, but if they're
355-
not, the routine will use the smallest of the two sizes.
356-
*/
357-
virtual void copyData(HardwareBuffer& srcBuffer)
358-
{
359-
size_t sz = std::min(getSizeInBytes(), srcBuffer.getSizeInBytes());
360-
copyData(srcBuffer, 0, 0, sz, true);
361-
}
362-
363350
/// Updates the real buffer from the shadow buffer, if required
364351
virtual void _updateFromShadow(void)
365352
{
366353
if (mUseShadowBuffer && mShadowUpdated && !mSuppressHardwareUpdate)
367354
{
368-
// Do this manually to avoid locking problems
369-
const void *srcData = mShadowBuffer->lockImpl(
370-
mLockStart, mLockSize, HBL_READ_ONLY);
371355
// Lock with discard if the whole buffer was locked, otherwise w/o
372-
LockOptions lockOpt;
373-
if (mLockStart == 0 && mLockSize == mSizeInBytes)
374-
lockOpt = HBL_DISCARD;
375-
else
376-
lockOpt = HBL_WRITE_ONLY;
377-
378-
void *destData = this->lockImpl(
379-
mLockStart, mLockSize, lockOpt);
356+
LockOptions lockOpt = mLockSize == mSizeInBytes ? HBL_DISCARD : HBL_WRITE_ONLY;
357+
// Do this manually to avoid locking problems
358+
void* destData = this->lockImpl(mLockStart, mLockSize, lockOpt);
380359
// Copy shadow to real
381-
memcpy(destData, srcData, mLockSize);
360+
mShadowBuffer->readData(mLockStart, mLockSize, destData);
382361
this->unlockImpl();
383-
mShadowBuffer->unlockImpl();
384362
mShadowUpdated = false;
385363
}
386364
}

Diff for: 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_CPU_ONLY)
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)

Diff for: 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

Diff for: 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

Diff for: 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
}

Diff for: 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);

Diff for: RenderSystems/Direct3D11/src/OgreD3D11HardwareBuffer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ namespace Ogre {
213213
copyDataImpl(srcBuffer, srcOffset, dstOffset, length, discardWholeBuffer);
214214
}
215215
//---------------------------------------------------------------------
216-
void D3D11HardwareBuffer::copyDataImpl(HardwareBuffer& srcBuffer, size_t srcOffset,
216+
void D3D11HardwareBuffer::copyDataImpl(Buffer& srcBuffer, size_t srcOffset,
217217
size_t dstOffset, size_t length, bool discardWholeBuffer)
218218
{
219219
// If we're copying same-size buffers in their entirety...

0 commit comments

Comments
 (0)