1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-05-10 19:13:44 +00:00

fix some oversights in vertex buffer binding cache

now buffers are only bound if needed
This commit is contained in:
fgenesis 2024-01-11 22:59:26 +01:00
parent 5dccefffc0
commit ee7129982f
2 changed files with 56 additions and 50 deletions

View file

@ -6,9 +6,8 @@
bool DynamicGPUBuffer::_HasARB = false; bool DynamicGPUBuffer::_HasARB = false;
static unsigned s_lastVertexBuffer = 0; static unsigned s_lastBuffer[GPUBUF_BINDING_MASK + 1]; // index via (usage & GPUBUF_BINDING_MASK)
static unsigned s_lastIndexBuffer = 0; static void *s_lastPtr = NULL;
static void *s_lastHostPtr = NULL;
static BufDataType s_lastDataType = BufDataType(-1); static BufDataType s_lastDataType = BufDataType(-1);
static unsigned s_lastState = 0; // StateBits static unsigned s_lastState = 0; // StateBits
@ -33,13 +32,14 @@ void DynamicGPUBuffer::StaticInit()
DynamicGPUBuffer::DynamicGPUBuffer(unsigned usage) DynamicGPUBuffer::DynamicGPUBuffer(unsigned usage)
: _bufid(0) : _bufid(0)
, _binding((usage & GPUBUF_INDEXBUF) ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB) , _gl_binding((usage & GPUBUF_INDEXBUF) ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB)
, _size(0) , _size(0)
, _h_cap(0) , _h_cap(0)
, _h_data(NULL) , _h_data(NULL)
, _d_cap(0) , _d_cap(0)
, _d_map(NULL) , _d_map(NULL)
, _usage(toGlUsage(usage)) , _gl_usage(toGlUsage(usage))
, _usage(usage)
, _datatype(BufDataType(-1)) , _datatype(BufDataType(-1))
{ {
} }
@ -51,8 +51,8 @@ DynamicGPUBuffer::~DynamicGPUBuffer()
void* DynamicGPUBuffer::_allocBytes(size_t bytes) void* DynamicGPUBuffer::_allocBytes(size_t bytes)
{ {
if(s_lastHostPtr == _h_data) if(s_lastPtr == _h_data)
s_lastHostPtr = NULL; s_lastPtr = NULL;
void *p = realloc(_h_data, bytes); void *p = realloc(_h_data, bytes);
if(p) if(p)
@ -83,12 +83,18 @@ void* DynamicGPUBuffer::beginWrite(BufDataType type, size_t newsize, unsigned ac
if(_HasARB) if(_HasARB)
{ {
glBindBufferARB(_binding, _ensureDBuf()); const unsigned id = _ensureDBuf();
unsigned& last = s_lastBuffer[_usage & GPUBUF_BINDING_MASK];
if(id != last)
{
last = id;
glBindBufferARB(_gl_binding, id);
}
if(!(access & GPUACCESS_HOSTCOPY)) if(!(access & GPUACCESS_HOSTCOPY))
{ {
_d_cap = newsize; _d_cap = newsize;
glBufferDataARB(_binding, newsize, NULL, _usage); // orphan buffer glBufferDataARB(_gl_binding, newsize, NULL, _gl_usage); // orphan buffer
void *p = glMapBufferARB(_binding, GL_WRITE_ONLY_ARB); void *p = glMapBufferARB(_gl_binding, GL_WRITE_ONLY_ARB);
_d_map = p; _d_map = p;
if(p) if(p)
return p; return p;
@ -116,7 +122,7 @@ bool DynamicGPUBuffer::_commitWrite(size_t used)
if(_d_map) if(_d_map)
{ {
assert(used <= _d_cap); assert(used <= _d_cap);
bool ok = glUnmapBufferARB(_binding); // can fail bool ok = glUnmapBufferARB(_gl_binding); // can fail
if(ok) if(ok)
_d_map = NULL; _d_map = NULL;
return ok; return ok;
@ -126,11 +132,11 @@ bool DynamicGPUBuffer::_commitWrite(size_t used)
assert(_h_data); assert(_h_data);
assert(used <= _h_cap); assert(used <= _h_cap);
if(used <= _d_cap) if(used <= _d_cap)
glBufferSubDataARB(_binding, 0, used, _h_data); // update existing buffer glBufferSubDataARB(_gl_binding, 0, used, _h_data); // update existing buffer
else else
{ {
_d_cap = used; _d_cap = used;
glBufferDataARB(_binding, used, _h_data, _usage); // alloc new buffer glBufferDataARB(_gl_binding, used, _h_data, _gl_usage); // alloc new buffer
} }
} }
// else nothing to do // else nothing to do
@ -145,8 +151,14 @@ void DynamicGPUBuffer::upload(BufDataType type, const void* data, size_t size)
if(_HasARB) if(_HasARB)
{ {
glBindBufferARB(_binding, _ensureDBuf()); const unsigned id = _ensureDBuf();
glBufferDataARB(_binding, size, data, _usage); unsigned& last = s_lastBuffer[_usage & GPUBUF_BINDING_MASK];
if(id != last)
{
last = id;
glBindBufferARB(_gl_binding, id);
}
glBufferDataARB(_gl_binding, size, data, _gl_usage);
} }
else else
memcpy(_ensureBytes(size), data, size); memcpy(_ensureBytes(size), data, size);
@ -173,30 +185,22 @@ void DynamicGPUBuffer::apply(BufDataType usetype) const
const unsigned bufid = this->_bufid; const unsigned bufid = this->_bufid;
void *p; void *p = bufid ? NULL : (void*)this->_h_data;
if(bufid)
{
p = NULL;
//if(bufid != s_lastVertexBuffer)
// glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufid);
}
else
{
p = (void*)this->_h_data;
//assert(p != s_lastHostPtr); // check that it's no redundant state change
//if(p == s_lastHostPtr && usetype == s_lastDataType) // don't need to check for datatype since that's const for the buffer with that ptr
// return;
}
assert(bufid || p); assert(bufid || p);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufid); if(bufid != s_lastBuffer[GPUBUF_VERTEXBUF])
{
s_lastBuffer[GPUBUF_VERTEXBUF] = bufid;
glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufid);
}
else if(p == s_lastPtr && usetype == s_lastDataType)
return;
//if(bufid == s_lastVertexBuffer && usetype == s_lastDataType && p == s_lastHostPtr) // --- something is different compared to last time, setup pointers ---
// return;
s_lastDataType = usetype; s_lastDataType = usetype;
s_lastVertexBuffer = bufid; s_lastPtr = p;
unsigned u = usetype; // always want unsigned shifts unsigned u = usetype; // always want unsigned shifts
assert((u & 0xf) < Countof(s_gltype)); assert((u & 0xf) < Countof(s_gltype));
@ -242,16 +246,16 @@ unsigned DynamicGPUBuffer::_ensureDBuf()
void DynamicGPUBuffer::dropBuffer() void DynamicGPUBuffer::dropBuffer()
{ {
if(s_lastHostPtr == _h_data) if(s_lastPtr == _h_data)
s_lastHostPtr = NULL; s_lastPtr = NULL;
free(_h_data); free(_h_data);
_h_data = NULL; _h_data = NULL;
if(_bufid) if(_bufid)
{ {
if(s_lastVertexBuffer == _bufid) if(s_lastBuffer[GPUBUF_VERTEXBUF] == _bufid)
s_lastVertexBuffer = 0; s_lastBuffer[GPUBUF_VERTEXBUF] = 0;
if(s_lastIndexBuffer == _bufid) if(s_lastBuffer[GPUBUF_INDEXBUF] == _bufid)
s_lastIndexBuffer = 0; s_lastBuffer[GPUBUF_INDEXBUF] = 0;
glDeleteBuffersARB(1, &_bufid); glDeleteBuffersARB(1, &_bufid);
_bufid = 0; _bufid = 0;
@ -268,17 +272,17 @@ void DynamicGPUBuffer::dropBuffer()
void DynamicGPUBuffer::drawElements(unsigned glmode, size_t n, size_t first) const void DynamicGPUBuffer::drawElements(unsigned glmode, size_t n, size_t first) const
{ {
assert(_binding == GL_ELEMENT_ARRAY_BUFFER_ARB); assert(_gl_binding == GL_ELEMENT_ARRAY_BUFFER_ARB);
assert(s_gltype[_datatype & 0xf] == GL_SHORT); assert(s_gltype[_datatype & 0xf] == GL_SHORT);
//assert(getBoundBuffer(GL_ARRAY_BUFFER_BINDING)); // FIXME: this assert is wrong if indices are on the host //assert(getBoundBuffer(GL_ARRAY_BUFFER_BINDING)); // FIXME: this assert is wrong if indices are on the host
unsigned id = _bufid; const unsigned id = _bufid;
//if(s_lastIndexBuffer != id) if(s_lastBuffer[GPUBUF_INDEXBUF] != id)
//{ {
// s_lastIndexBuffer = id; s_lastBuffer[GPUBUF_INDEXBUF] = id;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, id); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, id);
//} }
const unsigned short *p = (unsigned short*)(id ? NULL : _h_data); const unsigned short *p = (unsigned short*)(id ? NULL : _h_data);
assert(p || id); assert(p || id);

View file

@ -7,12 +7,13 @@ struct TexCoordBox;
enum BufUsage enum BufUsage
{ {
// usage
GPUBUF_DYNAMIC = 0x00,
GPUBUF_STATIC = 0x01,
// binding point // binding point
GPUBUF_VERTEXBUF = 0x00, GPUBUF_VERTEXBUF = 0x00,
GPUBUF_INDEXBUF = 0x02 GPUBUF_INDEXBUF = 0x01,
GPUBUF_BINDING_MASK = 0x01,
// usage
GPUBUF_DYNAMIC = 0x00,
GPUBUF_STATIC = 0x10
}; };
enum BufDataType enum BufDataType
@ -87,12 +88,13 @@ private:
bool _commitWrite(size_t used); bool _commitWrite(size_t used);
unsigned _bufid; unsigned _bufid;
unsigned _binding; unsigned _gl_binding;
size_t _size; size_t _size;
size_t _h_cap; size_t _h_cap;
void *_h_data; void *_h_data;
size_t _d_cap; size_t _d_cap;
void *_d_map; void *_d_map;
const unsigned _gl_usage;
const unsigned _usage; const unsigned _usage;
BufDataType _datatype; BufDataType _datatype;