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
This commit is contained in:
parent
f1ab625f5c
commit
30a5c91c99
|
@ -39,6 +39,7 @@
|
||||||
#include "rasterfont.h"
|
#include "rasterfont.h"
|
||||||
#include "VertexShader.h"
|
#include "VertexShader.h"
|
||||||
#include "PixelShaderManager.h"
|
#include "PixelShaderManager.h"
|
||||||
|
#include "VertexLoaderManager.h"
|
||||||
#include "VertexLoader.h"
|
#include "VertexLoader.h"
|
||||||
#include "XFB.h"
|
#include "XFB.h"
|
||||||
#if !defined(OSX64)
|
#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 BP loads (DL): %i\n",stats.thisFrame.numBPLoadsInDL);
|
||||||
p+=sprintf(p,"Num vertex loaders: %i\n",stats.numVertexLoaders);
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Profiler.h"
|
#include "Profiler.h"
|
||||||
#include "MemoryUtil.h"
|
#include "MemoryUtil.h"
|
||||||
|
#include "StringUtil.h"
|
||||||
#include "x64Emitter.h"
|
#include "x64Emitter.h"
|
||||||
#include "ABI.h"
|
#include "ABI.h"
|
||||||
|
|
||||||
|
@ -110,6 +111,7 @@ void LOADERDECL TexMtx_Write_Short3()
|
||||||
|
|
||||||
VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr)
|
VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr)
|
||||||
{
|
{
|
||||||
|
m_numLoadedVertices = 0;
|
||||||
m_VertexSize = 0;
|
m_VertexSize = 0;
|
||||||
m_numPipelineStages = 0;
|
m_numPipelineStages = 0;
|
||||||
m_NativeFmt = new NativeVertexFormat();
|
m_NativeFmt = new NativeVertexFormat();
|
||||||
|
@ -135,9 +137,18 @@ void VertexLoader::CompileVertexTranslator()
|
||||||
{
|
{
|
||||||
m_VertexSize = 0;
|
m_VertexSize = 0;
|
||||||
|
|
||||||
|
#ifdef USE_JIT
|
||||||
u8 *old_code_ptr = GetWritableCodePtr();
|
u8 *old_code_ptr = GetWritableCodePtr();
|
||||||
SetCodePtr(m_compiledCode);
|
SetCodePtr(m_compiledCode);
|
||||||
ABI_EmitPrologue(4);
|
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
|
// Colors
|
||||||
const int col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1};
|
const int col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1};
|
||||||
// TextureCoord
|
// TextureCoord
|
||||||
|
@ -450,6 +461,9 @@ void VertexLoader::CompileVertexTranslator()
|
||||||
if (vtx_decl.stride != offset)
|
if (vtx_decl.stride != offset)
|
||||||
PanicAlert("offset/stride mismatch, %i %i", vtx_decl.stride, offset);
|
PanicAlert("offset/stride mismatch, %i %i", vtx_decl.stride, offset);
|
||||||
#ifdef USE_JIT
|
#ifdef USE_JIT
|
||||||
|
// End loop here
|
||||||
|
// SUB(32, M(&vtxCounter), Imm8(1));
|
||||||
|
// J_CC(CC_NZ, loop);
|
||||||
ABI_EmitEpilogue(4);
|
ABI_EmitEpilogue(4);
|
||||||
#endif
|
#endif
|
||||||
SetCodePtr(old_code_ptr);
|
SetCodePtr(old_code_ptr);
|
||||||
|
@ -565,6 +579,8 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count)
|
||||||
{
|
{
|
||||||
DVSTARTPROFILE();
|
DVSTARTPROFILE();
|
||||||
|
|
||||||
|
m_numLoadedVertices += count;
|
||||||
|
|
||||||
// Flush if our vertex format is different from the currently set.
|
// Flush if our vertex format is different from the currently set.
|
||||||
if (g_nativeVertexFmt != NULL && g_nativeVertexFmt != m_NativeFmt)
|
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)
|
if (VertexManager::GetRemainingSize() < 2 * native_stride)
|
||||||
VertexManager::Flush();
|
VertexManager::Flush();
|
||||||
break;
|
break;
|
||||||
case 0: // quads
|
case 0: granularity = 4; break; // quads
|
||||||
granularity = 4;
|
case 2: granularity = 3; break; // tris
|
||||||
break;
|
case 5: granularity = 2; break; // lines
|
||||||
case 2: // tris
|
|
||||||
granularity = 3;
|
|
||||||
break;
|
|
||||||
case 5: // lines
|
|
||||||
granularity = 2;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int startv = 0, extraverts = 0;
|
int startv = 0, extraverts = 0;
|
||||||
|
@ -634,7 +644,8 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count)
|
||||||
|
|
||||||
while (v < count)
|
while (v < count)
|
||||||
{
|
{
|
||||||
if (VertexManager::GetRemainingSize() < granularity*native_stride) {
|
int remainingVerts = VertexManager::GetRemainingSize() / native_stride;
|
||||||
|
if (remainingVerts < granularity) {
|
||||||
INCSTAT(stats.thisFrame.numBufferSplits);
|
INCSTAT(stats.thisFrame.numBufferSplits);
|
||||||
// This buffer full - break current primitive and flush, to switch to the next buffer.
|
// This buffer full - break current primitive and flush, to switch to the next buffer.
|
||||||
u8* plastptr = VertexManager::s_pCurBufferPointer;
|
u8* plastptr = VertexManager::s_pCurBufferPointer;
|
||||||
|
@ -675,22 +686,26 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count)
|
||||||
}
|
}
|
||||||
startv = v;
|
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
|
#ifdef USE_JIT
|
||||||
((void (*)())(void*)m_compiledCode)();
|
((void (*)())(void*)m_compiledCode)();
|
||||||
#else
|
#else
|
||||||
|
tcIndex = 0;
|
||||||
|
colIndex = 0;
|
||||||
|
s_texmtxwrite = s_texmtxread = 0;
|
||||||
for (int i = 0; i < m_numPipelineStages; i++)
|
for (int i = 0; i < m_numPipelineStages; i++)
|
||||||
m_PipelineStages[i]();
|
m_PipelineStages[i]();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PRIM_LOG("\n");
|
PRIM_LOG("\n");
|
||||||
v++;
|
|
||||||
}
|
}
|
||||||
|
v += remainingVerts;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startv < count)
|
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].Format = vat.g2.Tex7CoordFormat;
|
||||||
m_VtxAttr.texCoord[7].Frac = vat.g2.Tex7Frac;
|
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));
|
||||||
|
}
|
|
@ -18,6 +18,8 @@
|
||||||
#ifndef _VERTEXLOADER_H
|
#ifndef _VERTEXLOADER_H
|
||||||
#define _VERTEXLOADER_H
|
#define _VERTEXLOADER_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "CPMemory.h"
|
#include "CPMemory.h"
|
||||||
#include "DataReader.h"
|
#include "DataReader.h"
|
||||||
|
|
||||||
|
@ -59,6 +61,9 @@ public:
|
||||||
int GetVertexSize() const {return m_VertexSize;}
|
int GetVertexSize() const {return m_VertexSize;}
|
||||||
void RunVertices(int vtx_attr_group, int primitive, int count);
|
void RunVertices(int vtx_attr_group, int primitive, int count);
|
||||||
|
|
||||||
|
// For debugging / profiling
|
||||||
|
void AppendToString(std::string *dest);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -83,6 +88,8 @@ private:
|
||||||
|
|
||||||
u8 *m_compiledCode;
|
u8 *m_compiledCode;
|
||||||
|
|
||||||
|
int m_numLoadedVertices;
|
||||||
|
|
||||||
void SetupColor(int num, int _iMode, int _iFormat, int _iElements);
|
void SetupColor(int num, int _iMode, int _iFormat, int _iElements);
|
||||||
void SetupTexCoord(int num, int _iMode, int _iFormat, int _iElements, int _iFrac);
|
void SetupTexCoord(int num, int _iMode, int _iFormat, int _iElements, int _iFrac);
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,14 @@ void Shutdown()
|
||||||
g_VertexLoaderMap.clear();
|
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()
|
void MarkAllDirty()
|
||||||
{
|
{
|
||||||
s_attr_dirty = 0xff;
|
s_attr_dirty = 0xff;
|
||||||
|
|
|
@ -30,6 +30,9 @@ namespace VertexLoaderManager
|
||||||
int GetVertexSize(int vtx_attr_group);
|
int GetVertexSize(int vtx_attr_group);
|
||||||
void RunVertices(int vtx_attr_group, int primitive, int count);
|
void RunVertices(int vtx_attr_group, int primitive, int count);
|
||||||
|
|
||||||
|
// For debugging
|
||||||
|
void AppendListToString(std::string *dest);
|
||||||
|
|
||||||
// TODO - don't expose these like this.
|
// TODO - don't expose these like this.
|
||||||
// static u8* s_pCurBufferPointer;
|
// static u8* s_pCurBufferPointer;
|
||||||
};
|
};
|
||||||
|
|
|
@ -85,19 +85,6 @@ void ResetBuffer()
|
||||||
s_vStoredPrimitives.resize(0);
|
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()
|
int GetRemainingSize()
|
||||||
{
|
{
|
||||||
return MAX_BUFFER_SIZE - (int)(s_pCurBufferPointer - s_pBaseBufferPointer);
|
return MAX_BUFFER_SIZE - (int)(s_pCurBufferPointer - s_pBaseBufferPointer);
|
||||||
|
@ -108,12 +95,21 @@ void AddVertices(int primitive, int numvertices)
|
||||||
_assert_( numvertices > 0 );
|
_assert_( numvertices > 0 );
|
||||||
|
|
||||||
ADDSTAT(stats.thisFrame.numPrims, numvertices);
|
ADDSTAT(stats.thisFrame.numPrims, numvertices);
|
||||||
/*
|
if (s_vStoredPrimitives.size() && s_vStoredPrimitives[s_vStoredPrimitives.size() - 1].first == c_primitiveType[primitive]) {
|
||||||
if (s_vStoredPrimitives.size() && s_vStoredPrimitives[s_vStoredPrimitives.size() - 1].first == primitive) {
|
// We can join primitives for free here. Not likely to help much, though, but whatever...
|
||||||
// Actually, just count potential primitive joins.
|
if (c_primitiveType[primitive] == GL_TRIANGLES ||
|
||||||
// Doesn't seem worth it in Metroid Prime games.
|
c_primitiveType[primitive] == GL_LINES ||
|
||||||
INCSTAT(stats.thisFrame.numPrimitiveJoins);
|
c_primitiveType[primitive] == GL_POINTS ||
|
||||||
}*/
|
c_primitiveType[primitive] == GL_QUADS) {
|
||||||
|
INCSTAT(stats.thisFrame.numPrimitiveJoins);
|
||||||
|
// Easy join
|
||||||
|
std::pair<int, int> &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<int, int>(c_primitiveType[primitive], numvertices));
|
s_vStoredPrimitives.push_back(std::pair<int, int>(c_primitiveType[primitive], numvertices));
|
||||||
|
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
|
|
|
@ -30,7 +30,6 @@ bool Init();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
void ResetBuffer();
|
void ResetBuffer();
|
||||||
void ResetComponents();
|
|
||||||
|
|
||||||
void AddVertices(int primitive, int numvertices);
|
void AddVertices(int primitive, int numvertices);
|
||||||
void Flush(); // flushes the current buffer
|
void Flush(); // flushes the current buffer
|
||||||
|
|
Loading…
Reference in New Issue