diff --git a/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp b/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp index 3a98332562..8669d32711 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp @@ -27,8 +27,6 @@ #define COMPILED_CODE_SIZE 4096 -// TODO: this guy is never initialized -u32 s_prevcomponents; // previous state set /* #ifdef _WIN32 #ifdef _M_IX86 @@ -63,19 +61,13 @@ NativeVertexFormat* VertexManager::CreateNativeVertexFormat() GLVertexFormat::GLVertexFormat() { -#ifdef USE_JIT - m_compiledCode = (u8 *)AllocateExecutableMemory(COMPILED_CODE_SIZE, false); - if (m_compiledCode) - memset(m_compiledCode, 0, COMPILED_CODE_SIZE); -#endif + } GLVertexFormat::~GLVertexFormat() { -#ifdef USE_JIT - FreeMemoryPages(m_compiledCode, COMPILED_CODE_SIZE); - m_compiledCode = 0; -#endif + VertexManager *vm = (OGL::VertexManager*)g_vertex_manager; + glDeleteVertexArrays(vm->m_buffers_count, VAO); } inline GLuint VarToGL(VarType t) @@ -88,227 +80,69 @@ inline GLuint VarToGL(VarType t) void GLVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl) { - s_prevcomponents = 0; - - vertex_stride = _vtx_decl.stride; - using namespace Gen; + this->vtx_decl = _vtx_decl; + vertex_stride = vtx_decl.stride; // We will not allow vertex components causing uneven strides. - if (_vtx_decl.stride & 3) - PanicAlert("Uneven vertex stride: %i", _vtx_decl.stride); - -#ifdef USE_JIT - Gen::XEmitter emit(m_compiledCode); - // Alright, we have our vertex declaration. Compile some crazy code to set it quickly using GL. - emit.ABI_EmitPrologue(6); + if (vertex_stride & 3) + PanicAlert("Uneven vertex stride: %i", vertex_stride); - emit.CallCdeclFunction4_I(glVertexPointer, 3, GL_FLOAT, _vtx_decl.stride, 0); + VertexManager *vm = (OGL::VertexManager*)g_vertex_manager; + + VAO = new GLuint[vm->m_buffers_count]; + glGenVertexArrays(vm->m_buffers_count, VAO); + for(u32 i=0; im_buffers_count; i++) { + glBindVertexArray(VAO[i]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vm->m_index_buffers[i]); + glBindBuffer(GL_ARRAY_BUFFER, vm->m_vertex_buffers[i]); + + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, vtx_decl.stride, (u8*)NULL); + + if (vtx_decl.num_normals >= 1) { + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(VarToGL(vtx_decl.normal_gl_type), vtx_decl.stride, (u8*)NULL + vtx_decl.normal_offset[0]); + if (vtx_decl.num_normals == 3) { + glEnableVertexAttribArray(SHADER_NORM1_ATTRIB); + glEnableVertexAttribArray(SHADER_NORM2_ATTRIB); + glVertexAttribPointer(SHADER_NORM1_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (u8*)NULL + vtx_decl.normal_offset[1]); + glVertexAttribPointer(SHADER_NORM2_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (u8*)NULL + vtx_decl.normal_offset[2]); + } + } - if (_vtx_decl.num_normals >= 1) - { - emit.CallCdeclFunction3_I(glNormalPointer, VarToGL(_vtx_decl.normal_gl_type), _vtx_decl.stride, _vtx_decl.normal_offset[0]); - if (_vtx_decl.num_normals == 3) { - emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM1_ATTRIB, _vtx_decl.normal_gl_size, VarToGL(_vtx_decl.normal_gl_type), GL_TRUE, _vtx_decl.stride, _vtx_decl.normal_offset[1]); - emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM2_ATTRIB, _vtx_decl.normal_gl_size, VarToGL(_vtx_decl.normal_gl_type), GL_TRUE, _vtx_decl.stride, _vtx_decl.normal_offset[2]); + for (int i = 0; i < 2; i++) { + if (vtx_decl.color_offset[i] != -1) { + if (i == 0) { + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (u8*)NULL + vtx_decl.color_offset[i]); + } else { + glEnableClientState(GL_SECONDARY_COLOR_ARRAY); + glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (u8*)NULL + vtx_decl.color_offset[i]); + } + } + } + + for (int i = 0; i < 8; i++) { + if (vtx_decl.texcoord_offset[i] != -1) { + int id = GL_TEXTURE0 + i; + glClientActiveTexture(id); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(vtx_decl.texcoord_size[i], VarToGL(vtx_decl.texcoord_gl_type[i]), + vtx_decl.stride, (u8*)NULL + vtx_decl.texcoord_offset[i]); + } + } + + if (vtx_decl.posmtx_offset != -1) { + glEnableVertexAttribArray(SHADER_POSMTX_ATTRIB); + glVertexAttribPointer(SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, vtx_decl.stride, (u8*)NULL + vtx_decl.posmtx_offset); } } - - for (int i = 0; i < 2; i++) - { - if (_vtx_decl.color_offset[i] != -1) - { - if (i == 0) - emit.CallCdeclFunction4_I(glColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]); - else - emit.CallCdeclFunction4((void *)glSecondaryColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]); - } - } - - for (int i = 0; i < 8; i++) - { - if (_vtx_decl.texcoord_offset[i] != -1) - { - int id = GL_TEXTURE0 + i; -#ifdef _M_X64 -#ifdef _MSC_VER - emit.MOV(32, R(RCX), Imm32(id)); -#else - emit.MOV(32, R(RDI), Imm32(id)); -#endif -#else - emit.ABI_AlignStack(1 * 4); - emit.PUSH(32, Imm32(id)); -#endif - emit.CALL((void *)glClientActiveTexture); -#ifndef _M_X64 -#ifdef _WIN32 - // don't inc stack on windows, stdcall -#else - emit.ABI_RestoreStack(1 * 4); -#endif -#endif - emit.CallCdeclFunction4_I( - glTexCoordPointer, _vtx_decl.texcoord_size[i], VarToGL(_vtx_decl.texcoord_gl_type[i]), - _vtx_decl.stride, _vtx_decl.texcoord_offset[i]); - } - } - - if (_vtx_decl.posmtx_offset != -1) - emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, _vtx_decl.stride, _vtx_decl.posmtx_offset); - - emit.ABI_EmitEpilogue(6); - - if (emit.GetCodePtr() - (u8*)m_compiledCode > COMPILED_CODE_SIZE) - Crash(); - -#endif - this->vtx_decl = _vtx_decl; + + glBindBuffer(GL_ARRAY_BUFFER, vm->m_vertex_buffers[vm->m_current_buffer]); } void GLVertexFormat::SetupVertexPointers() { - // Cast a pointer to compiled code to a pointer to a function taking no parameters, through a (void *) cast first to - // get around type checking errors, and call it. -#ifdef USE_JIT - ((void (*)())(void*)m_compiledCode)(); -#else - glVertexPointer(3, GL_FLOAT, vtx_decl.stride, VertexManager::s_pBaseBufferPointer); - if (vtx_decl.num_normals >= 1) { - glNormalPointer(VarToGL(vtx_decl.normal_gl_type), vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[0])); - if (vtx_decl.num_normals == 3) { - glVertexAttribPointer(SHADER_NORM1_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[1])); - glVertexAttribPointer(SHADER_NORM2_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[2])); - } - } - - for (int i = 0; i < 2; i++) { - if (vtx_decl.color_offset[i] != -1) { - if (i == 0) - glColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.color_offset[i])); - else { - glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.color_offset[i])); - } - } - } - - for (int i = 0; i < 8; i++) { - if (vtx_decl.texcoord_offset[i] != -1) { - int id = GL_TEXTURE0 + i; - glClientActiveTexture(id); - glTexCoordPointer(vtx_decl.texcoord_size[i], VarToGL(vtx_decl.texcoord_gl_type[i]), - vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.texcoord_offset[i])); - } - } - - if (vtx_decl.posmtx_offset != -1) { - glVertexAttribPointer(SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.posmtx_offset)); - } -#endif -} - -void GLVertexFormat::SetupVertexPointersOffset(u32 offset) { - // Cast a pointer to compiled code to a pointer to a function taking no parameters, through a (void *) cast first to - // get around type checking errors, and call it. -#ifdef USE_JIT - ((void (*)())(void*)m_compiledCode)(); -#else - glVertexPointer(3, GL_FLOAT, vtx_decl.stride, (GLvoid*)offset); - if (vtx_decl.num_normals >= 1) { - glNormalPointer(VarToGL(vtx_decl.normal_gl_type), vtx_decl.stride, (GLvoid*)(offset + vtx_decl.normal_offset[0])); - if (vtx_decl.num_normals == 3) { - glVertexAttribPointer(SHADER_NORM1_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (GLvoid*)(offset + vtx_decl.normal_offset[1])); - glVertexAttribPointer(SHADER_NORM2_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (GLvoid*)(offset + vtx_decl.normal_offset[2])); - } - } - - for (int i = 0; i < 2; i++) { - if (vtx_decl.color_offset[i] != -1) { - if (i == 0) - glColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (GLvoid*)(offset + vtx_decl.color_offset[i])); - else { - glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (GLvoid*)(offset + vtx_decl.color_offset[i])); - } - } - } - - for (int i = 0; i < 8; i++) { - if (vtx_decl.texcoord_offset[i] != -1) { - int id = GL_TEXTURE0 + i; - glClientActiveTexture(id); - glTexCoordPointer(vtx_decl.texcoord_size[i], VarToGL(vtx_decl.texcoord_gl_type[i]), - vtx_decl.stride, (GLvoid*)(offset + vtx_decl.texcoord_offset[i])); - } - } - - if (vtx_decl.posmtx_offset != -1) { - glVertexAttribPointer(SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, vtx_decl.stride, (GLvoid*)(offset + vtx_decl.posmtx_offset)); - } -#endif -} - -void GLVertexFormat::EnableComponents(u32 components) -{ - if (s_prevcomponents != components) - { - VertexManager::Flush(); - - // matrices - if ((components & VB_HAS_POSMTXIDX) != (s_prevcomponents & VB_HAS_POSMTXIDX)) - { - if (components & VB_HAS_POSMTXIDX) - glEnableVertexAttribArray(SHADER_POSMTX_ATTRIB); - else - glDisableVertexAttribArray(SHADER_POSMTX_ATTRIB); - } - - // normals - if ((components & VB_HAS_NRM0) != (s_prevcomponents & VB_HAS_NRM0)) - { - if (components & VB_HAS_NRM0) - glEnableClientState(GL_NORMAL_ARRAY); - else - glDisableClientState(GL_NORMAL_ARRAY); - } - if ((components & VB_HAS_NRM1) != (s_prevcomponents & VB_HAS_NRM1)) - { - if (components & VB_HAS_NRM1) { - glEnableVertexAttribArray(SHADER_NORM1_ATTRIB); - glEnableVertexAttribArray(SHADER_NORM2_ATTRIB); - } - else { - glDisableVertexAttribArray(SHADER_NORM1_ATTRIB); - glDisableVertexAttribArray(SHADER_NORM2_ATTRIB); - } - } - - // color - for (int i = 0; i < 2; ++i) - { - if ((components & (VB_HAS_COL0 << i)) != (s_prevcomponents & (VB_HAS_COL0 << i))) - { - if (components & (VB_HAS_COL0 << i)) - glEnableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY); - else - glDisableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY); - } - } - - // tex - for (int i = 0; i < 8; ++i) - { - if ((components & (VB_HAS_UV0 << i)) != (s_prevcomponents & (VB_HAS_UV0 << i))) - { - glClientActiveTexture(GL_TEXTURE0 + i); - if (components & (VB_HAS_UV0 << i)) - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - else - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } - } - - s_prevcomponents = components; - } -} - - } +} \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index a6121e1436..d4b945199c 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -62,6 +62,7 @@ #include "Host.h" #include "BPFunctions.h" #include "FPSCounter.h" +#include "VertexManager.h" #include "main.h" // Local #ifdef _WIN32 @@ -310,6 +311,20 @@ Renderer::Renderer() "GPU: Does your video card support OpenGL 2.x?"); bSuccess = false; } + + if (!GLEW_ARB_map_buffer_range) + { + ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_ARB_map_buffer_range.\n" + "GPU: Does your video card support OpenGL 3.0?"); + bSuccess = false; + } + + if (!GLEW_ARB_draw_elements_base_vertex) + { + ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_ARB_draw_elements_base_vertex.\n" + "GPU: Does your video card support OpenGL 3.2?"); + bSuccess = false; + } s_bHaveFramebufferBlit = strstr(ptoken, "GL_EXT_framebuffer_blit") != NULL; s_bHaveCoverageMSAA = strstr(ptoken, "GL_NV_framebuffer_multisample_coverage") != NULL; @@ -1415,6 +1430,10 @@ void Renderer::ResetAPIState() glDisable(GL_BLEND); glDepthMask(GL_FALSE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + // TODO: remove this after merging with immediate-remove + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); } void Renderer::RestoreAPIState() @@ -1432,6 +1451,10 @@ void Renderer::RestoreAPIState() VertexShaderCache::SetCurrentShader(0); PixelShaderCache::SetCurrentShader(0); + + VertexManager *vm = (OGL::VertexManager*)g_vertex_manager; + glBindBuffer(GL_ARRAY_BUFFER, vm->m_vertex_buffers[vm->m_current_buffer]); + vm->m_last_vao = 0; } void Renderer::SetGenerationMode() diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index bbd196ba78..ceb04daeca 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -49,8 +49,10 @@ extern NativeVertexFormat *g_nativeVertexFmt; namespace OGL { //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_IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * 16 * sizeof(u16); +const u32 MAX_VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE * 16; +const u32 MIN_IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * 1 * sizeof(u16); +const u32 MIN_VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE * 1; const u32 MAX_VBUFFER_COUNT = 2; VertexManager::VertexManager() @@ -70,82 +72,77 @@ void VertexManager::CreateDeviceObjects() m_index_buffers = NULL; glEnableClientState(GL_VERTEX_ARRAY); GL_REPORT_ERRORD(); - int max_Index_size = 0; - int max_Vertex_size = 0; + u32 max_Index_size = 0; + u32 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_index_buffer_size = std::min(MAX_IBUFFER_SIZE, std::max(max_Index_size, MIN_IBUFFER_SIZE)); + m_vertex_buffer_size = std::min(MAX_VBUFFER_SIZE, std::max(max_Vertex_size, MIN_VBUFFER_SIZE)); + + // should be not bigger, but we need it. so try and have luck + if (m_index_buffer_size > max_Index_size) { + ERROR_LOG(VIDEO, "GL_MAX_ELEMENTS_INDICES to small, so try it anyway. good luck\n"); + } + if (m_vertex_buffer_size > max_Vertex_size) { + ERROR_LOG(VIDEO, "GL_MAX_ELEMENTS_VERTICES to small, so try it anyway. good luck\n"); } - m_vertex_buffers = new GLuint[MAX_VBUFFER_COUNT]; - m_index_buffers = new GLuint[MAX_VBUFFER_COUNT]; + //TODO: find out, how many buffers fit in gpu memory + m_buffers_count = MAX_VBUFFER_COUNT; + + m_vertex_buffers = new GLuint[m_buffers_count]; + m_index_buffers = new GLuint[m_buffers_count]; - glGenBuffers(MAX_VBUFFER_COUNT, m_vertex_buffers); + glGenBuffers(m_buffers_count, m_vertex_buffers); GL_REPORT_ERROR(); - glGenBuffers(MAX_VBUFFER_COUNT, m_index_buffers); + glGenBuffers(m_buffers_count, m_index_buffers); GL_REPORT_ERROR(); - for (u32 i = 0; i < MAX_VBUFFER_COUNT; i++) + for (u32 i = 0; i < m_buffers_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++) + for (u32 i = 0; i < m_buffers_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 = m_index_buffer_size; - m_vertex_buffer_cursor = m_vertex_buffer_size; + m_current_buffer = 0; + m_index_buffer_cursor = 0; + m_vertex_buffer_cursor = 0; m_CurrentVertexFmt = NULL; + m_last_vao = 0; } void VertexManager::DestroyDeviceObjects() { glDisableClientState(GL_VERTEX_ARRAY); GL_REPORT_ERRORD(); - glBindBuffer(GL_ARRAY_BUFFER, NULL ); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL ); + glBindBuffer(GL_ARRAY_BUFFER, 0 ); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0 ); 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; - } + + glDeleteBuffers(m_buffers_count, m_vertex_buffers); + GL_REPORT_ERROR(); + delete [] m_vertex_buffers; + + glDeleteBuffers(m_buffers_count, m_index_buffers); + GL_REPORT_ERROR(); + delete [] m_index_buffers; + m_vertex_buffers = NULL; m_index_buffers = NULL; + m_buffers_count = 0; } void VertexManager::PrepareDrawBuffers(u32 stride) { - if (!m_buffers_count) - { - return; - } u8* pVertices = NULL; u16* pIndices = NULL; int vertex_data_size = IndexGenerator::GetNumVerts() * stride; @@ -153,141 +150,82 @@ void VertexManager::PrepareDrawBuffers(u32 stride) int line_index_size = IndexGenerator::GetLineindexLen(); int point_index_size = IndexGenerator::GetPointindexLen(); int index_data_size = (triangle_index_size + line_index_size + point_index_size) * sizeof(u16); - GLbitfield LockMode = GL_MAP_WRITE_BIT; + GLVertexFormat *nativeVertexFmt = (GLVertexFormat*)g_nativeVertexFmt; + GLbitfield LockMode = GL_MAP_WRITE_BIT; + m_vertex_buffer_cursor--; m_vertex_buffer_cursor = m_vertex_buffer_cursor - (m_vertex_buffer_cursor % stride) + stride; - if (m_vertex_buffer_cursor > m_vertex_buffer_size - vertex_data_size) + + if (m_vertex_buffer_cursor >= m_vertex_buffer_size - vertex_data_size || m_index_buffer_cursor >= m_index_buffer_size - index_data_size) { + // do we really want to set this? this require a reallocation. usualy only one buffer with reallocation, or much buffers without it LockMode |= GL_MAP_INVALIDATE_BUFFER_BIT; m_vertex_buffer_cursor = 0; - m_current_vertex_buffer = (m_current_vertex_buffer + 1) % m_buffers_count; - glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffers[m_current_vertex_buffer]); + m_index_buffer_cursor = 0; + m_current_buffer = (m_current_buffer + 1) % m_buffers_count; + glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffers[m_current_buffer]); } else { LockMode |= GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT; - } - 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 + + // this replaces SetupVertexPointers and must be called after switching buffer and befor uploading indexes + // but could be deleted, if we only use one buffer with orphaning + if(m_last_vao != nativeVertexFmt->VAO[m_current_buffer]) + glBindVertexArray(nativeVertexFmt->VAO[m_current_buffer]); + + 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 // could that happen? out-of-memory? { 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) + + pIndices = (u16*)glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer_cursor , index_data_size, LockMode); + if(pIndices) { - LockMode |= GL_MAP_INVALIDATE_BUFFER_BIT; - m_index_buffer_cursor = 0; - m_current_index_buffer = (m_current_index_buffer + 1) % m_buffers_count; - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffers[m_current_index_buffer]); - } - else - { - LockMode |= GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT; - } - 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 * sizeof(u16)); - pIndices += triangle_index_size; - } - if(line_index_size) - { - memcpy(pIndices, LIBuffer, line_index_size * sizeof(u16)); - pIndices += line_index_size; - } - if(point_index_size) - { - memcpy(pIndices, PIBuffer, point_index_size * sizeof(u16)); - } - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + if(triangle_index_size) + { + memcpy(pIndices, TIBuffer, triangle_index_size * sizeof(u16)); + pIndices += triangle_index_size; } - else - { - if(triangle_index_size) - { - triangle_index_size *= sizeof(u16); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer_cursor, triangle_index_size, TIBuffer); - } - if(line_index_size) - { - line_index_size *= sizeof(u16); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer_cursor + triangle_index_size, line_index_size, LIBuffer); - } - if(point_index_size) - { - point_index_size *= sizeof(u16); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer_cursor + triangle_index_size + line_index_size, point_index_size, PIBuffer); - } + if(line_index_size) + { + memcpy(pIndices, LIBuffer, line_index_size * sizeof(u16)); + pIndices += line_index_size; } - } -} - -void VertexManager::DrawVertexArray() -{ - int triangle_index_size = IndexGenerator::GetTriangleindexLen(); - int line_index_size = IndexGenerator::GetLineindexLen(); - int point_index_size = IndexGenerator::GetPointindexLen(); - if (triangle_index_size > 0) - { - glDrawElements(GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, TIBuffer); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); + if(point_index_size) + { + memcpy(pIndices, PIBuffer, point_index_size * sizeof(u16)); + } + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); } - if (line_index_size > 0) + else // could that happen? out-of-memory? { - glDrawElements(GL_LINES, line_index_size, GL_UNSIGNED_SHORT, LIBuffer); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } - if (point_index_size > 0) - { - glDrawElements(GL_POINTS, IndexGenerator::GetPointindexLen(), GL_UNSIGNED_SHORT, PIBuffer); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); + if(triangle_index_size) + { + triangle_index_size *= sizeof(u16); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer_cursor, triangle_index_size, TIBuffer); + } + if(line_index_size) + { + line_index_size *= sizeof(u16); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer_cursor + triangle_index_size, line_index_size, LIBuffer); + } + if(point_index_size) + { + point_index_size *= sizeof(u16); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer_cursor + triangle_index_size + line_index_size, point_index_size, PIBuffer); + } } } -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); - StartIndex += triangle_index_size * sizeof(u16); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } - if (line_index_size > 0) - { - glDrawElements(GL_LINES, line_index_size, GL_UNSIGNED_SHORT, (GLvoid*)StartIndex); - StartIndex += line_index_size * sizeof(u16); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } - if (point_index_size > 0) - { - glDrawElements(GL_POINTS, point_index_size, GL_UNSIGNED_SHORT, (GLvoid*)StartIndex); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } -} - -void VertexManager::DrawVertexBufferObjectBase(u32 stride) +void VertexManager::Draw(u32 stride) { int triangle_index_size = IndexGenerator::GetTriangleindexLen(); int line_index_size = IndexGenerator::GetLineindexLen(); @@ -296,19 +234,19 @@ void VertexManager::DrawVertexBufferObjectBase(u32 stride) int basevertex = m_vertex_buffer_cursor / stride; if (triangle_index_size > 0) { - glDrawElementsBaseVertex(GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (GLvoid*)StartIndex, basevertex); + glDrawElementsBaseVertex(GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+StartIndex, basevertex); StartIndex += triangle_index_size * sizeof(u16); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } if (line_index_size > 0) { - glDrawElementsBaseVertex(GL_LINES, line_index_size, GL_UNSIGNED_SHORT, (GLvoid*)StartIndex, basevertex); + glDrawElementsBaseVertex(GL_LINES, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+StartIndex, basevertex); StartIndex += line_index_size * sizeof(u16); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } if (point_index_size > 0) { - glDrawElementsBaseVertex(GL_POINTS, point_index_size, GL_UNSIGNED_SHORT, (GLvoid*)StartIndex, basevertex); + glDrawElementsBaseVertex(GL_POINTS, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+StartIndex, basevertex); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } } @@ -349,19 +287,6 @@ void VertexManager::vFlush() u32 stride = g_nativeVertexFmt->GetVertexStride(); PrepareDrawBuffers(stride); - //still testing if this line is enabled to reduce the amount of vertex setup call everything goes wrong - //if(m_CurrentVertexFmt != g_nativeVertexFmt || !GLEW_ARB_draw_elements_base_vertex ) - { - if(m_buffers_count) - { - ((GLVertexFormat*)g_nativeVertexFmt)->SetupVertexPointersOffset(GLEW_ARB_draw_elements_base_vertex ? 0 : m_vertex_buffer_cursor); - } - else - { - g_nativeVertexFmt->SetupVertexPointers(); - } - m_CurrentVertexFmt = g_nativeVertexFmt; - } GL_REPORT_ERRORD(); u32 usedtextures = 0; @@ -438,21 +363,7 @@ void VertexManager::vFlush() if (ps) PixelShaderCache::SetCurrentShader(ps->glprogid); // Lego Star Wars crashes here. if (vs) VertexShaderCache::SetCurrentShader(vs->glprogid); - if(m_buffers_count) - { - if(GLEW_ARB_draw_elements_base_vertex) - { - DrawVertexBufferObjectBase(stride); - } - else - { - DrawVertexBufferObject(); - } - } - else - { - DrawVertexArray(); - } + Draw(stride); // run through vertex groups again to set alpha if (useDstAlpha && !dualSourcePossible) @@ -465,21 +376,8 @@ void VertexManager::vFlush() glDisable(GL_BLEND); - if(m_buffers_count) - { - if(GLEW_ARB_draw_elements_base_vertex) - { - DrawVertexBufferObjectBase(stride); - } - else - { - DrawVertexBufferObject(); - } - } - else - { - DrawVertexArray(); - } + Draw(stride); + // restore color mask g_renderer->SetColorMask(); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h index db80f87a2b..91319b54f2 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h @@ -26,7 +26,6 @@ namespace OGL { class GLVertexFormat : public NativeVertexFormat { - u8 *m_compiledCode; PortableVertexDeclaration vtx_decl; public: @@ -35,8 +34,8 @@ namespace OGL virtual void Initialize(const PortableVertexDeclaration &_vtx_decl); virtual void SetupVertexPointers(); - virtual void SetupVertexPointersOffset(u32 offset); - virtual void EnableComponents(u32 components); + + GLuint *VAO; }; // Handles the OpenGL details of drawing lots of vertices quickly. @@ -49,21 +48,21 @@ public: NativeVertexFormat* CreateNativeVertexFormat(); void CreateDeviceObjects(); void DestroyDeviceObjects(); + + // NativeVertexFormat use this + u32 m_buffers_count; + u32 m_current_buffer; + GLuint* m_vertex_buffers; + GLuint* m_index_buffers; + GLuint m_last_vao; private: - void DrawVertexArray(); - void DrawVertexBufferObject(); - void DrawVertexBufferObjectBase(u32 stride); + void Draw(u32 stride); void vFlush(); void PrepareDrawBuffers(u32 stride); u32 m_vertex_buffer_cursor; u32 m_vertex_buffer_size; u32 m_index_buffer_cursor; u32 m_index_buffer_size; - u32 m_buffers_count; - u32 m_current_vertex_buffer; - u32 m_current_index_buffer; - GLuint* m_vertex_buffers; - GLuint* m_index_buffers; NativeVertexFormat *m_CurrentVertexFmt; };