diff --git a/Source/Core/VideoCommon/Src/NativeVertexFormat.h b/Source/Core/VideoCommon/Src/NativeVertexFormat.h index 64382ff040..bb9be45d79 100644 --- a/Source/Core/VideoCommon/Src/NativeVertexFormat.h +++ b/Source/Core/VideoCommon/Src/NativeVertexFormat.h @@ -18,7 +18,6 @@ #ifndef _NATIVEVERTEXFORMAT_H #define _NATIVEVERTEXFORMAT_H -#include "CPMemory.h" #include "PluginSpecs.h" // m_components @@ -58,6 +57,31 @@ enum { #define LOADERDECL __cdecl typedef void (LOADERDECL *TPipelineFunction)(const void *); +enum VarType { + VAR_BYTE, + VAR_UNSIGNED_BYTE, + VAR_SHORT, + VAR_UNSIGNED_SHORT, + VAR_FLOAT, +}; + +struct PortableVertexDeclaration +{ + int stride; + + int num_normals; + int normal_offset[3]; + VarType normal_gl_type; + int normal_gl_size; + VarType color_gl_type; // always GL_UNSIGNED_BYTE + int color_offset[2]; + VarType texcoord_gl_type[8]; + int texcoord_gl_size[8]; + int texcoord_offset[8]; + int texcoord_size[8]; + int posmtx_offset; +}; + // The implementation of this class is specific for GL/DX, so NativeVertexFormat.cpp // is in the respective plugin, not here in VideoCommon. @@ -66,15 +90,15 @@ typedef void (LOADERDECL *TPipelineFunction)(const void *); class NativeVertexFormat { u8* m_compiledCode; + PortableVertexDeclaration vtx_decl; public: NativeVertexFormat(); ~NativeVertexFormat(); - void Initialize(const TVtxDesc &vtx_desc, const TVtxAttr &vtx_attr); + void Initialize(const PortableVertexDeclaration &vtx_decl); void SetupVertexPointers() const; // TODO: move these in under private: - int m_VBVertexStride; // PC-side vertex stride u32 m_components; // VB_HAS_X. Bitmask telling what vertex components are present. }; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp b/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp index 7190a39ae5..c7659e26ab 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp @@ -27,6 +27,10 @@ #define COMPILED_CODE_SIZE 4096 +#ifdef _WIN32 +#define USE_JIT +#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 @@ -56,86 +60,52 @@ NativeVertexFormat::~NativeVertexFormat() m_compiledCode = 0; } -void NativeVertexFormat::SetupVertexPointers() const { - // 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. - ((void (*)())(void*)m_compiledCode)(); +inline GLuint VarToGL(VarType t) +{ + switch (t) { + case VAR_BYTE: return GL_BYTE; + case VAR_UNSIGNED_BYTE: return GL_UNSIGNED_BYTE; + case VAR_SHORT: return GL_SHORT; + case VAR_UNSIGNED_SHORT: return GL_UNSIGNED_SHORT; + case VAR_FLOAT: return GL_FLOAT; + } } -void NativeVertexFormat::Initialize(const TVtxDesc &vtx_desc, const TVtxAttr &vtx_attr) +void NativeVertexFormat::Initialize(const PortableVertexDeclaration &vtx_decl) { using namespace Gen; - const int col[2] = {vtx_desc.Color0, vtx_desc.Color1}; - // TextureCoord - const int tc[8] = { - vtx_desc.Tex0Coord, vtx_desc.Tex1Coord, vtx_desc.Tex2Coord, vtx_desc.Tex3Coord, - vtx_desc.Tex4Coord, vtx_desc.Tex5Coord, vtx_desc.Tex6Coord, vtx_desc.Tex7Coord, - }; - - DVSTARTPROFILE(); - if (m_VBVertexStride & 3) { + if (vtx_decl.stride & 3) { // We will not allow vertex components causing uneven strides. - PanicAlert("Uneven vertex stride: %i", m_VBVertexStride); + PanicAlert("Uneven vertex stride: %i", vtx_decl.stride); } - // compile the pointer set function - why? + // Alright, we have our vertex declaration. Compile some crazy code to set it quickly using GL. u8 *old_code_ptr = GetWritableCodePtr(); SetCodePtr(m_compiledCode); Util::EmitPrologue(6); - int offset = 0; - // Position, part 1 - if (vtx_desc.Position != NOT_PRESENT) { // TODO: Why the check? Always present, AFAIK! - CallCdeclFunction4_I(glVertexPointer, 3, GL_FLOAT, m_VBVertexStride, 0); - offset += 12; - } + CallCdeclFunction4_I(glVertexPointer, 3, GL_FLOAT, vtx_decl.stride, 0); - // Normals - if (vtx_desc.Normal != NOT_PRESENT) { - switch (vtx_attr.NormalFormat) { - case FORMAT_UBYTE: - case FORMAT_BYTE: - CallCdeclFunction3_I(glNormalPointer, GL_BYTE, m_VBVertexStride, offset); offset += 4; - if (vtx_attr.NormalElements) { - CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM1_ATTRIB, 4, GL_BYTE, GL_TRUE, m_VBVertexStride, offset); offset += 4; - CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM2_ATTRIB, 4, GL_BYTE, GL_TRUE, m_VBVertexStride, offset); offset += 4; - } - break; - case FORMAT_USHORT: - case FORMAT_SHORT: - CallCdeclFunction3_I(glNormalPointer, GL_SHORT, m_VBVertexStride, offset); offset += 8; - if (vtx_attr.NormalElements) { - CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM1_ATTRIB, 4, GL_SHORT, GL_TRUE, m_VBVertexStride, offset); offset += 8; - CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM2_ATTRIB, 4, GL_SHORT, GL_TRUE, m_VBVertexStride, offset); offset += 8; - } - break; - case FORMAT_FLOAT: - CallCdeclFunction3_I(glNormalPointer, GL_FLOAT, m_VBVertexStride, offset); offset += 12; - if (vtx_attr.NormalElements) { - CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM1_ATTRIB, 3, GL_FLOAT, GL_TRUE, m_VBVertexStride, offset); offset += 12; - CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM2_ATTRIB, 3, GL_FLOAT, GL_TRUE, m_VBVertexStride, offset); offset += 12; - } - break; - default: _assert_(0); break; + if (vtx_decl.num_normals >= 1) { + CallCdeclFunction3_I(glNormalPointer, VarToGL(vtx_decl.normal_gl_type), vtx_decl.stride, vtx_decl.normal_offset[0]); + if (vtx_decl.num_normals == 3) { + 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]); + 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]); } } - // TODO : With byte or short normals above, offset will be misaligned (not 4byte aligned)! Ugh! - for (int i = 0; i < 2; i++) { - if (col[i] != NOT_PRESENT) { - if (i) - CallCdeclFunction4((void *)glSecondaryColorPointer, 4, GL_UNSIGNED_BYTE, m_VBVertexStride, offset); + if (vtx_decl.color_offset[i] != -1) { + if (i == 0) + CallCdeclFunction4_I(glColorPointer, 4, GL_UNSIGNED_BYTE, vtx_decl.stride, vtx_decl.color_offset[i]); else - CallCdeclFunction4_I(glColorPointer, 4, GL_UNSIGNED_BYTE, m_VBVertexStride, offset); - offset += 4; + CallCdeclFunction4((void *)glSecondaryColorPointer, 4, GL_UNSIGNED_BYTE, vtx_decl.stride, vtx_decl.color_offset[i]); } } - // TextureCoord for (int i = 0; i < 8; i++) { - if (tc[i] != NOT_PRESENT || (m_components & (VB_HAS_TEXMTXIDX0 << i))) { + if (vtx_decl.texcoord_offset[i] != -1) { int id = GL_TEXTURE0 + i; #ifdef _M_X64 #ifdef _MSC_VER @@ -155,31 +125,16 @@ void NativeVertexFormat::Initialize(const TVtxDesc &vtx_desc, const TVtxAttr &vt ABI_RestoreStack(1 * 4); #endif #endif - // TODO : More potential disalignment! - if (m_components & (VB_HAS_TEXMTXIDX0 << i)) { - if (tc[i] != NOT_PRESENT) { - CallCdeclFunction4_I(glTexCoordPointer, 3, GL_FLOAT, m_VBVertexStride, offset); - offset += 12; - } - else { - CallCdeclFunction4_I(glTexCoordPointer, 3, GL_SHORT, m_VBVertexStride, offset); - offset += 8; - } - } - else { - CallCdeclFunction4_I(glTexCoordPointer, vtx_attr.texCoord[i].Elements ? 2 : 1, GL_FLOAT, m_VBVertexStride, offset); - offset += 4 * (vtx_attr.texCoord[i].Elements ? 2 : 1); - } + 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_desc.PosMatIdx) { - CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, m_VBVertexStride, offset); - offset += 4; + if (vtx_decl.posmtx_offset != -1) { + CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, vtx_decl.stride, vtx_decl.posmtx_offset); } - _assert_(offset + m_VBStridePad == m_VBVertexStride); - Util::EmitEpilogue(6); if (Gen::GetCodePtr() - (u8*)m_compiledCode > COMPILED_CODE_SIZE) { @@ -187,4 +142,44 @@ void NativeVertexFormat::Initialize(const TVtxDesc &vtx_desc, const TVtxAttr &vt } SetCodePtr(old_code_ptr); + this->vtx_decl = vtx_decl; } + +void NativeVertexFormat::SetupVertexPointers() const { + // 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, 0); + if (vtx_decl.num_normals >= 1) { + glNormalPointer(VarToGL(vtx_decl.normal_gl_type), vtx_decl.stride, (void *)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 *)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 *)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 *)vtx_decl.color_offset[i]); + else + glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)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 *)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 *)vtx_decl.posmtx_offset); + } +#endif +} \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.cpp index efc696fad3..ee45ed9787 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.cpp @@ -225,13 +225,24 @@ int VertexLoader::ComputeVertexSize() void VertexLoader::CompileVertexTranslator() { + // Colors + const int col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1}; + // TextureCoord + const int tc[8] = { + m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord, + m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, m_VtxDesc.Tex7Coord, + }; + // Reset pipeline m_numPipelineStages = 0; // It's a bit ugly that we poke inside m_NativeFmt in this function. Planning to fix this. - m_NativeFmt->m_VBVertexStride = 0; + native_stride = 0; m_NativeFmt->m_components = 0; + // Position + int offset = 0; + // m_VBVertexStride for texmtx and posmtx is computed later when writing. // Position Matrix Index @@ -250,8 +261,10 @@ void VertexLoader::CompileVertexTranslator() if (m_VtxDesc.Tex7MatIdx) {m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX7; WriteCall(TexMtx_ReadDirect_UByte); } // Position - if (m_VtxDesc.Position != NOT_PRESENT) - m_NativeFmt->m_VBVertexStride += 12; + if (m_VtxDesc.Position != NOT_PRESENT) { + offset += 12; + native_stride += 12; + } switch (m_VtxDesc.Position) { case NOT_PRESENT: {_assert_msg_(0, "Vertex descriptor without position!", "WTF?");} break; @@ -311,29 +324,22 @@ void VertexLoader::CompileVertexTranslator() case FORMAT_FLOAT: sizePro = 4*3; break; default: _assert_(0); break; } - m_NativeFmt->m_VBVertexStride += sizePro * (m_VtxAttr.NormalElements?3:1); + native_stride += sizePro * (m_VtxAttr.NormalElements?3:1); int numNormals = (m_VtxAttr.NormalElements == 1) ? NRM_THREE : NRM_ONE; m_NativeFmt->m_components |= VB_HAS_NRM0; + if (numNormals == NRM_THREE) m_NativeFmt->m_components |= VB_HAS_NRM1 | VB_HAS_NRM2; } - // Colors - int col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1}; for (int i = 0; i < 2; i++) { SetupColor(i, col[i], m_VtxAttr.color[i].Comp, m_VtxAttr.color[i].Elements); if (col[i] != NOT_PRESENT) - m_NativeFmt->m_VBVertexStride += 4; + native_stride += 4; } - // TextureCoord - int tc[8] = { - m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord, - m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, m_VtxDesc.Tex7Coord, - }; - // Texture matrix indices (remove if corresponding texture coordinate isn't enabled) for (int i = 0; i < 8; i++) { SetupTexCoord(i, tc[i], m_VtxAttr.texCoord[i].Format, m_VtxAttr.texCoord[i].Elements, m_VtxAttr.texCoord[i].Frac); @@ -341,17 +347,17 @@ void VertexLoader::CompileVertexTranslator() if (tc[i] != NOT_PRESENT) { // if texmtx is included, texcoord will always be 3 floats, z will be the texmtx index WriteCall(m_VtxAttr.texCoord[i].Elements ? TexMtx_Write_Float : TexMtx_Write_Float2); - m_NativeFmt->m_VBVertexStride += 12; + native_stride += 12; } else { WriteCall(TexMtx_Write_Short3); - m_NativeFmt->m_VBVertexStride += 8; // still include the texture coordinate, but this time as 6 bytes + native_stride += 8; // still include the texture coordinate, but this time as 6 + 2 bytes m_NativeFmt->m_components |= VB_HAS_UV0 << i; // have to include since using now } } else { if (tc[i] != NOT_PRESENT) - m_NativeFmt->m_VBVertexStride += 4 * (m_VtxAttr.texCoord[i].Elements ? 2 : 1); + native_stride += 4 * (m_VtxAttr.texCoord[i].Elements ? 2 : 1); } if (tc[i] == NOT_PRESENT) { @@ -370,17 +376,122 @@ void VertexLoader::CompileVertexTranslator() if (m_VtxDesc.PosMatIdx) { WriteCall(PosMtx_Write); - m_NativeFmt->m_VBVertexStride += 4; + native_stride += 4; } - m_NativeFmt->Initialize(m_VtxDesc, m_VtxAttr); + PortableVertexDeclaration vtx_decl; + + + int m_components = m_NativeFmt->m_components; + + const TVtxAttr &vtx_attr = m_VtxAttr; + const TVtxDesc &vtx_desc = m_VtxDesc; + // Normals + vtx_decl.num_normals = 0; + if (vtx_desc.Normal != NOT_PRESENT) { + vtx_decl.num_normals = vtx_attr.NormalElements ? 3 : 1; + switch (vtx_attr.NormalFormat) { + case FORMAT_UBYTE: + case FORMAT_BYTE: + vtx_decl.normal_gl_type = VAR_BYTE; + vtx_decl.normal_gl_size = 4; + vtx_decl.normal_offset[0] = offset; + offset += 4; + if (vtx_attr.NormalElements) { + vtx_decl.normal_offset[1] = offset; + offset += 4; + vtx_decl.normal_offset[2] = offset; + offset += 4; + } + break; + case FORMAT_USHORT: + case FORMAT_SHORT: + vtx_decl.normal_gl_type = VAR_SHORT; + vtx_decl.normal_gl_size = 4; + vtx_decl.normal_offset[0] = offset; + offset += 8; + if (vtx_attr.NormalElements) { + vtx_decl.normal_offset[1] = offset; + offset += 8; + vtx_decl.normal_offset[2] = offset; + offset += 8; + } + break; + case FORMAT_FLOAT: + vtx_decl.normal_gl_type = VAR_FLOAT; + vtx_decl.normal_gl_size = 3; + vtx_decl.normal_offset[0] = offset; + offset += 12; + if (vtx_attr.NormalElements) { + vtx_decl.normal_offset[1] = offset; + offset += 12; + vtx_decl.normal_offset[2] = offset; + offset += 12; + } + break; + default: _assert_(0); break; + } + } + + // TODO : With byte or short normals above, offset will be misaligned (not 4byte aligned)! Ugh! + vtx_decl.color_gl_type = VAR_UNSIGNED_BYTE; + for (int i = 0; i < 2; i++) { + if (col[i] != NOT_PRESENT) { + vtx_decl.color_offset[i] = offset; + offset += 4; + } else { + vtx_decl.color_offset[i] = -1; + } + } + + // TextureCoord + for (int i = 0; i < 8; i++) { + if (tc[i] != NOT_PRESENT || (m_components & (VB_HAS_TEXMTXIDX0 << i))) { + // TODO : More potential disalignment! + if (m_components & (VB_HAS_TEXMTXIDX0 << i)) { + if (tc[i] != NOT_PRESENT) { + vtx_decl.texcoord_offset[i] = offset; + vtx_decl.texcoord_gl_type[i] = VAR_FLOAT; + vtx_decl.texcoord_size[i] = 3; + offset += 12; + } + else { + vtx_decl.texcoord_offset[i] = offset; + vtx_decl.texcoord_gl_type[i] = VAR_SHORT; + vtx_decl.texcoord_size[i] = 4; + offset += 8; + } + } + else { + vtx_decl.texcoord_offset[i] = offset; + vtx_decl.texcoord_gl_type[i] = VAR_FLOAT; + vtx_decl.texcoord_size[i] = vtx_attr.texCoord[i].Elements ? 2 : 1; + offset += 4 * (vtx_attr.texCoord[i].Elements ? 2 : 1); + } + } else { + vtx_decl.texcoord_offset[i] = -1; + } + } + + if (vtx_desc.PosMatIdx) { + vtx_decl.posmtx_offset = offset; + offset += 4; + } else { + vtx_decl.posmtx_offset = -1; + } + + vtx_decl.stride = native_stride; + if (vtx_decl.stride != offset) + PanicAlert("offset/stride mismatch, %i %i", vtx_decl.stride, offset); + + m_NativeFmt->Initialize(vtx_decl); } void VertexLoader::SetupColor(int num, int mode, int format, int elements) { // if COL0 not present, then embed COL1 into COL0 - if (num == 1 && !(m_NativeFmt->m_components & VB_HAS_COL0)) - num = 0; +// if (num == 1 && !(m_NativeFmt->m_components & VB_HAS_COL0)) +// num = 0; m_NativeFmt->m_components |= VB_HAS_COL0 << num; switch (mode) @@ -526,11 +637,11 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count) switch (primitive) { case 3: // strip case 4: // fan - if (VertexManager::GetRemainingSize() < 3 * m_NativeFmt->m_VBVertexStride) + if (VertexManager::GetRemainingSize() < 3 * native_stride) VertexManager::Flush(); break; case 6: // line strip - if (VertexManager::GetRemainingSize() < 2 * m_NativeFmt->m_VBVertexStride) + if (VertexManager::GetRemainingSize() < 2 * native_stride) VertexManager::Flush(); break; case 0: // quads @@ -550,7 +661,7 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count) { if ((v % granularity) == 0) { - if (VertexManager::GetRemainingSize() < granularity*m_NativeFmt->m_VBVertexStride) { + if (VertexManager::GetRemainingSize() < granularity*native_stride) { // This buffer full - break current primitive and flush, to switch to the next buffer. u8* plastptr = VertexManager::s_pCurBufferPointer; if (v - startv > 0) @@ -561,27 +672,27 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count) case 3: // triangle strip, copy last two vertices // a little trick since we have to keep track of signs if (v & 1) { - memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-2*m_NativeFmt->m_VBVertexStride, m_NativeFmt->m_VBVertexStride); - memcpy_gc(VertexManager::s_pCurBufferPointer+m_NativeFmt->m_VBVertexStride, plastptr-m_NativeFmt->m_VBVertexStride*2, 2*m_NativeFmt->m_VBVertexStride); - VertexManager::s_pCurBufferPointer += m_NativeFmt->m_VBVertexStride*3; + memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-2*native_stride, native_stride); + memcpy_gc(VertexManager::s_pCurBufferPointer+native_stride, plastptr-native_stride*2, 2*native_stride); + VertexManager::s_pCurBufferPointer += native_stride*3; extraverts = 3; } else { - memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-m_NativeFmt->m_VBVertexStride*2, m_NativeFmt->m_VBVertexStride*2); - VertexManager::s_pCurBufferPointer += m_NativeFmt->m_VBVertexStride*2; + memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride*2, native_stride*2); + VertexManager::s_pCurBufferPointer += native_stride*2; extraverts = 2; } break; case 4: // tri fan, copy first and last vert - memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-m_NativeFmt->m_VBVertexStride*(v-startv+extraverts), m_NativeFmt->m_VBVertexStride); - VertexManager::s_pCurBufferPointer += m_NativeFmt->m_VBVertexStride; - memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-m_NativeFmt->m_VBVertexStride, m_NativeFmt->m_VBVertexStride); - VertexManager::s_pCurBufferPointer += m_NativeFmt->m_VBVertexStride; + memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride*(v-startv+extraverts), native_stride); + VertexManager::s_pCurBufferPointer += native_stride; + memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride, native_stride); + VertexManager::s_pCurBufferPointer += native_stride; extraverts = 2; break; case 6: // line strip - memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-m_NativeFmt->m_VBVertexStride, m_NativeFmt->m_VBVertexStride); - VertexManager::s_pCurBufferPointer += m_NativeFmt->m_VBVertexStride; + memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride, native_stride); + VertexManager::s_pCurBufferPointer += native_stride; extraverts = 1; break; default: diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.h b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.h index ef09c7762c..5a25fc6a6b 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.h @@ -75,6 +75,7 @@ private: // PC vertex format NativeVertexFormat *m_NativeFmt; + int native_stride; // Pipeline. To be JIT compiled in the future. TPipelineFunction m_PipelineStages[32]; // TODO - figure out real max. it's lower.