From 30a5c91c995f1d51460caa53beba221bd74a0acf Mon Sep 17 00:00:00 2001 From: hrydgard Date: Tue, 25 Nov 2008 21:15:31 +0000 Subject: [PATCH] GL: Safer vertex loading (should fix the new zelda crash), added vertex format logging to "show some statistics" git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1295 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 7 ++- .../Plugin_VideoOGL/Src/VertexLoader.cpp | 62 ++++++++++++++----- .../Plugin_VideoOGL/Src/VertexLoader.h | 7 +++ .../Src/VertexLoaderManager.cpp | 8 +++ .../Plugin_VideoOGL/Src/VertexLoaderManager.h | 3 + .../Plugin_VideoOGL/Src/VertexManager.cpp | 34 +++++----- .../Plugin_VideoOGL/Src/VertexManager.h | 1 - 7 files changed, 85 insertions(+), 37 deletions(-) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index 573aa9cdbf..b962d6cac0 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -39,6 +39,7 @@ #include "rasterfont.h" #include "VertexShader.h" #include "PixelShaderManager.h" +#include "VertexLoaderManager.h" #include "VertexLoader.h" #include "XFB.h" #if !defined(OSX64) @@ -791,7 +792,11 @@ void Renderer::SwapBuffers() p+=sprintf(p,"Num BP loads (DL): %i\n",stats.thisFrame.numBPLoadsInDL); p+=sprintf(p,"Num vertex loaders: %i\n",stats.numVertexLoaders); - Renderer::RenderText(st, 20, 20, 0xFF00FFFF); + + std::string text = st; + VertexLoaderManager::AppendListToString(&text); + + Renderer::RenderText(text.c_str(), 20, 20, 0xFF00FFFF); } else { diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.cpp index c426359b60..8d335467c5 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.cpp @@ -23,6 +23,7 @@ #include "Config.h" #include "Profiler.h" #include "MemoryUtil.h" +#include "StringUtil.h" #include "x64Emitter.h" #include "ABI.h" @@ -110,6 +111,7 @@ void LOADERDECL TexMtx_Write_Short3() VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr) { + m_numLoadedVertices = 0; m_VertexSize = 0; m_numPipelineStages = 0; m_NativeFmt = new NativeVertexFormat(); @@ -135,9 +137,18 @@ void VertexLoader::CompileVertexTranslator() { m_VertexSize = 0; +#ifdef USE_JIT u8 *old_code_ptr = GetWritableCodePtr(); SetCodePtr(m_compiledCode); ABI_EmitPrologue(4); + + // Start loop here + MOV(32, M(&tcIndex), Imm32(0)); + MOV(32, M(&colIndex), Imm32(0)); + MOV(32, M(&s_texmtxwrite), Imm32(0)); + MOV(32, M(&s_texmtxread), Imm32(0)); +#endif + // Colors const int col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1}; // TextureCoord @@ -450,6 +461,9 @@ void VertexLoader::CompileVertexTranslator() if (vtx_decl.stride != offset) PanicAlert("offset/stride mismatch, %i %i", vtx_decl.stride, offset); #ifdef USE_JIT + // End loop here + // SUB(32, M(&vtxCounter), Imm8(1)); + // J_CC(CC_NZ, loop); ABI_EmitEpilogue(4); #endif SetCodePtr(old_code_ptr); @@ -565,6 +579,8 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count) { DVSTARTPROFILE(); + m_numLoadedVertices += count; + // Flush if our vertex format is different from the currently set. if (g_nativeVertexFmt != NULL && g_nativeVertexFmt != m_NativeFmt) { @@ -618,15 +634,9 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count) if (VertexManager::GetRemainingSize() < 2 * native_stride) VertexManager::Flush(); break; - case 0: // quads - granularity = 4; - break; - case 2: // tris - granularity = 3; - break; - case 5: // lines - granularity = 2; - break; + case 0: granularity = 4; break; // quads + case 2: granularity = 3; break; // tris + case 5: granularity = 2; break; // lines } int startv = 0, extraverts = 0; @@ -634,7 +644,8 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count) while (v < count) { - if (VertexManager::GetRemainingSize() < granularity*native_stride) { + int remainingVerts = VertexManager::GetRemainingSize() / native_stride; + if (remainingVerts < granularity) { INCSTAT(stats.thisFrame.numBufferSplits); // This buffer full - break current primitive and flush, to switch to the next buffer. u8* plastptr = VertexManager::s_pCurBufferPointer; @@ -675,22 +686,26 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count) } startv = v; } + int remainingPrims = remainingVerts / granularity; + remainingVerts = remainingPrims * granularity; + if (count - v < remainingVerts) + remainingVerts = count - v; - for (int s = 0; s < granularity; s++) + // Clean tight loader loop. Todo - build the loop into the JIT code. + for (int s = 0; s < remainingVerts; s++) { - tcIndex = 0; - colIndex = 0; - s_texmtxwrite = s_texmtxread = 0; #ifdef USE_JIT ((void (*)())(void*)m_compiledCode)(); #else + tcIndex = 0; + colIndex = 0; + s_texmtxwrite = s_texmtxread = 0; for (int i = 0; i < m_numPipelineStages; i++) m_PipelineStages[i](); #endif - PRIM_LOG("\n"); - v++; } + v += remainingVerts; } if (startv < count) @@ -742,3 +757,18 @@ void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2) m_VtxAttr.texCoord[7].Format = vat.g2.Tex7CoordFormat; m_VtxAttr.texCoord[7].Frac = vat.g2.Tex7Frac; }; + +void VertexLoader::AppendToString(std::string *dest) { + static const char *posMode[4] = { + "Invalid", + "Direct", + "Idx8", + "Idx16", + }; + static const char *posFormats[5] = { + "u8", "s8", "u16", "s16", "flt", + }; + dest->append(StringFromFormat("sz: %i skin: %i Pos: %i %s %s Nrm: %i %s %s - %i vtx\n", + m_VertexSize, m_VtxDesc.PosMatIdx, m_VtxAttr.PosElements ? 3 : 2, posMode[m_VtxDesc.Position], posFormats[m_VtxAttr.PosFormat], + m_VtxAttr.NormalElements, posMode[m_VtxDesc.Normal], posFormats[m_VtxAttr.NormalFormat], m_numLoadedVertices)); +} \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.h b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.h index 74586ad3db..b638ac9641 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.h @@ -18,6 +18,8 @@ #ifndef _VERTEXLOADER_H #define _VERTEXLOADER_H +#include + #include "CPMemory.h" #include "DataReader.h" @@ -59,6 +61,9 @@ public: int GetVertexSize() const {return m_VertexSize;} void RunVertices(int vtx_attr_group, int primitive, int count); + // For debugging / profiling + void AppendToString(std::string *dest); + private: enum { @@ -83,6 +88,8 @@ private: u8 *m_compiledCode; + int m_numLoadedVertices; + void SetupColor(int num, int _iMode, int _iFormat, int _iElements); void SetupTexCoord(int num, int _iMode, int _iFormat, int _iElements, int _iFrac); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoaderManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoaderManager.cpp index 447115db8e..464faf989f 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoaderManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoaderManager.cpp @@ -50,6 +50,14 @@ void Shutdown() g_VertexLoaderMap.clear(); } +void AppendListToString(std::string *dest) +{ + for (VertexLoaderMap::iterator iter = g_VertexLoaderMap.begin(); iter != g_VertexLoaderMap.end(); ++iter) + { + iter->second->AppendToString(dest); + } +} + void MarkAllDirty() { s_attr_dirty = 0xff; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoaderManager.h b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoaderManager.h index 8af8416474..ed07309210 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoaderManager.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoaderManager.h @@ -30,6 +30,9 @@ namespace VertexLoaderManager int GetVertexSize(int vtx_attr_group); void RunVertices(int vtx_attr_group, int primitive, int count); + // For debugging + void AppendListToString(std::string *dest); + // TODO - don't expose these like this. // static u8* s_pCurBufferPointer; }; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index a772813fa7..c62791c989 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -85,19 +85,6 @@ void ResetBuffer() s_vStoredPrimitives.resize(0); } -void ResetComponents() -{ - s_prevcomponents = 0; - glDisableVertexAttribArray(SHADER_POSMTX_ATTRIB); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableVertexAttribArray(SHADER_NORM1_ATTRIB); - glDisableVertexAttribArray(SHADER_NORM2_ATTRIB); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_SECONDARY_COLOR_ARRAY); - for (int i = 0; i < 8; i++) - glDisableClientState(GL_TEXTURE_COORD_ARRAY); -} - int GetRemainingSize() { return MAX_BUFFER_SIZE - (int)(s_pCurBufferPointer - s_pBaseBufferPointer); @@ -108,12 +95,21 @@ void AddVertices(int primitive, int numvertices) _assert_( numvertices > 0 ); ADDSTAT(stats.thisFrame.numPrims, numvertices); - /* - if (s_vStoredPrimitives.size() && s_vStoredPrimitives[s_vStoredPrimitives.size() - 1].first == primitive) { - // Actually, just count potential primitive joins. - // Doesn't seem worth it in Metroid Prime games. - INCSTAT(stats.thisFrame.numPrimitiveJoins); - }*/ + if (s_vStoredPrimitives.size() && s_vStoredPrimitives[s_vStoredPrimitives.size() - 1].first == c_primitiveType[primitive]) { + // We can join primitives for free here. Not likely to help much, though, but whatever... + if (c_primitiveType[primitive] == GL_TRIANGLES || + c_primitiveType[primitive] == GL_LINES || + c_primitiveType[primitive] == GL_POINTS || + c_primitiveType[primitive] == GL_QUADS) { + INCSTAT(stats.thisFrame.numPrimitiveJoins); + // Easy join + std::pair &last_pair = s_vStoredPrimitives[s_vStoredPrimitives.size() - 1]; + last_pair.second += numvertices; + return; + } + // Joining strips is a lot more work but would bring more gain. Not sure if it's worth it though. + } + s_vStoredPrimitives.push_back(std::pair(c_primitiveType[primitive], numvertices)); #if defined(_DEBUG) || defined(DEBUGFAST) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h index 214824f1d7..84e051ec03 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h @@ -30,7 +30,6 @@ bool Init(); void Shutdown(); void ResetBuffer(); -void ResetComponents(); void AddVertices(int primitive, int numvertices); void Flush(); // flushes the current buffer