Merge branch 'Graphic_Update' into GLSL-master

Conflicts:
	Source/Core/VideoCommon/Src/VertexManagerBase.cpp
	Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp
	Source/Plugins/Plugin_VideoOGL/Src/Render.cpp
	Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp
This commit is contained in:
degasus
2013-01-14 21:36:31 +01:00
20 changed files with 691 additions and 546 deletions

View File

@ -26,48 +26,9 @@
#include "NativeVertexFormat.h"
#include "VertexManager.h"
#define COMPILED_CODE_SIZE 4096
// TODO: Use this again for performance, but without VAO we never know exactly the last configuration
static u32 s_prevcomponents; // previous state set
/*
#ifdef _WIN32
#ifdef _M_IX86
#define USE_JIT
#endif
#endif
*/
// Note the use of CallCdeclFunction3I etc.
// This is a horrible hack that is necessary because in 64-bit mode, Opengl32.dll is based way, way above the 32-bit
// address space that is within reach of a CALL, and just doing &fn gives us these high uncallable addresses. So we
// want to grab the function pointers from the import table instead.
// This problem does not apply to glew functions, only core opengl32 functions.
// Here's some global state. We only use this to keep track of what we've sent to the OpenGL state
// machine.
#ifdef USE_JIT
DECLARE_IMPORT(glNormalPointer);
DECLARE_IMPORT(glVertexPointer);
DECLARE_IMPORT(glColorPointer);
DECLARE_IMPORT(glTexCoordPointer);
#endif
class GLVertexFormat : public NativeVertexFormat
{
u8 *m_compiledCode;
PortableVertexDeclaration vtx_decl;
public:
GLVertexFormat();
~GLVertexFormat();
virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
virtual void SetupVertexPointers();
};
namespace OGL
{
@ -76,23 +37,14 @@ NativeVertexFormat* VertexManager::CreateNativeVertexFormat()
return new GLVertexFormat();
}
}
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
glDeleteVertexArrays(1, &VAO);
}
inline GLuint VarToGL(VarType t)
@ -105,105 +57,44 @@ 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);
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)
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;
}
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
VertexManager *vm = (OGL::VertexManager*)g_vertex_manager;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
// the element buffer is bound directly to the vao, so we must it set for every vao
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vm->m_index_buffers);
glBindBuffer(GL_ARRAY_BUFFER, vm->m_vertex_buffers);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, vtx_decl.stride, (u8*)NULL);
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]));
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) {
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]));
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]);
}
}
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]));
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]);
}
}
}
@ -212,75 +103,21 @@ void GLVertexFormat::SetupVertexPointers() {
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, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.texcoord_offset[i]));
vtx_decl.stride, (u8*)NULL + 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));
glEnableVertexAttribArray(SHADER_POSMTX_ATTRIB);
glVertexAttribPointer(SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, vtx_decl.stride, (u8*)NULL + vtx_decl.posmtx_offset);
}
#endif
if (s_prevcomponents != m_components)
{
// vertices
glEnableClientState(GL_VERTEX_ARRAY);
// matrices
if ((m_components & VB_HAS_POSMTXIDX) != (s_prevcomponents & VB_HAS_POSMTXIDX))
{
if (m_components & VB_HAS_POSMTXIDX)
glEnableVertexAttribArray(SHADER_POSMTX_ATTRIB);
else
glDisableVertexAttribArray(SHADER_POSMTX_ATTRIB);
}
// normals
if ((m_components & VB_HAS_NRM0) != (s_prevcomponents & VB_HAS_NRM0))
{
if (m_components & VB_HAS_NRM0)
glEnableClientState(GL_NORMAL_ARRAY);
else
glDisableClientState(GL_NORMAL_ARRAY);
}
if ((m_components & VB_HAS_NRM1) != (s_prevcomponents & VB_HAS_NRM1))
{
if (m_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 ((m_components & (VB_HAS_COL0 << i)) != (s_prevcomponents & (VB_HAS_COL0 << i)))
{
if (m_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 ((m_components & (VB_HAS_UV0 << i)) != (s_prevcomponents & (VB_HAS_UV0 << i)))
{
glClientActiveTexture(GL_TEXTURE0 + i);
if (m_components & (VB_HAS_UV0 << i))
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
else
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
s_prevcomponents = m_components;
}
vm->m_last_vao = VAO;
}
void GLVertexFormat::SetupVertexPointers() {
}
}

View File

@ -193,10 +193,6 @@ RasterFont::RasterFont()
glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, NULL);
glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
// TODO: this after merging with graphic_update
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
RasterFont::~RasterFont()
@ -288,10 +284,6 @@ void RasterFont::printMultilineText(const char *text, double start_x, double sta
glBindTexture(GL_TEXTURE_2D, texture);
glDrawArrays(GL_TRIANGLES, 0, usage/4);
// TODO: this after merging with graphic_update
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
}

View File

@ -64,6 +64,7 @@
#include "BPFunctions.h"
#include "FPSCounter.h"
#include "ConfigManager.h"
#include "VertexManager.h"
#include "main.h" // Local
#ifdef _WIN32
@ -296,6 +297,20 @@ Renderer::Renderer()
"GPU: Does your video card support OpenGL 3.0?");
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_bHaveCoverageMSAA = strstr(ptoken, "GL_NV_framebuffer_multisample_coverage") != NULL;
@ -415,10 +430,6 @@ Renderer::Renderer()
glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*5, NULL);
glEnableVertexAttribArray(SHADER_COLOR0_ATTRIB);
glVertexAttribPointer(SHADER_COLOR0_ATTRIB, 3, GL_FLOAT, 0, sizeof(GLfloat)*5, (GLfloat*)NULL+2);
// TODO: this after merging with graphic_update
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glStencilFunc(GL_ALWAYS, 0, 0);
glBlendFunc(GL_ONE, GL_ONE);
@ -603,10 +614,6 @@ void Renderer::DrawDebugInfo()
ProgramShaderCache::SetBothShaders(s_ShowEFBCopyRegions_PS.glprogid, s_ShowEFBCopyRegions_VS.glprogid);
glBindVertexArray( s_ShowEFBCopyRegions_VAO );
glDrawArrays(GL_LINES, 0, stats.efb_regions.size() * 2*6);
// TODO: this after merging with graphic_update
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Restore Line Size
glLineWidth(lSize);
@ -1429,6 +1436,10 @@ void Renderer::RestoreAPIState()
glPolygonMode(GL_FRONT_AND_BACK, g_ActiveConfig.bWireFrame ? GL_LINE : GL_FILL);
ProgramShaderCache::SetBothShaders(0, 0);
VertexManager *vm = (OGL::VertexManager*)g_vertex_manager;
glBindBuffer(GL_ARRAY_BUFFER, vm->m_vertex_buffers);
vm->m_last_vao = 0;
}
void Renderer::SetGenerationMode()

View File

@ -375,10 +375,6 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
glBindVertexArray(vbo_it->second.vao);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
// TODO: this after merging with graphic_update
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);

View File

@ -183,10 +183,6 @@ void Init()
glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL);
glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
// TODO: this after merging with graphic_update
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenRenderbuffers(1, &s_dstRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, s_dstRenderBuffer);
@ -285,10 +281,6 @@ void EncodeToRamUsingShader(GLuint srcTexture, const TargetRectangle& sourceRc,
glBindVertexArray( s_encode_VAO );
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
// TODO: this after merging with graphic_update
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
GL_REPORT_ERRORD();
@ -475,10 +467,6 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTextur
glBindVertexArray( s_decode_VAO );
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
// TODO: this after merging with graphic_update
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
GL_REPORT_ERRORD();
// reset state

View File

@ -49,58 +49,177 @@ 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 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;
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();
VertexManager::~VertexManager()
{
DestroyDeviceObjects();
}
void VertexManager::CreateDeviceObjects()
{
GL_REPORT_ERRORD();
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 = 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");
}
glGenBuffers(1, &m_vertex_buffers);
GL_REPORT_ERROR();
glGenBuffers(1, &m_index_buffers);
GL_REPORT_ERROR();
glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffers );
GL_REPORT_ERROR();
glBufferData(GL_ARRAY_BUFFER, m_vertex_buffer_size, NULL, GL_STREAM_DRAW );
GL_REPORT_ERROR();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffers );
GL_REPORT_ERROR();
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer_size, NULL, GL_STREAM_DRAW );
GL_REPORT_ERROR();
m_index_buffer_cursor = 0;
m_vertex_buffer_cursor = 0;
m_CurrentVertexFmt = NULL;
m_last_vao = 0;
}
void VertexManager::DestroyDeviceObjects()
{
GL_REPORT_ERRORD();
glBindBuffer(GL_ARRAY_BUFFER, 0 );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0 );
GL_REPORT_ERROR();
glDeleteBuffers(1, &m_vertex_buffers);
GL_REPORT_ERROR();
glDeleteBuffers(1, &m_index_buffers);
GL_REPORT_ERROR();
}
void VertexManager::Draw()
void VertexManager::PrepareDrawBuffers(u32 stride)
{
if (IndexGenerator::GetNumTriangles() > 0)
u8* pVertices = NULL;
u16* pIndices = NULL;
int vertex_data_size = IndexGenerator::GetNumVerts() * stride;
int triangle_index_size = IndexGenerator::GetTriangleindexLen();
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;
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 || m_index_buffer_cursor >= m_index_buffer_size - index_data_size)
{
glDrawElements(GL_TRIANGLES, IndexGenerator::GetTriangleindexLen(), GL_UNSIGNED_SHORT, TIBuffer);
LockMode |= GL_MAP_INVALIDATE_BUFFER_BIT;
m_vertex_buffer_cursor = 0;
m_index_buffer_cursor = 0;
}
else
{
LockMode |= /*GL_MAP_INVALIDATE_RANGE_BIT |*/ GL_MAP_UNSYNCHRONIZED_BIT;
}
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);
}
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);
}
else // could that happen? out-of-memory?
{
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::Draw(u32 stride)
{
int triangle_index_size = IndexGenerator::GetTriangleindexLen();
int line_index_size = IndexGenerator::GetLineindexLen();
int point_index_size = IndexGenerator::GetPointindexLen();
int StartIndex = m_index_buffer_cursor;
int basevertex = m_vertex_buffer_cursor / stride;
if (triangle_index_size > 0)
{
glDrawElementsBaseVertex(GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+StartIndex, basevertex);
StartIndex += triangle_index_size * sizeof(u16);
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
if (IndexGenerator::GetNumLines() > 0)
if (line_index_size > 0)
{
glDrawElements(GL_LINES, IndexGenerator::GetLineindexLen(), GL_UNSIGNED_SHORT, LIBuffer);
glDrawElementsBaseVertex(GL_LINES, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+StartIndex, basevertex);
StartIndex += line_index_size * sizeof(u16);
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
if (IndexGenerator::GetNumPoints() > 0)
if (point_index_size > 0)
{
glDrawElements(GL_POINTS, IndexGenerator::GetPointindexLen(), GL_UNSIGNED_SHORT, PIBuffer);
glDrawElementsBaseVertex(GL_POINTS, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+StartIndex, basevertex);
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
}
void VertexManager::vFlush()
{
if (LocalVBuffer == s_pCurBufferPointer) return;
if (Flushed) return;
Flushed=true;
VideoFifo_CheckEFBAccess();
#if defined(_DEBUG) || defined(DEBUGFAST)
PRIM_LOG("frame%d:\n texgen=%d, numchan=%d, dualtex=%d, ztex=%d, cole=%d, alpe=%d, ze=%d", g_ActiveConfig.iSaveTargetId, xfregs.numTexGen.numTexGens,
@ -132,10 +251,15 @@ 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();
GLVertexFormat *nativeVertexFmt = (GLVertexFormat*)g_nativeVertexFmt;
u32 stride = nativeVertexFmt->GetVertexStride();
if(m_last_vao != nativeVertexFmt->VAO) {
glBindVertexArray(nativeVertexFmt->VAO);
m_last_vao = nativeVertexFmt->VAO;
}
PrepareDrawBuffers(stride);
GL_REPORT_ERRORD();
u32 usedtextures = 0;
@ -148,7 +272,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))
{
@ -215,7 +339,7 @@ void VertexManager::vFlush()
g_nativeVertexFmt->SetupVertexPointers();
GL_REPORT_ERRORD();
Draw();
Draw(stride);
// run through vertex groups again to set alpha
if (useDstAlpha && !dualSourcePossible)
@ -235,7 +359,8 @@ void VertexManager::vFlush()
glDisable(GL_BLEND);
Draw();
Draw(stride);
// restore color mask
g_renderer->SetColorMask();
@ -243,11 +368,11 @@ 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);
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)
{

View File

@ -24,6 +24,19 @@
namespace OGL
{
class GLVertexFormat : public NativeVertexFormat
{
PortableVertexDeclaration vtx_decl;
public:
GLVertexFormat();
~GLVertexFormat();
virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
virtual void SetupVertexPointers();
GLuint VAO;
};
// Handles the OpenGL details of drawing lots of vertices quickly.
// Other functionality is moving out.
@ -31,14 +44,24 @@ class VertexManager : public ::VertexManager
{
public:
VertexManager();
~VertexManager();
NativeVertexFormat* CreateNativeVertexFormat();
void CreateDeviceObjects();
void DestroyDeviceObjects();
// NativeVertexFormat use this
GLuint m_vertex_buffers;
GLuint m_index_buffers;
GLuint m_last_vao;
private:
void Draw();
// temp
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;
NativeVertexFormat *m_CurrentVertexFmt;
};
}