Cachable vertex loaders. Not a very big speedup in itself, but makes it easier to speed up vertex loading in the future.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@960 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
681a40dd36
commit
f77624147d
|
@ -39,6 +39,8 @@ struct Statistics
|
|||
|
||||
int numJoins;
|
||||
|
||||
int numVertexLoaders;
|
||||
|
||||
struct ThisFrame
|
||||
{
|
||||
int numBPLoads;
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
#include "TextureDecoder.h"
|
||||
#include "Fifo.h"
|
||||
|
||||
static void DoState(PointerWrap &p) {
|
||||
|
||||
static void DoState(PointerWrap &p)
|
||||
{
|
||||
// BP Memory
|
||||
p.Do(bpmem);
|
||||
// CP Memory
|
||||
|
|
|
@ -171,7 +171,7 @@ void PixelShaderMngr::Cleanup()
|
|||
PSCache::iterator iter = pshaders.begin();
|
||||
while (iter != pshaders.end()) {
|
||||
PSCacheEntry &entry = iter->second;
|
||||
if (entry.frameCount < frameCount - 200) {
|
||||
if (entry.frameCount < frameCount - 400) {
|
||||
entry.Destroy();
|
||||
#ifdef _WIN32
|
||||
iter = pshaders.erase(iter);
|
||||
|
@ -242,10 +242,9 @@ void PixelShaderMngr::SetConstants()
|
|||
{
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (s_nColorsChanged[i]) {
|
||||
|
||||
int baseind = i?C_KCOLORS:C_COLORS;
|
||||
int baseind = i ? C_KCOLORS : C_COLORS;
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
if (s_nColorsChanged[i] & (1<<j)) {
|
||||
if (s_nColorsChanged[i] & (1 << j)) {
|
||||
SetPSConstant4fv(baseind+j, &lastRGBAfull[i][j][0]);
|
||||
}
|
||||
}
|
||||
|
@ -258,7 +257,7 @@ void PixelShaderMngr::SetConstants()
|
|||
if (bpmem.tevorders[i/2].getEnable(i&1)) {
|
||||
int texmap = bpmem.tevorders[i/2].getTexMap(i&1);
|
||||
maptocoord[texmap] = bpmem.tevorders[i/2].getTexCoord(i&1);
|
||||
newmask |= 1<<texmap;
|
||||
newmask |= 1 << texmap;
|
||||
SetTexDimsChanged(texmap);
|
||||
}
|
||||
}
|
||||
|
@ -266,7 +265,7 @@ void PixelShaderMngr::SetConstants()
|
|||
if (maptocoord_mask != newmask) {
|
||||
//u32 changes = maptocoord_mask ^ newmask;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (newmask&(1<<i)) {
|
||||
if (newmask & (1 << i)) {
|
||||
SetTexDimsChanged(i);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -773,6 +773,7 @@ void Renderer::SwapBuffers()
|
|||
p+=sprintf(p,"Num CP loads (DL): %i\n",stats.thisFrame.numCPLoadsInDL);
|
||||
p+=sprintf(p,"Num BP loads: %i\n",stats.thisFrame.numBPLoads);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,9 @@ int TextureMngr::nTex2DEnabled, TextureMngr::nTexRECTEnabled;
|
|||
|
||||
extern int frameCount;
|
||||
static u32 s_TempFramebuffer = 0;
|
||||
|
||||
#define TEMP_SIZE (1024*1024*4)
|
||||
#define TEXTURE_KILL_THRESHOLD 200
|
||||
|
||||
const GLint c_MinLinearFilter[8] = {
|
||||
GL_NEAREST,
|
||||
|
@ -119,7 +121,7 @@ void TextureMngr::Init()
|
|||
void TextureMngr::Invalidate()
|
||||
{
|
||||
TexCache::iterator iter = textures.begin();
|
||||
for (;iter!=textures.end();iter++)
|
||||
for (; iter!=textures.end(); iter++)
|
||||
iter->second.Destroy();
|
||||
textures.clear();
|
||||
TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter);
|
||||
|
@ -134,7 +136,7 @@ void TextureMngr::Shutdown()
|
|||
}
|
||||
mapDepthTargets.clear();
|
||||
|
||||
if( s_TempFramebuffer ) {
|
||||
if (s_TempFramebuffer) {
|
||||
glDeleteFramebuffersEXT(1, (GLuint *)&s_TempFramebuffer);
|
||||
s_TempFramebuffer = 0;
|
||||
}
|
||||
|
@ -147,7 +149,7 @@ void TextureMngr::Cleanup()
|
|||
{
|
||||
TexCache::iterator iter = textures.begin();
|
||||
while (iter != textures.end()) {
|
||||
if (frameCount > 20 + iter->second.frameCount) {
|
||||
if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second.frameCount) {
|
||||
if (!iter->second.isRenderTarget) {
|
||||
iter->second.Destroy();
|
||||
#ifdef _WIN32
|
||||
|
@ -215,10 +217,10 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
|
|||
if (iter != textures.end()) {
|
||||
TCacheEntry &entry = iter->second;
|
||||
|
||||
if(entry.isRenderTarget || (((u32 *)ptr)[entry.hashoffset] == entry.hash && palhash == entry.paletteHash)) { //stupid, improve
|
||||
if (entry.isRenderTarget || (((u32 *)ptr)[entry.hashoffset] == entry.hash && palhash == entry.paletteHash)) { //stupid, improve
|
||||
entry.frameCount = frameCount;
|
||||
//glEnable(entry.isNonPow2?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D);
|
||||
glBindTexture(entry.isNonPow2?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D, entry.texture);
|
||||
glBindTexture(entry.isNonPow2 ? GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D, entry.texture);
|
||||
if (entry.mode.hex != tm0.hex)
|
||||
entry.SetTextureParameters(tm0);
|
||||
return &entry;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,66 +23,72 @@
|
|||
|
||||
#include "NativeVertexFormat.h"
|
||||
|
||||
class VertexLoaderUID
|
||||
{
|
||||
u32 id[5];
|
||||
public:
|
||||
VertexLoaderUID() {}
|
||||
void InitFromCurrentState(int vtx_attr_group) {
|
||||
id[0] = g_VtxDesc.Hex & 0xFFFFFFFF;
|
||||
id[1] = g_VtxDesc.Hex >> 32;
|
||||
id[2] = g_VtxAttr[vtx_attr_group].g0.Hex & ~VAT_0_FRACBITS;
|
||||
id[3] = g_VtxAttr[vtx_attr_group].g1.Hex & ~VAT_1_FRACBITS;
|
||||
id[4] = g_VtxAttr[vtx_attr_group].g2.Hex & ~VAT_2_FRACBITS;
|
||||
}
|
||||
bool operator < (const VertexLoaderUID &other) const {
|
||||
if (id[0] < other.id[0])
|
||||
return true;
|
||||
else if (id[0] > other.id[0])
|
||||
return false;
|
||||
for (int i = 1; i < 5; ++i) {
|
||||
if (id[i] < other.id[i])
|
||||
return true;
|
||||
else if (id[i] > other.id[i])
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class VertexLoader
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
NRM_ZERO = 0,
|
||||
NRM_ONE = 1,
|
||||
NRM_THREE = 3
|
||||
};
|
||||
VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr);
|
||||
~VertexLoader();
|
||||
|
||||
int GetVertexSize() const {return m_VertexSize;}
|
||||
void RunVertices(int vtx_attr_group, int primitive, int count);
|
||||
|
||||
private:
|
||||
// The 3 possible values (0, 1, 2) should be documented here.
|
||||
enum {
|
||||
AD_CLEAN = 0,
|
||||
AD_DIRTY = 1,
|
||||
AD_VAT_DIRTY = 2,
|
||||
} m_AttrDirty;
|
||||
enum
|
||||
{
|
||||
NRM_ZERO = 0,
|
||||
NRM_ONE = 1,
|
||||
NRM_THREE = 3,
|
||||
};
|
||||
|
||||
int m_VertexSize; // number of bytes of a raw GC vertex
|
||||
int m_VertexSize; // number of bytes of a raw GC vertex
|
||||
|
||||
// Flipper vertex format
|
||||
// GC vertex format
|
||||
TVtxAttr m_VtxAttr; // VAT decoded into easy format
|
||||
TVtxDesc m_VtxDesc; // Not really used currently - or well it is, but could be easily avoided.
|
||||
|
||||
// Raw VAttr
|
||||
UVAT_group0 m_group0;
|
||||
UVAT_group1 m_group1;
|
||||
UVAT_group2 m_group2;
|
||||
TVtxAttr m_VtxAttr; // Decoded into easy format
|
||||
|
||||
// Vtx desc
|
||||
TVtxDesc m_VtxDesc;
|
||||
|
||||
// PC vertex format, + converter
|
||||
// PC vertex format
|
||||
NativeVertexFormat m_NativeFmt;
|
||||
|
||||
// Pipeline. To be JIT compiled in the future.
|
||||
TPipelineFunction m_PipelineStages[32];
|
||||
TPipelineFunction m_PipelineStages[32]; // TODO - figure out real max. it's lower.
|
||||
int m_numPipelineStages;
|
||||
|
||||
void SetupColor(int num, int _iMode, int _iFormat, int _iElements);
|
||||
void SetupTexCoord(int num, int _iMode, int _iFormat, int _iElements, int _iFrac);
|
||||
void RunPipelineOnce() const;
|
||||
void SetupColor(int num, int _iMode, int _iFormat, int _iElements);
|
||||
void SetupTexCoord(int num, int _iMode, int _iFormat, int _iElements, int _iFrac);
|
||||
|
||||
public:
|
||||
// constructor
|
||||
VertexLoader();
|
||||
~VertexLoader();
|
||||
void SetVAT(u32 _group0, u32 _group1, u32 _group2);
|
||||
|
||||
// run the pipeline
|
||||
void CompileVertexTranslator();
|
||||
void RunVertices(int primitive, int count);
|
||||
void WriteCall(TPipelineFunction);
|
||||
int ComputeVertexSize();
|
||||
void CompileVertexTranslator();
|
||||
|
||||
int GetGCVertexSize() const { _assert_( !m_AttrDirty ); return m_VertexSize; }
|
||||
int GetVBVertexStride() const { _assert_( !m_AttrDirty); return m_NativeFmt.m_VBVertexStride; }
|
||||
|
||||
int ComputeVertexSize();
|
||||
|
||||
void SetVAT_group0(u32 _group0);
|
||||
void SetVAT_group1(u32 _group1);
|
||||
void SetVAT_group2(u32 _group2);
|
||||
void WriteCall(TPipelineFunction);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,43 +15,78 @@
|
|||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "Statistics.h"
|
||||
|
||||
#include "VertexShaderManager.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "VertexLoaderManager.h"
|
||||
|
||||
static bool s_desc_dirty;
|
||||
static bool s_attr_dirty[8];
|
||||
static int s_attr_dirty; // bitfield
|
||||
|
||||
// TODO - change into array of pointers. Keep a map of all seen so far.
|
||||
static VertexLoader g_VertexLoaders[8];
|
||||
static VertexLoader *g_VertexLoaders[8];
|
||||
|
||||
namespace VertexLoaderManager
|
||||
{
|
||||
|
||||
typedef std::map<VertexLoaderUID, VertexLoader *> VertexLoaderMap;
|
||||
static VertexLoaderMap g_VertexLoaderMap;
|
||||
// TODO - change into array of pointers. Keep a map of all seen so far.
|
||||
|
||||
void Init()
|
||||
{
|
||||
s_desc_dirty = false;
|
||||
for (int i = 0; i < 8; i++)
|
||||
s_attr_dirty[i] = false;
|
||||
MarkAllDirty();
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
for (VertexLoaderMap::iterator iter = g_VertexLoaderMap.begin(); iter != g_VertexLoaderMap.end(); ++iter)
|
||||
{
|
||||
delete iter->second;
|
||||
}
|
||||
g_VertexLoaderMap.clear();
|
||||
}
|
||||
|
||||
void MarkAllDirty()
|
||||
{
|
||||
s_attr_dirty = 0xff;
|
||||
}
|
||||
|
||||
void RefreshLoader(int vtx_attr_group)
|
||||
{
|
||||
if (((s_attr_dirty >> vtx_attr_group) & 1) || !g_VertexLoaders[vtx_attr_group])
|
||||
{
|
||||
VertexLoaderUID uid;
|
||||
uid.InitFromCurrentState(vtx_attr_group);
|
||||
VertexLoaderMap::iterator iter = g_VertexLoaderMap.find(uid);
|
||||
if (iter != g_VertexLoaderMap.end())
|
||||
{
|
||||
g_VertexLoaders[vtx_attr_group] = iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
VertexLoader *loader = new VertexLoader(g_VtxDesc, g_VtxAttr[vtx_attr_group]);
|
||||
g_VertexLoaderMap[uid] = loader;
|
||||
g_VertexLoaders[vtx_attr_group] = loader;
|
||||
INCSTAT(stats.numVertexLoaders);
|
||||
}
|
||||
}
|
||||
s_attr_dirty &= ~(1 << vtx_attr_group);
|
||||
}
|
||||
|
||||
void RunVertices(int vtx_attr_group, int primitive, int count)
|
||||
{
|
||||
if (!count)
|
||||
return;
|
||||
// TODO - grab & load the correct vertex loader if anything is dirty.
|
||||
g_VertexLoaders[vtx_attr_group].RunVertices(primitive, count);
|
||||
RefreshLoader(vtx_attr_group);
|
||||
g_VertexLoaders[vtx_attr_group]->RunVertices(vtx_attr_group, primitive, count);
|
||||
}
|
||||
|
||||
int GetVertexSize(int vtx_attr_group)
|
||||
{
|
||||
// The vertex loaders will soon cache the vertex size.
|
||||
return g_VertexLoaders[vtx_attr_group].ComputeVertexSize();
|
||||
RefreshLoader(vtx_attr_group);
|
||||
return g_VertexLoaders[vtx_attr_group]->GetVertexSize();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -71,34 +106,31 @@ void LoadCPReg(u32 sub_cmd, u32 value)
|
|||
case 0x50:
|
||||
g_VtxDesc.Hex &= ~0x1FFFF; // keep the Upper bits
|
||||
g_VtxDesc.Hex |= value;
|
||||
s_desc_dirty = true;
|
||||
s_attr_dirty = 0xFF;
|
||||
break;
|
||||
|
||||
case 0x60:
|
||||
g_VtxDesc.Hex &= 0x1FFFF; // keep the lower 17Bits
|
||||
g_VtxDesc.Hex |= (u64)value << 17;
|
||||
s_desc_dirty = true;
|
||||
s_attr_dirty = 0xFF;
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
_assert_((sub_cmd & 0x0F) < 8);
|
||||
g_VtxAttr[sub_cmd & 7].g0.Hex = value;
|
||||
g_VertexLoaders[sub_cmd & 7].SetVAT_group0(value);
|
||||
s_attr_dirty[sub_cmd & 7] = true;
|
||||
s_attr_dirty |= 1 << (sub_cmd & 7);
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
_assert_((sub_cmd & 0x0F) < 8);
|
||||
g_VtxAttr[sub_cmd & 7].g1.Hex = value;
|
||||
g_VertexLoaders[sub_cmd & 7].SetVAT_group1(value);
|
||||
s_attr_dirty[sub_cmd & 7] = true;
|
||||
s_attr_dirty |= 1 << (sub_cmd & 7);
|
||||
break;
|
||||
|
||||
case 0x90:
|
||||
_assert_((sub_cmd & 0x0F) < 8);
|
||||
g_VtxAttr[sub_cmd & 7].g2.Hex = value;
|
||||
g_VertexLoaders[sub_cmd & 7].SetVAT_group2(value);
|
||||
s_attr_dirty[sub_cmd & 7] = true;
|
||||
s_attr_dirty |= 1 << (sub_cmd & 7);
|
||||
break;
|
||||
|
||||
// Pointers to vertex arrays in GC RAM
|
||||
|
|
|
@ -25,6 +25,8 @@ namespace VertexLoaderManager
|
|||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
void MarkAllDirty();
|
||||
|
||||
int GetVertexSize(int vtx_attr_group);
|
||||
void RunVertices(int vtx_attr_group, int primitive, int count);
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ VERTEXSHADER* VertexShaderMngr::GetShader(u32 components)
|
|||
VSCache::iterator iter = vshaders.find(uid);
|
||||
|
||||
if (iter != vshaders.end()) {
|
||||
iter->second.frameCount=frameCount;
|
||||
iter->second.frameCount = frameCount;
|
||||
VSCacheEntry &entry = iter->second;
|
||||
if (&entry.shader != pShaderLast) {
|
||||
pShaderLast = &entry.shader;
|
||||
|
|
|
@ -116,7 +116,7 @@ void DllConfig(HWND _hParent)
|
|||
resFound = (resos[b] == strBuffer);
|
||||
b++;
|
||||
}
|
||||
if(!resFound)
|
||||
if (!resFound)
|
||||
//and add the res
|
||||
{
|
||||
resos[i] = strBuffer;
|
||||
|
@ -196,8 +196,11 @@ void Video_Initialize(SVideoInitialize* _pVideoInitialize)
|
|||
|
||||
void Video_DoState(unsigned char **ptr, int mode) {
|
||||
|
||||
// Clear all caches
|
||||
// Clear all caches that touch RAM
|
||||
TextureMngr::Invalidate();
|
||||
// DisplayListManager::Invalidate();
|
||||
|
||||
VertexLoaderManager::MarkAllDirty();
|
||||
|
||||
PointerWrap p(ptr, mode);
|
||||
VideoCommon_DoState(p);
|
||||
|
|
Loading…
Reference in New Issue