mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-21 05:09:34 -06:00
Implement the new buffer approach in opengl. sadly in my machine it gives my only 2 more fps and if your hardware does not support ARB_map_buffer_range is even slower than plain vertex arrays.
change naming in all the backends vertex managers to make more easy to continue with the merge an some future improvements. please test this as i'm interested in knowing the performance in linux and windows with the different hardware platforms.
This commit is contained in:
@ -48,38 +48,194 @@ extern NativeVertexFormat *g_nativeVertexFmt;
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
//static GLint max_Index_size = 0;
|
||||
|
||||
//static GLuint s_vboBuffers[MAXVBOBUFFERCOUNT] = {0};
|
||||
//static int s_nCurVBOIndex = 0; // current free buffer
|
||||
//This are the initially requeted size for the buffers expresed in bytes
|
||||
const u32 IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * 16 * sizeof(u16);
|
||||
const u32 VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE * 16;
|
||||
const u32 MAX_VBUFFER_COUNT = 2;
|
||||
|
||||
VertexManager::VertexManager()
|
||||
{
|
||||
// TODO: doesn't seem to be used anywhere
|
||||
CreateDeviceObjects();
|
||||
}
|
||||
|
||||
//glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*)&max_Index_size);
|
||||
//
|
||||
//if (max_Index_size > MAXIBUFFERSIZE)
|
||||
// max_Index_size = MAXIBUFFERSIZE;
|
||||
//
|
||||
//GL_REPORT_ERRORD();
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
GL_REPORT_ERRORD();
|
||||
VertexManager::~VertexManager()
|
||||
{
|
||||
DestroyDeviceObjects();
|
||||
}
|
||||
|
||||
void VertexManager::CreateDeviceObjects()
|
||||
{
|
||||
|
||||
m_buffers_count = 0;
|
||||
m_vertex_buffers = NULL;
|
||||
m_index_buffers = NULL;
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
GL_REPORT_ERRORD();
|
||||
int max_Index_size = 0;
|
||||
int max_Vertex_size = 0;
|
||||
glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*)&max_Index_size);
|
||||
glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*)&max_Vertex_size);
|
||||
max_Index_size *= sizeof(u16);
|
||||
GL_REPORT_ERROR();
|
||||
m_index_buffer_size = IBUFFER_SIZE;
|
||||
if (max_Index_size > 0 && max_Index_size < m_index_buffer_size)
|
||||
m_index_buffer_size = max_Index_size;
|
||||
|
||||
m_vertex_buffer_size = VBUFFER_SIZE;
|
||||
if (max_Vertex_size > 0 && max_Vertex_size < m_vertex_buffer_size)
|
||||
m_vertex_buffer_size = max_Vertex_size;
|
||||
|
||||
if (m_index_buffer_size < VertexManager::MAXIBUFFERSIZE || m_vertex_buffer_size < VertexManager::MAXVBUFFERSIZE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_vertex_buffers = new GLuint[MAX_VBUFFER_COUNT];
|
||||
m_index_buffers = new GLuint[MAX_VBUFFER_COUNT];
|
||||
|
||||
glGenBuffers(MAX_VBUFFER_COUNT, m_vertex_buffers);
|
||||
GL_REPORT_ERROR();
|
||||
glGenBuffers(MAX_VBUFFER_COUNT, m_index_buffers);
|
||||
GL_REPORT_ERROR();
|
||||
for (u32 i = 0; i < MAX_VBUFFER_COUNT; i++)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffers[i] );
|
||||
GL_REPORT_ERROR();
|
||||
glBufferData(GL_ARRAY_BUFFER, m_vertex_buffer_size, NULL, GL_STREAM_DRAW );
|
||||
GL_REPORT_ERROR();
|
||||
}
|
||||
for (u32 i = 0; i < MAX_VBUFFER_COUNT; i++)
|
||||
{
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffers[i] );
|
||||
GL_REPORT_ERROR();
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer_size, NULL, GL_STREAM_DRAW );
|
||||
GL_REPORT_ERROR();
|
||||
}
|
||||
m_buffers_count = MAX_VBUFFER_COUNT;
|
||||
m_current_index_buffer = 0;
|
||||
m_current_vertex_buffer = 0;
|
||||
m_index_buffer_cursor = 0;
|
||||
m_vertex_buffer_cursor = 0;
|
||||
}
|
||||
void VertexManager::DestroyDeviceObjects()
|
||||
{
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
GL_REPORT_ERRORD();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, NULL );
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL );
|
||||
GL_REPORT_ERROR();
|
||||
if(m_vertex_buffers)
|
||||
{
|
||||
glDeleteBuffers(MAX_VBUFFER_COUNT, m_vertex_buffers);
|
||||
GL_REPORT_ERROR();
|
||||
delete [] m_vertex_buffers;
|
||||
}
|
||||
if(m_index_buffers)
|
||||
{
|
||||
glDeleteBuffers(MAX_VBUFFER_COUNT, m_index_buffers);
|
||||
GL_REPORT_ERROR();
|
||||
delete [] m_index_buffers;
|
||||
}
|
||||
m_vertex_buffers = NULL;
|
||||
m_index_buffers = NULL;
|
||||
}
|
||||
|
||||
void VertexManager::Draw()
|
||||
void VertexManager::PrepareDrawBuffers(u32 stride)
|
||||
{
|
||||
if (!m_buffers_count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
u8* pVertices = NULL;
|
||||
u16* pIndices = NULL;
|
||||
int vertex_data_size = IndexGenerator::GetNumVerts() * stride;
|
||||
int triangle_index_size = IndexGenerator::GetTriangleindexLen() * sizeof(u16);
|
||||
int line_index_size = IndexGenerator::GetLineindexLen() * sizeof(u16);
|
||||
int point_index_size = IndexGenerator::GetPointindexLen() * sizeof(u16);
|
||||
int index_data_size = triangle_index_size + line_index_size + point_index_size;
|
||||
GLbitfield LockMode = GL_MAP_WRITE_BIT;
|
||||
if (m_vertex_buffer_cursor > m_vertex_buffer_size - vertex_data_size)
|
||||
{
|
||||
LockMode |= GL_MAP_INVALIDATE_BUFFER_BIT;
|
||||
m_vertex_buffer_cursor = 0;
|
||||
m_current_vertex_buffer = (m_current_vertex_buffer + 1) % m_buffers_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
LockMode |= GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffers[m_current_vertex_buffer]);
|
||||
if(GLEW_ARB_map_buffer_range)
|
||||
{
|
||||
pVertices = (u8*)glMapBufferRange(GL_ARRAY_BUFFER, m_vertex_buffer_cursor, vertex_data_size, LockMode);
|
||||
if(pVertices)
|
||||
{
|
||||
memcpy(pVertices, LocalVBuffer, vertex_data_size);
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBufferSubData(GL_ARRAY_BUFFER, m_vertex_buffer_cursor, vertex_data_size, LocalVBuffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glBufferSubData(GL_ARRAY_BUFFER, m_vertex_buffer_cursor, vertex_data_size, LocalVBuffer);
|
||||
}
|
||||
|
||||
LockMode = GL_MAP_WRITE_BIT;
|
||||
|
||||
if (m_index_buffer_cursor > m_index_buffer_size - index_data_size)
|
||||
{
|
||||
LockMode |= GL_MAP_INVALIDATE_BUFFER_BIT;
|
||||
m_index_buffer_cursor = 0;
|
||||
m_current_index_buffer = (m_current_index_buffer + 1) % m_buffers_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
LockMode |= GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
|
||||
}
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffers[m_current_index_buffer]);
|
||||
if(GLEW_ARB_map_buffer_range)
|
||||
{
|
||||
pIndices = (u16*)glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer_cursor , index_data_size, LockMode);
|
||||
if(pIndices)
|
||||
{
|
||||
if(triangle_index_size)
|
||||
{
|
||||
memcpy(pIndices, TIBuffer, triangle_index_size);
|
||||
pIndices += triangle_index_size;
|
||||
}
|
||||
if(line_index_size)
|
||||
{
|
||||
memcpy(pIndices, LIBuffer, line_index_size);
|
||||
pIndices += line_index_size;
|
||||
}
|
||||
if(point_index_size)
|
||||
{
|
||||
memcpy(pIndices, PIBuffer, point_index_size);
|
||||
}
|
||||
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(triangle_index_size)
|
||||
{
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer_cursor, triangle_index_size, TIBuffer);
|
||||
}
|
||||
if(line_index_size)
|
||||
{
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer_cursor + triangle_index_size, line_index_size, LIBuffer);
|
||||
}
|
||||
if(point_index_size)
|
||||
{
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer_cursor + triangle_index_size + line_index_size, point_index_size, PIBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VertexManager::DrawVertexArray()
|
||||
{
|
||||
if (IndexGenerator::GetNumTriangles() > 0)
|
||||
{
|
||||
@ -98,6 +254,31 @@ void VertexManager::Draw()
|
||||
}
|
||||
}
|
||||
|
||||
void VertexManager::DrawVertexBufferObject()
|
||||
{
|
||||
int triangle_index_size = IndexGenerator::GetTriangleindexLen();
|
||||
int line_index_size = IndexGenerator::GetLineindexLen();
|
||||
int point_index_size = IndexGenerator::GetPointindexLen();
|
||||
int StartIndex = m_index_buffer_cursor;
|
||||
if (triangle_index_size > 0)
|
||||
{
|
||||
glDrawElements(GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (GLvoid*)StartIndex);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (line_index_size > 0)
|
||||
{
|
||||
StartIndex += triangle_index_size * sizeof(u16);
|
||||
glDrawElements(GL_LINES, line_index_size, GL_UNSIGNED_SHORT, (GLvoid*)StartIndex);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (point_index_size > 0)
|
||||
{
|
||||
StartIndex += line_index_size * sizeof(u16);
|
||||
glDrawElements(GL_POINTS, point_index_size, GL_UNSIGNED_SHORT, (GLvoid*)StartIndex);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
}
|
||||
|
||||
void VertexManager::vFlush()
|
||||
{
|
||||
if (LocalVBuffer == s_pCurBufferPointer) return;
|
||||
@ -134,13 +315,17 @@ void VertexManager::vFlush()
|
||||
|
||||
(void)GL_REPORT_ERROR();
|
||||
|
||||
//glBindBuffer(GL_ARRAY_BUFFER, s_vboBuffers[s_nCurVBOIndex]);
|
||||
//glBufferData(GL_ARRAY_BUFFER, s_pCurBufferPointer - LocalVBuffer, LocalVBuffer, GL_STREAM_DRAW);
|
||||
GL_REPORT_ERRORD();
|
||||
u32 stride = g_nativeVertexFmt->GetVertexStride();
|
||||
|
||||
// setup the pointers
|
||||
if (g_nativeVertexFmt)
|
||||
PrepareDrawBuffers(stride);
|
||||
if(m_buffers_count)
|
||||
{
|
||||
((GLVertexFormat*)g_nativeVertexFmt)->SetupVertexPointersOffset(m_vertex_buffer_cursor);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_nativeVertexFmt->SetupVertexPointers();
|
||||
}
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
u32 usedtextures = 0;
|
||||
@ -153,7 +338,7 @@ void VertexManager::vFlush()
|
||||
if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages)
|
||||
usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
{
|
||||
if (usedtextures & (1 << i))
|
||||
{
|
||||
@ -217,7 +402,7 @@ void VertexManager::vFlush()
|
||||
if (ps) PixelShaderCache::SetCurrentShader(ps->glprogid); // Lego Star Wars crashes here.
|
||||
if (vs) VertexShaderCache::SetCurrentShader(vs->glprogid);
|
||||
|
||||
Draw();
|
||||
if(m_buffers_count) { DrawVertexBufferObject(); }else{ DrawVertexArray();};
|
||||
|
||||
// run through vertex groups again to set alpha
|
||||
if (useDstAlpha && !dualSourcePossible)
|
||||
@ -230,7 +415,7 @@ void VertexManager::vFlush()
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
Draw();
|
||||
if(m_buffers_count) { DrawVertexBufferObject(); }else{ DrawVertexArray();};
|
||||
// restore color mask
|
||||
g_renderer->SetColorMask();
|
||||
|
||||
@ -238,11 +423,12 @@ void VertexManager::vFlush()
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);
|
||||
|
||||
//s_nCurVBOIndex = (s_nCurVBOIndex + 1) % ARRAYSIZE(s_vboBuffers);
|
||||
s_pCurBufferPointer = LocalVBuffer;
|
||||
IndexGenerator::Start(TIBuffer,LIBuffer,PIBuffer);
|
||||
|
||||
if(m_buffers_count)
|
||||
{
|
||||
m_index_buffer_cursor += (IndexGenerator::GetTriangleindexLen() + IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen()) * sizeof(u16);
|
||||
m_vertex_buffer_cursor += IndexGenerator::GetNumVerts() * stride;
|
||||
}
|
||||
ResetBuffer();
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (g_ActiveConfig.iLog & CONF_SAVESHADERS)
|
||||
{
|
||||
|
Reference in New Issue
Block a user