Move pipeline back into VertexLoader. Started work on VertexLoaderManager, which will cache VertexLoaders. (yep, the design plan changed a little bit).

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@956 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard 2008-10-25 12:35:55 +00:00
parent 3a3eebc313
commit bc79d22f5e
12 changed files with 219 additions and 116 deletions

View File

@ -58,6 +58,13 @@ enum
FORMAT_32B_8888 = 5, FORMAT_32B_8888 = 5,
}; };
enum
{
VAT_0_FRACBITS = 0x3e0001f0,
VAT_1_FRACBITS = 0x07c3e1f0,
VAT_2_FRACBITS = 0xf87c3e1f,
};
#pragma pack(4) #pragma pack(4)
union TVtxDesc union TVtxDesc
{ {

View File

@ -70,26 +70,20 @@ typedef void (LOADERDECL *TPipelineFunction)(const void *);
// all the data loading code must always be made compatible. // all the data loading code must always be made compatible.
class NativeVertexFormat class NativeVertexFormat
{ {
u8* m_compiledCode;
public: public:
NativeVertexFormat(); NativeVertexFormat();
~NativeVertexFormat(); ~NativeVertexFormat();
void Initialize(const TVtxDesc &vtx_desc, const TVtxAttr &vtx_attr); void Initialize(const TVtxDesc &vtx_desc, const TVtxAttr &vtx_attr);
void RunPipelineOnce(const TVtxAttr &vtx_attr) const; void SetupVertexPointers() const;
void 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.
((void (*)())(void*)m_compiledCode)();
}
// TODO: move these in under private: // TODO: move these in under private:
int m_VBVertexStride; // PC-side vertex stride int m_VBVertexStride; // PC-side vertex stride
int m_VBStridePad; int m_VBStridePad;
u32 m_components; // VB_HAS_X. Bitmask telling what vertex components are present. u32 m_components; // VB_HAS_X. Bitmask telling what vertex components are present.
TPipelineFunction m_PipelineStages[32];
int m_numPipelineStages;
u8* m_compiledCode;
}; };
#endif // _NATIVEVERTEXFORMAT_H #endif // _NATIVEVERTEXFORMAT_H

View File

@ -764,6 +764,14 @@
RelativePath=".\Src\VertexLoader_TextCoord.h" RelativePath=".\Src\VertexLoader_TextCoord.h"
> >
</File> </File>
<File
RelativePath=".\Src\VertexLoaderManager.cpp"
>
</File>
<File
RelativePath=".\Src\VertexLoaderManager.h"
>
</File>
<File <File
RelativePath=".\Src\VertexManager.cpp" RelativePath=".\Src\VertexManager.cpp"
> >

View File

@ -37,10 +37,6 @@
// Here's some global state. We only use this to keep track of what we've sent to the OpenGL state // Here's some global state. We only use this to keep track of what we've sent to the OpenGL state
// machine. // machine.
DECLARE_IMPORT(glNormalPointer); DECLARE_IMPORT(glNormalPointer);
DECLARE_IMPORT(glVertexPointer); DECLARE_IMPORT(glVertexPointer);
DECLARE_IMPORT(glColorPointer); DECLARE_IMPORT(glColorPointer);
@ -49,7 +45,6 @@ DECLARE_IMPORT(glTexCoordPointer);
NativeVertexFormat::NativeVertexFormat() NativeVertexFormat::NativeVertexFormat()
{ {
m_compiledCode = (u8 *)AllocateExecutableMemory(COMPILED_CODE_SIZE, false); m_compiledCode = (u8 *)AllocateExecutableMemory(COMPILED_CODE_SIZE, false);
m_numPipelineStages = 0;
if (m_compiledCode) { if (m_compiledCode) {
memset(m_compiledCode, 0, COMPILED_CODE_SIZE); memset(m_compiledCode, 0, COMPILED_CODE_SIZE);
} }
@ -61,6 +56,12 @@ NativeVertexFormat::~NativeVertexFormat()
m_compiledCode = 0; 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)();
}
void NativeVertexFormat::Initialize(const TVtxDesc &vtx_desc, const TVtxAttr &vtx_attr) void NativeVertexFormat::Initialize(const TVtxDesc &vtx_desc, const TVtxAttr &vtx_attr)
{ {
using namespace Gen; using namespace Gen;
@ -178,7 +179,7 @@ void NativeVertexFormat::Initialize(const TVtxDesc &vtx_desc, const TVtxAttr &vt
offset += 1; offset += 1;
} }
_assert_(offset+m_VBStridePad == m_VBVertexStride); _assert_(offset + m_VBStridePad == m_VBVertexStride);
Util::EmitEpilogue(6); Util::EmitEpilogue(6);
if (Gen::GetCodePtr() - (u8*)m_compiledCode > COMPILED_CODE_SIZE) if (Gen::GetCodePtr() - (u8*)m_compiledCode > COMPILED_CODE_SIZE)
@ -188,9 +189,3 @@ void NativeVertexFormat::Initialize(const TVtxDesc &vtx_desc, const TVtxAttr &vt
SetCodePtr(old_code_ptr); SetCodePtr(old_code_ptr);
} }
void NativeVertexFormat::RunPipelineOnce(const TVtxAttr &vtx_attr) const
{
for (int i = 0; i < m_numPipelineStages; i++)
m_PipelineStages[i](&vtx_attr);
}

View File

@ -29,6 +29,7 @@
#include "OpcodeDecoding.h" #include "OpcodeDecoding.h"
#include "VertexLoader.h" #include "VertexLoader.h"
#include "VertexLoaderManager.h"
#include "VertexManager.h" #include "VertexManager.h"
#include "VertexShaderManager.h" #include "VertexShaderManager.h"
@ -55,7 +56,7 @@ static void ExecuteDisplayList(u32 address, u32 size)
// temporarily swap dl and non-dl (small "hack" for the stats) // temporarily swap dl and non-dl (small "hack" for the stats)
Statistics::SwapDL(); Statistics::SwapDL();
while((u32)(g_pVideoData - startAddress) < size) while ((u32)(g_pVideoData - startAddress) < size)
{ {
Decode(); Decode();
} }
@ -78,7 +79,7 @@ bool FifoCommandRunnable()
u8 Cmd = DataPeek8(0); u8 Cmd = DataPeek8(0);
u32 iCommandSize = 0; u32 iCommandSize = 0;
switch(Cmd) switch (Cmd)
{ {
case GX_NOP: case GX_NOP:
// Hm, this means that we scan over nop streams pretty slowly... // Hm, this means that we scan over nop streams pretty slowly...
@ -210,7 +211,7 @@ static void Decode()
{ {
u32 SubCmd = DataReadU8(); u32 SubCmd = DataReadU8();
u32 Value = DataReadU32(); u32 Value = DataReadU32();
VertexManager::LoadCPReg(SubCmd,Value); LoadCPReg(SubCmd, Value);
INCSTAT(stats.thisFrame.numCPLoads); INCSTAT(stats.thisFrame.numCPLoads);
} }
break; break;
@ -218,13 +219,13 @@ static void Decode()
case GX_LOAD_XF_REG: case GX_LOAD_XF_REG:
{ {
u32 Cmd2 = DataReadU32(); u32 Cmd2 = DataReadU32();
int dwTransferSize = ((Cmd2 >> 16) & 15) + 1;
int dwTransferSize = ((Cmd2>>16)&15) + 1;
u32 dwAddress = Cmd2 & 0xFFFF; u32 dwAddress = Cmd2 & 0xFFFF;
// TODO - speed this up. pshufb?
static u32 pData[16]; static u32 pData[16];
for (int i=0; i<dwTransferSize; i++) for (int i = 0; i < dwTransferSize; i++)
pData[i] = DataReadU32(); pData[i] = DataReadU32();
VertexShaderMngr::LoadXFReg(dwTransferSize,dwAddress,pData); VertexShaderMngr::LoadXFReg(dwTransferSize, dwAddress, pData);
INCSTAT(stats.thisFrame.numXFLoads); INCSTAT(stats.thisFrame.numXFLoads);
} }
break; break;
@ -272,9 +273,10 @@ static void Decode()
{ {
// load vertices (use computed vertex size from FifoCommandRunnable above) // load vertices (use computed vertex size from FifoCommandRunnable above)
u16 numVertices = DataReadU16(); u16 numVertices = DataReadU16();
if (numVertices > 0) { VertexLoaderManager::RunVertices(
g_VertexLoaders[Cmd & GX_VAT_MASK].RunVertices((Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, numVertices); Cmd & GX_VAT_MASK, // Vertex loader index (0 - 7)
} (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT,
numVertices);
} }
else else
{ {

View File

@ -23,6 +23,7 @@ files = [
'VertexManager.cpp', 'VertexManager.cpp',
'VertexLoader.cpp', 'VertexLoader.cpp',
'VertexLoader_Normal.cpp', 'VertexLoader_Normal.cpp',
'VertexLoaderManager.cpp',
'VertexShaderManager.cpp', 'VertexShaderManager.cpp',
'XFB.cpp', 'XFB.cpp',
'GUI/ConfigDlg.cpp', 'GUI/ConfigDlg.cpp',

View File

@ -29,6 +29,7 @@
#include "Render.h" #include "Render.h"
#include "VertexShader.h" #include "VertexShader.h"
#include "VertexManager.h" #include "VertexManager.h"
#include "VertexLoaderManager.h"
#include "VertexLoader.h" #include "VertexLoader.h"
#include "BPStructs.h" #include "BPStructs.h"
#include "DataReader.h" #include "DataReader.h"
@ -115,6 +116,7 @@ VertexLoader::VertexLoader()
{ {
m_VertexSize = 0; m_VertexSize = 0;
m_AttrDirty = AD_DIRTY; m_AttrDirty = AD_DIRTY;
m_numPipelineStages = 0;
VertexLoader_Normal::Init(); VertexLoader_Normal::Init();
} }
@ -126,15 +128,15 @@ int VertexLoader::ComputeVertexSize()
{ {
if (m_AttrDirty == AD_CLEAN) { if (m_AttrDirty == AD_CLEAN) {
// Compare the 33 desc bits. // Compare the 33 desc bits.
if (m_VtxDesc.Hex0 == VertexManager::GetVtxDesc().Hex0 && if (m_VtxDesc.Hex0 == GetVtxDesc().Hex0 &&
(m_VtxDesc.Hex1 & 1) == (VertexManager::GetVtxDesc().Hex1 & 1)) (m_VtxDesc.Hex1 & 1) == (GetVtxDesc().Hex1 & 1))
return m_VertexSize; return m_VertexSize;
m_VtxDesc.Hex = VertexManager::GetVtxDesc().Hex; m_VtxDesc.Hex = GetVtxDesc().Hex;
} }
else { else {
// Attributes are dirty so we have to recompute everything anyway. // Attributes are dirty so we have to recompute everything anyway.
m_VtxDesc.Hex = VertexManager::GetVtxDesc().Hex; m_VtxDesc.Hex = GetVtxDesc().Hex;
} }
m_AttrDirty = AD_DIRTY; m_AttrDirty = AD_DIRTY;
@ -248,7 +250,8 @@ void VertexLoader::PrepareForVertexFormat()
if (m_AttrDirty == AD_CLEAN) if (m_AttrDirty == AD_CLEAN)
{ {
// Check if local cached desc (in this VL) matches global desc // Check if local cached desc (in this VL) matches global desc
if (m_VtxDesc.Hex0 == VertexManager::GetVtxDesc().Hex0 && (m_VtxDesc.Hex1 & 1)==(VertexManager::GetVtxDesc().Hex1 & 1)) if (m_VtxDesc.Hex0 == GetVtxDesc().Hex0 &&
(m_VtxDesc.Hex1 & 1) == (GetVtxDesc().Hex1 & 1))
{ {
return; // same return; // same
} }
@ -258,19 +261,21 @@ void VertexLoader::PrepareForVertexFormat()
m_AttrDirty = AD_CLEAN; m_AttrDirty = AD_CLEAN;
} }
m_VtxDesc.Hex = VertexManager::GetVtxDesc().Hex; m_VtxDesc.Hex = GetVtxDesc().Hex;
// Reset pipeline // 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_VBStridePad = 0; m_NativeFmt.m_VBStridePad = 0;
m_NativeFmt.m_VBVertexStride = 0; m_NativeFmt.m_VBVertexStride = 0;
m_NativeFmt.m_numPipelineStages = 0;
m_NativeFmt.m_components = 0; m_NativeFmt.m_components = 0;
// m_VBVertexStride for texmtx and posmtx is computed later when writing. // m_VBVertexStride for texmtx and posmtx is computed later when writing.
// Position Matrix Index // Position Matrix Index
if (m_VtxDesc.PosMatIdx) { if (m_VtxDesc.PosMatIdx) {
m_NativeFmt.m_PipelineStages[m_NativeFmt.m_numPipelineStages++] = PosMtx_ReadDirect_UByte; m_PipelineStages[m_numPipelineStages++] = PosMtx_ReadDirect_UByte;
m_NativeFmt.m_components |= VB_HAS_POSMTXIDX; m_NativeFmt.m_components |= VB_HAS_POSMTXIDX;
} }
@ -508,7 +513,7 @@ void VertexLoader::SetupTexCoord(int num, int mode, int format, int elements, in
void VertexLoader::WriteCall(TPipelineFunction func) void VertexLoader::WriteCall(TPipelineFunction func)
{ {
m_NativeFmt.m_PipelineStages[m_NativeFmt.m_numPipelineStages++] = func; m_PipelineStages[m_numPipelineStages++] = func;
} }
void VertexLoader::RunVertices(int primitive, int count) void VertexLoader::RunVertices(int primitive, int count)
@ -626,7 +631,7 @@ void VertexLoader::RunVertices(int primitive, int count)
colIndex = 0; colIndex = 0;
s_texmtxwrite = s_texmtxread = 0; s_texmtxwrite = s_texmtxread = 0;
m_NativeFmt.RunPipelineOnce(m_VtxAttr); RunPipelineOnce();
VertexManager::s_pCurBufferPointer += m_NativeFmt.m_VBStridePad; VertexManager::s_pCurBufferPointer += m_NativeFmt.m_VBStridePad;
PRIM_LOG("\n"); PRIM_LOG("\n");
@ -635,3 +640,9 @@ void VertexLoader::RunVertices(int primitive, int count)
if (startv < count) if (startv < count)
VertexManager::AddVertices(primitive, count - startv + extraverts); VertexManager::AddVertices(primitive, count - startv + extraverts);
} }
void VertexLoader::RunPipelineOnce() const
{
for (int i = 0; i < m_numPipelineStages; i++)
m_PipelineStages[i](&m_VtxAttr);
}

View File

@ -59,8 +59,13 @@ private:
// PC vertex format, + converter ====== // PC vertex format, + converter ======
NativeVertexFormat m_NativeFmt; NativeVertexFormat m_NativeFmt;
// Pipeline. To be JIT compiled in the future.
TPipelineFunction m_PipelineStages[32];
int m_numPipelineStages;
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);
void RunPipelineOnce() const;
public: public:
// constructor // constructor
@ -79,7 +84,8 @@ public:
void SetVAT_group0(u32 _group0) void SetVAT_group0(u32 _group0)
{ {
if ((m_group0.Hex & ~0x3e0001f0) != (_group0 & ~0x3e0001f0)) { // ignore frac bits - we don't need to recompute if all that's changed was the frac bits.
if ((m_group0.Hex & ~VAT_0_FRACBITS) != (_group0 & ~VAT_0_FRACBITS)) {
m_AttrDirty = AD_VAT_DIRTY; m_AttrDirty = AD_VAT_DIRTY;
} }
m_group0.Hex = _group0; m_group0.Hex = _group0;
@ -102,7 +108,7 @@ public:
void SetVAT_group1(u32 _group1) void SetVAT_group1(u32 _group1)
{ {
if ((m_group1.Hex & ~0x7c3e1f0) != (_group1 & ~0x7c3e1f0)) { if ((m_group1.Hex & ~VAT_1_FRACBITS) != (_group1 & ~VAT_1_FRACBITS)) {
m_AttrDirty = AD_VAT_DIRTY; m_AttrDirty = AD_VAT_DIRTY;
} }
m_group1.Hex = _group1; m_group1.Hex = _group1;
@ -122,7 +128,7 @@ public:
void SetVAT_group2(u32 _group2) void SetVAT_group2(u32 _group2)
{ {
if ((m_group2.Hex & ~0xf87c3e1f) != (_group2 & ~0xf87c3e1f)) { if ((m_group2.Hex & ~VAT_2_FRACBITS) != (_group2 & ~VAT_2_FRACBITS)) {
m_AttrDirty = AD_VAT_DIRTY; m_AttrDirty = AD_VAT_DIRTY;
} }
m_group2.Hex = _group2; m_group2.Hex = _group2;

View File

@ -0,0 +1,79 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "VertexShaderManager.h"
#include "VertexLoader.h"
#include "VertexLoaderManager.h"
// The one and only vtx_desc
TVtxDesc g_vtx_desc;
// There are 8 vtx_attr structures. They will soon live here.
const TVtxDesc &GetVtxDesc()
{
return g_vtx_desc;
}
namespace VertexLoaderManager {
void Init() {
g_vtx_desc.Hex = 0;
}
void Shutdown() {
}
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);
}
} // namespace
void LoadCPReg(u32 sub_cmd, u32 value)
{
switch (sub_cmd & 0xF0)
{
case 0x30:
VertexShaderMngr::SetTexMatrixChangedA(value);
break;
case 0x40:
VertexShaderMngr::SetTexMatrixChangedB(value);
break;
case 0x50:
g_vtx_desc.Hex &= ~0x1FFFF; // keep the Upper bits
g_vtx_desc.Hex |= value;
break;
case 0x60:
g_vtx_desc.Hex &= 0x1FFFF; // keep the lower 17Bits
g_vtx_desc.Hex |= (u64)value << 17;
break;
case 0x70: g_VertexLoaders[sub_cmd & 7].SetVAT_group0(value); _assert_((sub_cmd & 0x0F) < 8); break;
case 0x80: g_VertexLoaders[sub_cmd & 7].SetVAT_group1(value); _assert_((sub_cmd & 0x0F) < 8); break;
case 0x90: g_VertexLoaders[sub_cmd & 7].SetVAT_group2(value); _assert_((sub_cmd & 0x0F) < 8); break;
case 0xA0: arraybases[sub_cmd & 0xF] = value & 0xFFFFFFFF; break;
case 0xB0: arraystrides[sub_cmd & 0xF] = value & 0xFF; break;
}
}

View File

@ -0,0 +1,39 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _VERTEXLOADERMANAGER_H
#define _VERTEXLOADERMANAGER_H
#include "Common.h"
namespace VertexLoaderManager
{
void Init();
void Shutdown();
void RunVertices(int vtx_attr_group, int primitive, int count);
// TODO - don't expose these like this.
static u8* s_pCurBufferPointer;
};
const TVtxDesc &GetVtxDesc();
// Might move this into its own file later.
void LoadCPReg(u32 SubCmd, u32 Value);
#endif // _VERTEXLOADERMANAGER_H

View File

@ -19,14 +19,21 @@
#define MAX_BUFFER_SIZE 0x4000 #define MAX_BUFFER_SIZE 0x4000
// internal state for loading vertices
extern NativeVertexFormat *g_nativeVertexFmt;
namespace VertexManager
{
static GLuint s_vboBuffers[0x40] = {0}; static GLuint s_vboBuffers[0x40] = {0};
static int s_nCurVBOIndex = 0; // current free buffer static int s_nCurVBOIndex = 0; // current free buffer
static u8 *s_pBaseBufferPointer = NULL; static u8 *s_pBaseBufferPointer = NULL;
static std::vector< std::pair<int, int> > s_vStoredPrimitives; // every element, mode and count to be passed to glDrawArrays static std::vector< std::pair<int, int> > s_vStoredPrimitives; // every element, mode and count to be passed to glDrawArrays
static u32 s_prevcomponents; // previous state set static u32 s_prevcomponents; // previous state set
u8* VertexManager::s_pCurBufferPointer = NULL; u8* s_pCurBufferPointer = NULL;
TVtxDesc VertexManager::s_GlobalVtxDesc;
TVtxDesc s_GlobalVtxDesc;
static const GLenum c_primitiveType[8] = static const GLenum c_primitiveType[8] =
{ {
@ -40,14 +47,10 @@ static const GLenum c_primitiveType[8] =
GL_POINTS GL_POINTS
}; };
// internal state for loading vertices bool Init()
extern NativeVertexFormat *g_nativeVertexFmt;
bool VertexManager::Init()
{ {
Destroy(); Destroy();
s_GlobalVtxDesc.Hex = 0;
s_prevcomponents = 0; s_prevcomponents = 0;
s_pBaseBufferPointer = (u8*)AllocateMemoryPages(MAX_BUFFER_SIZE); s_pBaseBufferPointer = (u8*)AllocateMemoryPages(MAX_BUFFER_SIZE);
s_pCurBufferPointer = s_pBaseBufferPointer; s_pCurBufferPointer = s_pBaseBufferPointer;
@ -67,7 +70,7 @@ bool VertexManager::Init()
return true; return true;
} }
void VertexManager::Destroy() void Destroy()
{ {
FreeMemoryPages(s_pBaseBufferPointer, MAX_BUFFER_SIZE); s_pBaseBufferPointer = s_pCurBufferPointer = NULL; FreeMemoryPages(s_pBaseBufferPointer, MAX_BUFFER_SIZE); s_pBaseBufferPointer = s_pCurBufferPointer = NULL;
glDeleteBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers); glDeleteBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers);
@ -78,14 +81,14 @@ void VertexManager::Destroy()
ResetBuffer(); ResetBuffer();
} }
void VertexManager::ResetBuffer() void ResetBuffer()
{ {
s_nCurVBOIndex = (s_nCurVBOIndex + 1) % ARRAYSIZE(s_vboBuffers); s_nCurVBOIndex = (s_nCurVBOIndex + 1) % ARRAYSIZE(s_vboBuffers);
s_pCurBufferPointer = s_pBaseBufferPointer; s_pCurBufferPointer = s_pBaseBufferPointer;
s_vStoredPrimitives.resize(0); s_vStoredPrimitives.resize(0);
} }
void VertexManager::ResetComponents() void ResetComponents()
{ {
s_prevcomponents = 0; s_prevcomponents = 0;
glDisableVertexAttribArray(SHADER_POSMTX_ATTRIB); glDisableVertexAttribArray(SHADER_POSMTX_ATTRIB);
@ -98,12 +101,12 @@ void VertexManager::ResetComponents()
glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY);
} }
int VertexManager::GetRemainingSize() int GetRemainingSize()
{ {
return MAX_BUFFER_SIZE - (int)(s_pCurBufferPointer - s_pBaseBufferPointer); return MAX_BUFFER_SIZE - (int)(s_pCurBufferPointer - s_pBaseBufferPointer);
} }
void VertexManager::AddVertices(int primitive, int numvertices) void AddVertices(int primitive, int numvertices)
{ {
_assert_( numvertices > 0 ); _assert_( numvertices > 0 );
@ -116,7 +119,7 @@ void VertexManager::AddVertices(int primitive, int numvertices)
#endif #endif
} }
void VertexManager::Flush() void Flush()
{ {
if (s_vStoredPrimitives.size() == 0) if (s_vStoredPrimitives.size() == 0)
return; return;
@ -298,37 +301,8 @@ void VertexManager::Flush()
ResetBuffer(); ResetBuffer();
} }
void VertexManager::LoadCPReg(u32 sub_cmd, u32 value)
{
switch (sub_cmd & 0xF0)
{
case 0x30:
VertexShaderMngr::SetTexMatrixChangedA(value);
break;
case 0x40:
VertexShaderMngr::SetTexMatrixChangedB(value);
break;
case 0x50:
s_GlobalVtxDesc.Hex &= ~0x1FFFF; // keep the Upper bits
s_GlobalVtxDesc.Hex |= value;
break;
case 0x60:
s_GlobalVtxDesc.Hex &= 0x1FFFF; // keep the lower 17Bits
s_GlobalVtxDesc.Hex |= (u64)value << 17;
break;
case 0x70: g_VertexLoaders[sub_cmd & 7].SetVAT_group0(value); _assert_((sub_cmd & 0x0F) < 8); break;
case 0x80: g_VertexLoaders[sub_cmd & 7].SetVAT_group1(value); _assert_((sub_cmd & 0x0F) < 8); break;
case 0x90: g_VertexLoaders[sub_cmd & 7].SetVAT_group2(value); _assert_((sub_cmd & 0x0F) < 8); break;
case 0xA0: arraybases[sub_cmd & 0xF] = value & 0xFFFFFFFF; break;
case 0xB0: arraystrides[sub_cmd & 0xF] = value & 0xFF; break;
}
}
// This should move into NativeVertexFormat // This should move into NativeVertexFormat
void VertexManager::EnableComponents(u32 components) void EnableComponents(u32 components)
{ {
if (s_prevcomponents != components) { if (s_prevcomponents != components) {
if (s_vStoredPrimitives.size() != 0) if (s_vStoredPrimitives.size() != 0)
@ -384,3 +358,5 @@ void VertexManager::EnableComponents(u32 components)
s_prevcomponents = components; s_prevcomponents = components;
} }
} }
} // namespace

View File

@ -21,40 +21,25 @@
#include "CPMemory.h" #include "CPMemory.h"
// TODO - clarify the role of this class. // Handles the OpenGL details of drawing lots of vertices quickly.
// Other functionality is moving out.
// Methods to manage and cache the global state of vertex streams and flushing streams namespace VertexManager
// Also handles processing the CP registers
class VertexManager
{ {
static TVtxDesc s_GlobalVtxDesc; bool Init();
void Destroy();
public: void ResetBuffer();
enum Collection void ResetComponents();
{
C_NOTHING=0,
C_TRIANGLES=1,
C_LINES=2,
C_POINTS=3
};
static bool Init(); void AddVertices(int primitive, int numvertices);
static void Destroy(); void Flush(); // flushes the current buffer
static void ResetBuffer(); int GetRemainingSize(); // remaining space in the current buffer.
static void ResetComponents();
static void AddVertices(int primitive, int numvertices); void EnableComponents(u32 components); // very implementation specific - D3D9 won't need this one.
static void Flush(); // flushes the current buffer
static int GetRemainingSize(); // TODO: move, rename.
static TVtxDesc &GetVtxDesc() {return s_GlobalVtxDesc; } extern u8* s_pCurBufferPointer;
static void LoadCPReg(u32 SubCmd, u32 Value);
static void EnableComponents(u32 components);
// TODO - don't expose these like this.
static u8* s_pCurBufferPointer;
}; };
#endif // _VERTEXMANAGER_H #endif // _VERTEXMANAGER_H