|
|
|
@ -298,15 +298,6 @@ void CVertexBufferGL3::setupVBInfos(CVertexBufferInfo &vb)
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
void CVertexBufferGL3::setFence()
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferGLARB_setFence)
|
|
|
|
|
|
|
|
|
|
// no-op
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
void CVertexBufferGL3::invalidate()
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferGLARB_invalidate)
|
|
|
|
@ -348,7 +339,7 @@ CVertexBufferAMDPinned::CVertexBufferAMDPinned(CDriverGL3 *drv, uint size, uint
|
|
|
|
|
nglBufferData(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, size, m_VertexPtrAligned, drv->vertexBufferUsageGL3(preferred));
|
|
|
|
|
if (glGetError() == GL_INVALID_OPERATION)
|
|
|
|
|
{
|
|
|
|
|
nlerror("GL3: Failed to pin memory");
|
|
|
|
|
nlerror("Failed to pin memory");
|
|
|
|
|
nglDeleteBuffers(1, &vertexBufferID);
|
|
|
|
|
vertexBufferID = 0;
|
|
|
|
|
}
|
|
|
|
@ -515,360 +506,6 @@ void CVertexBufferAMDPinned::setupVBInfos(CVertexBufferInfo &vb)
|
|
|
|
|
vb.VertexObjectId = m_VertexObjectId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
void CVertexBufferAMDPinned::setFence()
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferAMDPinned_setFence)
|
|
|
|
|
|
|
|
|
|
// no-op
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
CVertexBufferAMDPinnedVolatile::CVertexBufferAMDPinnedVolatile(CDriverGL3 *drv, uint size, uint numVertices, CVertexBuffer::TPreferredMemory preferred, CVertexBuffer *vb)
|
|
|
|
|
: IVertexBufferGL3(drv, vb, IVertexBufferGL3::AMDPinnedVolatile),
|
|
|
|
|
m_Block(NULL),
|
|
|
|
|
m_VertexPtr(NULL)
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferAMDPinnedVolatile_CVertexBufferAMDPinned)
|
|
|
|
|
|
|
|
|
|
// no-op
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
CVertexBufferAMDPinnedVolatile::~CVertexBufferAMDPinnedVolatile()
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferAMDPinnedVolatile_CVertexBufferAMDPinnedDtor)
|
|
|
|
|
|
|
|
|
|
if (m_Block)
|
|
|
|
|
{
|
|
|
|
|
m_Driver->_AMDPinnedAllocator->free(m_Block);
|
|
|
|
|
m_Block = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
void *CVertexBufferAMDPinnedVolatile::lock()
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferAMDPinnedVolatile_lock);
|
|
|
|
|
|
|
|
|
|
if (m_VertexPtr) // Already locked...
|
|
|
|
|
return m_VertexPtr;
|
|
|
|
|
|
|
|
|
|
// Profiling
|
|
|
|
|
TTicks beforeLock = 0;
|
|
|
|
|
if (m_Driver->_VBHardProfiling)
|
|
|
|
|
{
|
|
|
|
|
beforeLock = CTime::getPerformanceTime();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Allocate if necessary
|
|
|
|
|
const uint size = VB->getNumVertices() * VB->getVertexSize();
|
|
|
|
|
if (m_Block)
|
|
|
|
|
{
|
|
|
|
|
// Verify size
|
|
|
|
|
uint index = 0;
|
|
|
|
|
uint sizeShift = size >> (NLDRV_GL3_AMD_PINNED_VOLATILE_SHIFT);
|
|
|
|
|
while (sizeShift)
|
|
|
|
|
{
|
|
|
|
|
sizeShift >>= 1;
|
|
|
|
|
++index;
|
|
|
|
|
}
|
|
|
|
|
if (m_Block->Bin != index)
|
|
|
|
|
{
|
|
|
|
|
// nldebug("GL3: Size inconsistency"); // NOTE: May have to handle this for other buffers...
|
|
|
|
|
// Wrong size, want a different block size
|
|
|
|
|
m_Driver->_AMDPinnedAllocator->free(m_Block);
|
|
|
|
|
m_Block = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (m_Block)
|
|
|
|
|
{
|
|
|
|
|
// Check fence
|
|
|
|
|
if (m_Block->FenceId)
|
|
|
|
|
{
|
|
|
|
|
GLint status = 0;
|
|
|
|
|
nglGetSynciv(m_Block->FenceId, GL_SYNC_STATUS, 1, NULL, &status);
|
|
|
|
|
if (status == GL_SIGNALED)
|
|
|
|
|
{
|
|
|
|
|
// Can use this
|
|
|
|
|
nglDeleteSync(m_Block->FenceId);
|
|
|
|
|
m_Block->FenceId = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Not ready, get a different block
|
|
|
|
|
m_Driver->_AMDPinnedAllocator->free(m_Block);
|
|
|
|
|
m_Block = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!m_Block)
|
|
|
|
|
{
|
|
|
|
|
m_Block = m_Driver->_AMDPinnedAllocator->allocate(size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Lock
|
|
|
|
|
nlassert(m_Block);
|
|
|
|
|
m_VertexPtr = m_Block->Buffer;
|
|
|
|
|
nlassert(m_VertexPtr);
|
|
|
|
|
|
|
|
|
|
// Profiling
|
|
|
|
|
if (m_Driver->_VBHardProfiling)
|
|
|
|
|
{
|
|
|
|
|
TTicks afterLock;
|
|
|
|
|
afterLock= CTime::getPerformanceTime();
|
|
|
|
|
m_Driver->appendVBHardLockProfile(afterLock-beforeLock, VB);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return m_VertexPtr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
void CVertexBufferAMDPinnedVolatile::unlock()
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferAMDPinnedVolatile_unlock);
|
|
|
|
|
|
|
|
|
|
m_VertexPtr = NULL;
|
|
|
|
|
|
|
|
|
|
if (!m_Block)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Profiling
|
|
|
|
|
/*TTicks beforeLock = 0;
|
|
|
|
|
if (m_Driver->_VBHardProfiling)
|
|
|
|
|
{
|
|
|
|
|
beforeLock = CTime::getPerformanceTime();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Unlock
|
|
|
|
|
m_Driver->_DriverGLStates.bindARBVertexBuffer(m_Block->VertexObjectId);
|
|
|
|
|
nglUnmapBuffer(GL_ARRAY_BUFFER);
|
|
|
|
|
m_Driver->_DriverGLStates.forceBindARBVertexBuffer(0);
|
|
|
|
|
|
|
|
|
|
// Profiling
|
|
|
|
|
if (m_Driver->_VBHardProfiling)
|
|
|
|
|
{
|
|
|
|
|
TTicks afterLock;
|
|
|
|
|
afterLock= CTime::getPerformanceTime();
|
|
|
|
|
m_Driver->appendVBHardLockProfile(afterLock-beforeLock, VB);
|
|
|
|
|
}*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
void *CVertexBufferAMDPinnedVolatile::getPointer()
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferAMDPinnedVolatile_getPointer)
|
|
|
|
|
|
|
|
|
|
return m_VertexPtr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
void CVertexBufferAMDPinnedVolatile::unlock(uint /* startVert */,uint /* endVert */)
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferAMDPinnedVolatile_unlock)
|
|
|
|
|
|
|
|
|
|
unlock();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
void CVertexBufferAMDPinnedVolatile::enable()
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferAMDPinnedVolatile_enable)
|
|
|
|
|
if (m_Driver->_CurrentVertexBufferGL != this)
|
|
|
|
|
{
|
|
|
|
|
m_Driver->_CurrentVertexBufferGL = this;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
void CVertexBufferAMDPinnedVolatile::disable()
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferAMDPinned_disable)
|
|
|
|
|
if (m_Driver->_CurrentVertexBufferGL != NULL)
|
|
|
|
|
{
|
|
|
|
|
m_Driver->_CurrentVertexBufferGL = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
void CVertexBufferAMDPinnedVolatile::setupVBInfos(CVertexBufferInfo &vb)
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferAMDPinned_setupVBInfos)
|
|
|
|
|
|
|
|
|
|
vb.VertexObjectId = m_Block->VertexObjectId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
void CVertexBufferAMDPinnedVolatile::setFence()
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferAMDPinnedVolatile_setFence)
|
|
|
|
|
|
|
|
|
|
// Set the fence
|
|
|
|
|
nlassert(m_Block);
|
|
|
|
|
if (m_Block->FenceId)
|
|
|
|
|
{
|
|
|
|
|
nglDeleteSync(m_Block->FenceId);
|
|
|
|
|
m_Block->FenceId = 0;
|
|
|
|
|
}
|
|
|
|
|
m_Block->FenceId = nglFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
|
|
|
|
nlassert(m_Block->FenceId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
CVertexBufferAMDPinnedAllocator::CVertexBufferAMDPinnedAllocator(CDriverGL3 *driver)
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferAMDPinnedAllocator_ctor)
|
|
|
|
|
|
|
|
|
|
m_Driver = driver;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
CVertexBufferAMDPinnedAllocator::~CVertexBufferAMDPinnedAllocator()
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferAMDPinnedAllocator_dtor)
|
|
|
|
|
|
|
|
|
|
// Release all pools
|
|
|
|
|
for (uint bin = 0; bin < NLDRV_GL3_AMD_PINNED_VOLATILE_BINS; ++bin)
|
|
|
|
|
{
|
|
|
|
|
while (!m_Pool[bin].empty())
|
|
|
|
|
{
|
|
|
|
|
CVertexBufferAMDPinnedBlock *block = m_Pool[bin].front();
|
|
|
|
|
m_Pool[bin].pop();
|
|
|
|
|
|
|
|
|
|
if (m_Driver && block->VertexObjectId)
|
|
|
|
|
{
|
|
|
|
|
if (m_Driver->_DriverGLStates.getCurrBoundARBVertexBuffer() == block->VertexObjectId)
|
|
|
|
|
{
|
|
|
|
|
m_Driver->_DriverGLStates.forceBindARBVertexBuffer(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (block->VertexObjectId)
|
|
|
|
|
{
|
|
|
|
|
nlassert(nglIsBuffer(block->VertexObjectId));
|
|
|
|
|
nglDeleteBuffers(1, &block->VertexObjectId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete block->Allocated;
|
|
|
|
|
delete block;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_Driver = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
CVertexBufferAMDPinnedBlock *CVertexBufferAMDPinnedAllocator::allocate(uint size)
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferAMDPinnedAllocator_allocate)
|
|
|
|
|
|
|
|
|
|
uint index = 0;
|
|
|
|
|
uint sizeShift = size >> (NLDRV_GL3_AMD_PINNED_VOLATILE_SHIFT);
|
|
|
|
|
while (sizeShift)
|
|
|
|
|
{
|
|
|
|
|
sizeShift >>= 1;
|
|
|
|
|
++index;
|
|
|
|
|
}
|
|
|
|
|
nlassert(index < NLDRV_GL3_AMD_PINNED_VOLATILE_BINS); // Not implemented over 8MB
|
|
|
|
|
|
|
|
|
|
if (!m_Pool[index].empty())
|
|
|
|
|
{
|
|
|
|
|
CVertexBufferAMDPinnedBlock *block = m_Pool[index].front();
|
|
|
|
|
if (block->FenceId == 0)
|
|
|
|
|
{
|
|
|
|
|
// No fence, don't check
|
|
|
|
|
m_Pool[index].pop();
|
|
|
|
|
return block;
|
|
|
|
|
}
|
|
|
|
|
GLint status = 0;
|
|
|
|
|
nlassert(nglIsSync(block->FenceId));
|
|
|
|
|
nglGetSynciv(block->FenceId, GL_SYNC_STATUS, 1, NULL, &status);
|
|
|
|
|
if (status == GL_SIGNALED)
|
|
|
|
|
{
|
|
|
|
|
// Ready, can use this block
|
|
|
|
|
// nldebug("GL3: APV Reuse (idx %i, glid %i)", index, block->VertexObjectId);
|
|
|
|
|
nglDeleteSync(block->FenceId);
|
|
|
|
|
block->FenceId = 0;
|
|
|
|
|
m_Pool[index].pop();
|
|
|
|
|
return block;
|
|
|
|
|
}
|
|
|
|
|
nlassert(status == GL_UNSIGNALED);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// nldebug("GL3: Empty container");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create new block
|
|
|
|
|
CVertexBufferAMDPinnedBlock *newblock = new CVertexBufferAMDPinnedBlock();
|
|
|
|
|
newblock->Bin = index;
|
|
|
|
|
|
|
|
|
|
// Allocate memory
|
|
|
|
|
uint allocSize = 1 << (NLDRV_GL3_AMD_PINNED_VOLATILE_SHIFT + index);
|
|
|
|
|
static int totalAlloc = 0;
|
|
|
|
|
totalAlloc += allocSize + 4096;
|
|
|
|
|
nldebug("GL3: APV Alloc (%i -> %i, total: %i)", size, allocSize, totalAlloc);
|
|
|
|
|
newblock->Allocated = new char[allocSize + 4096];
|
|
|
|
|
nlassert(newblock->Allocated);
|
|
|
|
|
uintptr_t addr = (uintptr_t)newblock->Allocated;
|
|
|
|
|
addr = (addr + 4095) & (~0xfff);
|
|
|
|
|
void *addrAligned = (void *)addr;
|
|
|
|
|
newblock->Buffer = addrAligned;
|
|
|
|
|
|
|
|
|
|
// Create id and bind
|
|
|
|
|
nglGenBuffers(1, &newblock->VertexObjectId);
|
|
|
|
|
nglBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, newblock->VertexObjectId);
|
|
|
|
|
|
|
|
|
|
// Set buffer
|
|
|
|
|
nglBufferData(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, allocSize, addrAligned, GL_DYNAMIC_DRAW);
|
|
|
|
|
if (glGetError() == GL_INVALID_OPERATION)
|
|
|
|
|
{
|
|
|
|
|
nlerror("GL3: Failed to pin memory (volatile)");
|
|
|
|
|
nglDeleteBuffers(1, &newblock->VertexObjectId);
|
|
|
|
|
newblock->VertexObjectId = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Unbind
|
|
|
|
|
nglBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0);
|
|
|
|
|
|
|
|
|
|
// TEST LOCK
|
|
|
|
|
/*m_Driver->_DriverGLStates.bindARBVertexBuffer(newblock->VertexObjectId);
|
|
|
|
|
// m_VertexPtr = nglMapBufferRange(GL_ARRAY_BUFFER, 0, size, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
|
|
|
|
|
void *testptr = nglMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
|
|
|
|
|
nlassert(testptr);
|
|
|
|
|
m_Driver->_DriverGLStates.bindARBVertexBuffer(0);*/
|
|
|
|
|
|
|
|
|
|
return newblock;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
void CVertexBufferAMDPinnedAllocator::free(CVertexBufferAMDPinnedBlock *block)
|
|
|
|
|
{
|
|
|
|
|
H_AUTO_OGL(CVertexBufferAMDPinnedAllocator_free)
|
|
|
|
|
|
|
|
|
|
// nldebug("GL3: Free block (glid: %i)", block->VertexObjectId);
|
|
|
|
|
m_Pool[block->Bin].push(block);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|