GL3: Add support for GL_AMD_pinned_memory

--HG--
branch : opengl3
hg/feature/opengl3
kaetemi 11 years ago
parent 60851a863e
commit 76cacae628

@ -689,7 +689,7 @@ public:
#endif
private:
virtual class IVertexBufferGL3 *createVertexBufferGL(uint size, uint numVertices, CVertexBuffer::TPreferredMemory vbType, CVertexBuffer *vb);
virtual class IVertexBufferGL3 *createVertexBufferGL(uint size, uint numVertices, CVertexBuffer::TPreferredMemory preferred, CVertexBuffer *vb);
friend class CTextureDrvInfosGL3;
friend class CVertexProgamDrvInfosGL3;
@ -1126,6 +1126,7 @@ private:
// @{
CPtrSet<IVertexBufferGL3> _VertexBufferGLSet;
friend class CVertexBufferGL3;
friend class CVertexBufferAMDPinned;
friend class CVBDrvInfosGL3;
// The VertexBufferHardGL activated.

@ -539,6 +539,13 @@ static bool setupARBSeparateShaderObjects(std::vector<const char *> &glext)
return true;
}
static bool setupAMDPinnedMemory(std::vector<const char *> &glext)
{
CHECK_EXT_2("GL_AMD_pinned_memory");
return true;
}
// ***************************************************************************
// Extension Check.
bool registerGlExtensions(CGlExtensions &ext)
@ -611,6 +618,9 @@ bool registerGlExtensions(CGlExtensions &ext)
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &ext.EXTTextureFilterAnisotropicMaximum);
}
// Check GL_AMD_pinned_memory
ext.AMDPinnedMemory = setupAMDPinnedMemory(glext);
// Get the maximum fragment texture unites
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &ext.MaxFragmentTextureImageUnits);
if (ext.MaxFragmentTextureImageUnits < 8)

@ -44,6 +44,7 @@ struct CGlExtensions
bool EXTTextureCompressionS3TC;
bool EXTTextureFilterAnisotropic;
float EXTTextureFilterAnisotropicMaximum;
bool AMDPinnedMemory;
// Required Extensions. (old)
bool ARBMultiTexture;
@ -70,6 +71,7 @@ public:
EXTTextureCompressionS3TC = false;
EXTTextureFilterAnisotropic = false;
EXTTextureFilterAnisotropicMaximum = 0.f;
AMDPinnedMemory = false;
ARBMultiTexture= false;
@ -102,6 +104,9 @@ public:
result += "fragment texture units(*) = ";
result += NLMISC::toString(MaxFragmentTextureImageUnits);
result += "\n Buffers: ";
result += AMDPinnedMemory ? "AMDPinnedMemory " : "";
#ifdef NL_OS_WINDOWS
result += "\n WindowsGL: ";
result += WGLARBPBuffer ? "WGLARBPBuffer " : "";

@ -221,7 +221,7 @@ bool CDriverGL3::activeIndexBuffer(CIndexBuffer& IB)
bool CDriverGL3::supportVolatileVertexBuffer() const
{
H_AUTO_OGL(CDriverGL3_supportVolatileVertexBuffer)
return true; // TODO VERTEXBUFFER PINNED
return true; // Supported by GL_MAP_INVALIDATE_BUFFER_BIT
}
@ -230,7 +230,7 @@ bool CDriverGL3::supportVolatileVertexBuffer() const
bool CDriverGL3::slowUnlockVertexBufferHard() const
{
H_AUTO_OGL(CDriverGL3_slowUnlockVertexBufferHard)
return false;
return false; // Always false gives slightly better performance on AMD. Might make difference with _Extensions.AMDPinnedMemory
}
@ -241,6 +241,7 @@ uint CDriverGL3::getMaxVerticesByVertexBufferHard() const
return std::numeric_limits<uint32>::max();
}
// TODO: Move this to CVertexBufferGL3
GLenum CDriverGL3::vertexBufferUsageGL3(CVertexBuffer::TPreferredMemory usage)
{
switch (usage)
@ -260,19 +261,25 @@ GLenum CDriverGL3::vertexBufferUsageGL3(CVertexBuffer::TPreferredMemory usage)
}
// ***************************************************************************
IVertexBufferGL3 *CDriverGL3::createVertexBufferGL(uint size, uint numVertices, CVertexBuffer::TPreferredMemory vbType, CVertexBuffer *vb)
IVertexBufferGL3 *CDriverGL3::createVertexBufferGL(uint size, uint numVertices, CVertexBuffer::TPreferredMemory preferred, CVertexBuffer *vb)
{
H_AUTO_OGL(CDriverGL3_createVertexBufferGL)
// Create a Vertex Buffer
GLuint vertexBufferID;
nglGenBuffers(1, &vertexBufferID);
_DriverGLStates.forceBindARBVertexBuffer(vertexBufferID);
nglBufferData(GL_ARRAY_BUFFER, size, NULL, vertexBufferUsageGL3(vbType));
CVertexBufferGL3 *newVbHard = new CVertexBufferGL3(this, vb);
newVbHard->initGL(vertexBufferID, vbType);
_DriverGLStates.forceBindARBVertexBuffer(0);
return _VertexBufferGLSet.insert(newVbHard);
IVertexBufferGL3 *result;
if (_Extensions.AMDPinnedMemory && (
preferred == CVertexBuffer::RAMPreferred
// || preferred == CVertexBuffer::AGPPreferred
))
{
result = new CVertexBufferAMDPinned(this, size, numVertices, preferred, vb);
}
else
{
result = new CVertexBufferGL3(this, size, numVertices, preferred, vb);
}
return _VertexBufferGLSet.insert(result);
}
// ********************************************************************

@ -31,6 +31,9 @@ namespace NLDRIVERGL3 {
#endif
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
IVertexBufferGL3::IVertexBufferGL3(CDriverGL3 *drv, CVertexBuffer *vb, TVBType vbType)
: VB(vb), VBType(vbType), m_Driver(drv), m_Invalid(false)
{
@ -38,21 +41,39 @@ IVertexBufferGL3::IVertexBufferGL3(CDriverGL3 *drv, CVertexBuffer *vb, TVBType v
}
// ***************************************************************************
IVertexBufferGL3::~IVertexBufferGL3()
{
H_AUTO_OGL(IVertexBufferGL_IVertexBufferGLDtor)
}
// ***************************************************************************
CVertexBufferGL3::CVertexBufferGL3(CDriverGL3 *drv, CVertexBuffer *vb)
// ***************************************************************************
// ***************************************************************************
CVertexBufferGL3::CVertexBufferGL3(CDriverGL3 *drv, uint size, uint numVertices, CVertexBuffer::TPreferredMemory preferred, CVertexBuffer *vb)
: IVertexBufferGL3(drv, vb, IVertexBufferGL3::GL3),
m_VertexPtr(NULL),
m_VertexObjectId(0)
{
H_AUTO_OGL(CVertexBufferGLARB_CVertexBufferGLARB)
// Create id and bind
GLuint vertexBufferID;
nglGenBuffers(1, &vertexBufferID);
drv->_DriverGLStates.forceBindARBVertexBuffer(vertexBufferID);
// Initialize
nglBufferData(GL_ARRAY_BUFFER, size, NULL, drv->vertexBufferUsageGL3(preferred));
m_VertexObjectId = vertexBufferID;
m_MemType = preferred;
// Unbind
drv->_DriverGLStates.forceBindARBVertexBuffer(0);
}
// ***************************************************************************
CVertexBufferGL3::~CVertexBufferGL3()
{
H_AUTO_OGL(CVertexBufferGLARB_CVertexBufferGLARBDtor)
@ -83,6 +104,7 @@ CVertexBufferGL3::~CVertexBufferGL3()
}
// ***************************************************************************
void *CVertexBufferGL3::lock()
{
H_AUTO_OGL(CVertexBufferGLARB_lock);
@ -184,6 +206,7 @@ void *CVertexBufferGL3::lock()
}
// ***************************************************************************
void CVertexBufferGL3::unlock()
{
H_AUTO_OGL(CVertexBufferGLARB_unlock);
@ -228,6 +251,7 @@ void CVertexBufferGL3::unlock()
}
// ***************************************************************************
void *CVertexBufferGL3::getPointer()
{
H_AUTO_OGL(CVertexBufferGLARB_getPointer)
@ -235,6 +259,7 @@ void *CVertexBufferGL3::getPointer()
}
// ***************************************************************************
void CVertexBufferGL3::unlock(uint /* startVert */,uint /* endVert */)
{
H_AUTO_OGL(CVertexBufferGLARB_unlock)
@ -242,38 +267,29 @@ void CVertexBufferGL3::unlock(uint /* startVert */,uint /* endVert */)
}
// ***************************************************************************
void CVertexBufferGL3::enable()
{
H_AUTO_OGL(CVertexBufferGLARB_enable)
if (m_Driver->_CurrentVertexBufferGL != this)
{
/* nlassert(_VertexArrayRange);
_VertexArrayRange->enable(); */
m_Driver->_CurrentVertexBufferGL= this;
}
}
// ***************************************************************************
void CVertexBufferGL3::disable()
{
H_AUTO_OGL(CVertexBufferGLARB_disable)
if (m_Driver->_CurrentVertexBufferGL != NULL)
{
/* nlassert(_VertexArrayRange);
_VertexArrayRange->disable(); */
m_Driver->_CurrentVertexBufferGL= NULL;
}
}
// ***************************************************************************
void CVertexBufferGL3::initGL(uint vertexObjectID, CVertexBuffer::TPreferredMemory memType)
{
H_AUTO_OGL(CVertexBufferGLARB_initGL)
m_VertexObjectId = vertexObjectID;
m_MemType = memType;
}
// ***************************************************************************
void CVertexBufferGL3::setupVBInfos(CVertexBufferInfo &vb)
{
H_AUTO_OGL(CVertexBufferGLARB_setupVBInfos)
@ -281,6 +297,7 @@ void CVertexBufferGL3::setupVBInfos(CVertexBufferInfo &vb)
}
// ***************************************************************************
void CVertexBufferGL3::invalidate()
{
H_AUTO_OGL(CVertexBufferGLARB_invalidate)
@ -295,6 +312,201 @@ void CVertexBufferGL3::invalidate()
m_IteratorInLostVBList = m_Driver->_LostVBList.begin();
}
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
CVertexBufferAMDPinned::CVertexBufferAMDPinned(CDriverGL3 *drv, uint size, uint numVertices, CVertexBuffer::TPreferredMemory preferred, CVertexBuffer *vb)
: IVertexBufferGL3(drv, vb, IVertexBufferGL3::AMDPinned),
m_MemType(preferred),
m_VertexPtr(NULL),
m_VertexObjectId(0)
{
H_AUTO_OGL(CVertexBufferAMDPinned_CVertexBufferAMDPinned)
// Create id and bind
GLuint vertexBufferID;
nglGenBuffers(1, &vertexBufferID);
nglBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, vertexBufferID);
// Initialize
// Align allocated to page size, which is assumed to be 4K
m_VertexPtrAllocated = new char[size + 4096];
uintptr_t addr = (uintptr_t)m_VertexPtrAllocated;
addr = (addr + 4095) & (~0xfff);
m_VertexPtrAligned = (void *)addr;
nglBufferData(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, size, m_VertexPtrAligned, drv->vertexBufferUsageGL3(preferred));
if (glGetError() == GL_INVALID_OPERATION)
{
nlerror("Failed to pin memory");
nglDeleteBuffers(1, &vertexBufferID);
vertexBufferID = 0;
}
m_VertexObjectId = vertexBufferID;
// Unbind
nglBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0);
}
// ***************************************************************************
CVertexBufferAMDPinned::~CVertexBufferAMDPinned()
{
H_AUTO_OGL(CVertexBufferAMDPinned_CVertexBufferAMDPinnedDtor)
if (m_Driver && m_VertexObjectId)
{
if (m_Driver->_DriverGLStates.getCurrBoundARBVertexBuffer() == m_VertexObjectId)
{
m_Driver->_DriverGLStates.forceBindARBVertexBuffer(0);
}
}
if (m_VertexObjectId)
{
GLuint id = (GLuint)m_VertexObjectId;
nlassert(nglIsBuffer(id));
nglDeleteBuffers(1, &id);
}
delete m_VertexPtrAllocated;
m_VertexPtrAllocated = NULL;
m_VertexPtrAligned = NULL;
nlassert(m_VertexPtr == NULL);
}
// ***************************************************************************
void *CVertexBufferAMDPinned::lock()
{
H_AUTO_OGL(CVertexBufferAMDPinned_lock);
if (m_VertexPtr) // Already locked...
return m_VertexPtr;
if (!m_VertexObjectId) // Failed to pin
return m_VertexPtrAligned;
// Profiling
TTicks beforeLock = 0;
if (m_Driver->_VBHardProfiling)
{
beforeLock= CTime::getPerformanceTime();
}
// Lock
m_Driver->_DriverGLStates.bindARBVertexBuffer(m_VertexObjectId);
switch (m_MemType)
{
case CVertexBuffer::AGPVolatile:
case CVertexBuffer::RAMVolatile:
nlerror("Volatile currently not supported by pinned memory, this would require a re-allocating RAM, and thus require a fast allocation mechanism");
m_VertexPtr = NULL;
break;
case CVertexBuffer::RAMPreferred:
m_VertexPtr = nglMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
break;
default:
m_VertexPtr = nglMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
break;
}
m_Driver->_DriverGLStates.forceBindARBVertexBuffer(0);
nlassert(m_VertexPtr);
nlassert(m_VertexPtr == m_VertexPtrAligned);
// Profiling
if (m_Driver->_VBHardProfiling)
{
TTicks afterLock;
afterLock = CTime::getPerformanceTime();
m_Driver->appendVBHardLockProfile(afterLock - beforeLock, VB);
}
return m_VertexPtr;
}
// ***************************************************************************
void CVertexBufferAMDPinned::unlock()
{
H_AUTO_OGL(CVertexBufferAMDPinned_unlock);
m_VertexPtr = NULL;
if (!m_VertexObjectId)
return;
// Profiling
TTicks beforeLock = 0;
if (m_Driver->_VBHardProfiling)
{
beforeLock = CTime::getPerformanceTime();
}
// Unlock
m_Driver->_DriverGLStates.bindARBVertexBuffer(m_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 *CVertexBufferAMDPinned::getPointer()
{
H_AUTO_OGL(CVertexBufferAMDPinned_getPointer)
return m_VertexPtr;
}
// ***************************************************************************
void CVertexBufferAMDPinned::unlock(uint /* startVert */,uint /* endVert */)
{
H_AUTO_OGL(CVertexBufferAMDPinned_unlock)
unlock();
}
// ***************************************************************************
void CVertexBufferAMDPinned::enable()
{
H_AUTO_OGL(CVertexBufferAMDPinned_enable)
if (m_Driver->_CurrentVertexBufferGL != this)
{
m_Driver->_CurrentVertexBufferGL = this;
}
}
// ***************************************************************************
void CVertexBufferAMDPinned::disable()
{
H_AUTO_OGL(CVertexBufferAMDPinned_disable)
if (m_Driver->_CurrentVertexBufferGL != NULL)
{
m_Driver->_CurrentVertexBufferGL = NULL;
}
}
// ***************************************************************************
void CVertexBufferAMDPinned::setupVBInfos(CVertexBufferInfo &vb)
{
H_AUTO_OGL(CVertexBufferAMDPinned_setupVBInfos)
vb.VertexObjectId = m_VertexObjectId;
}
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
#ifdef NL_STATIC
} // NLDRIVERGL3
#endif

@ -33,7 +33,7 @@ class CVertexBufferGL3;
class IVertexBufferGL3
{
public:
enum TVBType { GL3 };
enum TVBType { GL3, AMDPinned };
IVertexBufferGL3(CDriverGL3 *drv, CVertexBuffer *vb, TVBType vbType);
virtual ~IVertexBufferGL3();
@ -62,7 +62,7 @@ protected:
class CVertexBufferGL3 : public IVertexBufferGL3
{
public:
CVertexBufferGL3(CDriverGL3 *drv, CVertexBuffer *vb);
CVertexBufferGL3(CDriverGL3 *drv, uint size, uint numVertices, CVertexBuffer::TPreferredMemory preferred, CVertexBuffer *vb);
virtual ~CVertexBufferGL3();
/// \name Implementation
@ -76,9 +76,6 @@ public:
virtual void setupVBInfos(CVertexBufferInfo &vb);
// @}
/// Setup ptrs allocated by createVBHard()
void initGL(uint vertexObjectID, CVertexBuffer::TPreferredMemory memType);
/// Invalidate the buffer (when it is lost, or when a lock fails)
void invalidate();
@ -96,6 +93,31 @@ private:
uint m_VertexObjectId;
};
class CVertexBufferAMDPinned : public IVertexBufferGL3
{
public:
CVertexBufferAMDPinned(CDriverGL3 *drv, uint size, uint numVertices, CVertexBuffer::TPreferredMemory preferred, CVertexBuffer *vb);
virtual ~CVertexBufferAMDPinned();
/// \name Implementation
// @{
virtual void *lock();
virtual void unlock();
virtual void unlock(uint startVert, uint endVert);
virtual void *getPointer();
virtual void enable();
virtual void disable();
virtual void setupVBInfos(CVertexBufferInfo &vb);
// @}
private:
CVertexBuffer::TPreferredMemory m_MemType;
void *m_VertexPtrAllocated;
void *m_VertexPtrAligned;
void *m_VertexPtr;
uint m_VertexObjectId;
};
#ifdef NL_STATIC
} // NLDRIVERGL3
#endif

Loading…
Cancel
Save