Changes to allow LoadCPReg to work in a preprocess mode which affects a separate state.

This state will be used to calculate sizes for skipping over commands on
a separate thread.  An alternative to having these state variables would
be to have the preprocessor stash "state as we go" somewhere, but I
think that would be much uglier.

GetVertexSize now takes an extra argument to determine which state to
use, as does FifoCommandRunnable, which calls it.  While I'm modifying
FifoCommandRunnable, I also change it to take a buffer and size as
parameters rather than using g_pVideoData, which will also be necessary
later.  I also get rid of an unused overload.
This commit is contained in:
comex 2014-08-27 13:38:00 -04:00
parent f0131c2e09
commit e86ddacb18
5 changed files with 64 additions and 40 deletions

View File

@ -10,9 +10,12 @@
u8 *cached_arraybases[16];
CPState g_main_cp_state;
CPState g_preprocess_cp_state;
void DoCPState(PointerWrap& p)
{
// We don't save g_preprocess_cp_state separately because the GPU should be
// synced around state save/load.
p.DoArray(g_main_cp_state.array_bases, 16);
p.DoArray(g_main_cp_state.array_strides, 16);
p.Do(g_main_cp_state.matrix_index_a);
@ -20,4 +23,11 @@ void DoCPState(PointerWrap& p)
p.Do(g_main_cp_state.vtx_desc.Hex);
p.DoArray(g_main_cp_state.vtx_attr, 8);
p.DoMarker("CP Memory");
if (p.mode == PointerWrap::MODE_READ)
CopyPreprocessCPStateFromMain();
}
void CopyPreprocessCPStateFromMain()
{
memcpy(&g_preprocess_cp_state, &g_main_cp_state, sizeof(CPState));
}

View File

@ -238,6 +238,8 @@ struct VAT
UVAT_group2 g2;
};
class VertexLoader;
// STATE_TO_SAVE
struct CPState final
{
@ -248,18 +250,25 @@ struct CPState final
TVtxDesc vtx_desc;
// Most games only use the first VtxAttr and simply reconfigure it all the time as needed.
VAT vtx_attr[8];
// Attributes that actually belong to VertexLoaderManager:
int attr_dirty; // bitfield
VertexLoader* vertex_loaders[8];
};
class PointerWrap;
extern void DoCPState(PointerWrap& p);
extern void CopyPreprocessCPStateFromMain();
extern CPState g_main_cp_state;
extern CPState g_preprocess_cp_state;
extern u8 *cached_arraybases[16];
// Might move this into its own file later.
void LoadCPReg(u32 SubCmd, u32 Value);
void LoadCPReg(u32 SubCmd, u32 Value, bool is_preprocess = false);
// Fills memory with data from CP regs
void FillCPMemoryArray(u32 *memory);

View File

@ -21,12 +21,8 @@
#include "VideoCommon/VertexShaderManager.h"
#include "VideoCommon/VideoCommon.h"
static int s_attr_dirty; // bitfield
static NativeVertexFormat* s_current_vtx_fmt;
static VertexLoader* s_VertexLoaders[8];
namespace std
{
@ -53,10 +49,10 @@ static VertexLoaderMap s_vertex_loader_map;
void Init()
{
MarkAllDirty();
for (auto& map_entry : s_VertexLoaders)
{
for (auto& map_entry : g_main_cp_state.vertex_loaders)
map_entry = nullptr;
for (auto& map_entry : g_preprocess_cp_state.vertex_loaders)
map_entry = nullptr;
}
RecomputeCachedArraybases();
}
@ -104,15 +100,16 @@ void AppendListToString(std::string *dest)
void MarkAllDirty()
{
s_attr_dirty = 0xff;
g_main_cp_state.attr_dirty = 0xff;
g_preprocess_cp_state.attr_dirty = 0xff;
}
static VertexLoader* RefreshLoader(int vtx_attr_group)
static VertexLoader* RefreshLoader(int vtx_attr_group, CPState* state)
{
VertexLoader* loader;
if ((s_attr_dirty >> vtx_attr_group) & 1)
if ((state->attr_dirty >> vtx_attr_group) & 1)
{
VertexLoaderUID uid(g_main_cp_state.vtx_desc, g_main_cp_state.vtx_attr[vtx_attr_group]);
VertexLoaderUID uid(state->vtx_desc, state->vtx_attr[vtx_attr_group]);
std::lock_guard<std::mutex> lk(s_vertex_loader_map_lock);
VertexLoaderMap::iterator iter = s_vertex_loader_map.find(uid);
if (iter != s_vertex_loader_map.end())
@ -121,14 +118,14 @@ static VertexLoader* RefreshLoader(int vtx_attr_group)
}
else
{
loader = new VertexLoader(g_main_cp_state.vtx_desc, g_main_cp_state.vtx_attr[vtx_attr_group]);
loader = new VertexLoader(state->vtx_desc, state->vtx_attr[vtx_attr_group]);
s_vertex_loader_map[uid] = std::unique_ptr<VertexLoader>(loader);
INCSTAT(stats.numVertexLoaders);
}
s_VertexLoaders[vtx_attr_group] = loader;
s_attr_dirty &= ~(1 << vtx_attr_group);
state->vertex_loaders[vtx_attr_group] = loader;
state->attr_dirty &= ~(1 << vtx_attr_group);
} else {
loader = s_VertexLoaders[vtx_attr_group];
loader = state->vertex_loaders[vtx_attr_group];
}
return loader;
}
@ -137,7 +134,10 @@ bool RunVertices(int vtx_attr_group, int primitive, int count, size_t buf_size,
{
if (!count)
return true;
VertexLoader* loader = RefreshLoader(vtx_attr_group);
CPState* state = &g_main_cp_state;
VertexLoader* loader = RefreshLoader(vtx_attr_group, state);
size_t size = count * loader->GetVertexSize();
if (buf_size < size)
@ -152,7 +152,6 @@ bool RunVertices(int vtx_attr_group, int primitive, int count, size_t buf_size,
NativeVertexFormat* native = loader->GetNativeVertexFormat();
// If the native vertex format changed, force a flush.
if (native != s_current_vtx_fmt)
VertexManager::Flush();
@ -161,7 +160,7 @@ bool RunVertices(int vtx_attr_group, int primitive, int count, size_t buf_size,
VertexManager::PrepareForAdditionalData(primitive, count,
loader->GetNativeVertexDeclaration().stride);
loader->RunVertices(g_main_cp_state.vtx_attr[vtx_attr_group], primitive, count);
loader->RunVertices(state->vtx_attr[vtx_attr_group], primitive, count);
IndexGenerator::AddIndices(primitive, count);
@ -170,9 +169,9 @@ bool RunVertices(int vtx_attr_group, int primitive, int count, size_t buf_size,
return true;
}
int GetVertexSize(int vtx_attr_group)
int GetVertexSize(int vtx_attr_group, bool preprocess)
{
return RefreshLoader(vtx_attr_group)->GetVertexSize();
return RefreshLoader(vtx_attr_group, preprocess ? &g_preprocess_cp_state : &g_main_cp_state)->GetVertexSize();
}
NativeVertexFormat* GetCurrentVertexFormat()
@ -182,56 +181,61 @@ NativeVertexFormat* GetCurrentVertexFormat()
} // namespace
void LoadCPReg(u32 sub_cmd, u32 value)
void LoadCPReg(u32 sub_cmd, u32 value, bool is_preprocess)
{
bool update_global_state = !is_preprocess;
CPState* state = is_preprocess ? &g_preprocess_cp_state : &g_main_cp_state;
switch (sub_cmd & 0xF0)
{
case 0x30:
VertexShaderManager::SetTexMatrixChangedA(value);
if (update_global_state)
VertexShaderManager::SetTexMatrixChangedA(value);
break;
case 0x40:
VertexShaderManager::SetTexMatrixChangedB(value);
if (update_global_state)
VertexShaderManager::SetTexMatrixChangedB(value);
break;
case 0x50:
g_main_cp_state.vtx_desc.Hex &= ~0x1FFFF; // keep the Upper bits
g_main_cp_state.vtx_desc.Hex |= value;
s_attr_dirty = 0xFF;
state->vtx_desc.Hex &= ~0x1FFFF; // keep the Upper bits
state->vtx_desc.Hex |= value;
state->attr_dirty = 0xFF;
break;
case 0x60:
g_main_cp_state.vtx_desc.Hex &= 0x1FFFF; // keep the lower 17Bits
g_main_cp_state.vtx_desc.Hex |= (u64)value << 17;
s_attr_dirty = 0xFF;
state->vtx_desc.Hex &= 0x1FFFF; // keep the lower 17Bits
state->vtx_desc.Hex |= (u64)value << 17;
state->attr_dirty = 0xFF;
break;
case 0x70:
_assert_((sub_cmd & 0x0F) < 8);
g_main_cp_state.vtx_attr[sub_cmd & 7].g0.Hex = value;
s_attr_dirty |= 1 << (sub_cmd & 7);
state->vtx_attr[sub_cmd & 7].g0.Hex = value;
state->attr_dirty |= 1 << (sub_cmd & 7);
break;
case 0x80:
_assert_((sub_cmd & 0x0F) < 8);
g_main_cp_state.vtx_attr[sub_cmd & 7].g1.Hex = value;
s_attr_dirty |= 1 << (sub_cmd & 7);
state->vtx_attr[sub_cmd & 7].g1.Hex = value;
state->attr_dirty |= 1 << (sub_cmd & 7);
break;
case 0x90:
_assert_((sub_cmd & 0x0F) < 8);
g_main_cp_state.vtx_attr[sub_cmd & 7].g2.Hex = value;
s_attr_dirty |= 1 << (sub_cmd & 7);
state->vtx_attr[sub_cmd & 7].g2.Hex = value;
state->attr_dirty |= 1 << (sub_cmd & 7);
break;
// Pointers to vertex arrays in GC RAM
case 0xA0:
g_main_cp_state.array_bases[sub_cmd & 0xF] = value;
cached_arraybases[sub_cmd & 0xF] = Memory::GetPointer(value);
state->array_bases[sub_cmd & 0xF] = value;
if (update_global_state)
cached_arraybases[sub_cmd & 0xF] = Memory::GetPointer(value);
break;
case 0xB0:
g_main_cp_state.array_strides[sub_cmd & 0xF] = value & 0xFF;
state->array_strides[sub_cmd & 0xF] = value & 0xFF;
break;
}
}

View File

@ -16,7 +16,7 @@ namespace VertexLoaderManager
void MarkAllDirty();
int GetVertexSize(int vtx_attr_group);
int GetVertexSize(int vtx_attr_group, bool preprocess);
// Returns false if buf_size is insufficient.
bool RunVertices(int vtx_attr_group, int primitive, int count, size_t buf_size, bool skip_drawing = false);

View File

@ -68,5 +68,6 @@ void VideoCommon_RunLoop(bool enable)
void VideoCommon_Init()
{
memset(&g_main_cp_state, 0, sizeof(g_main_cp_state));
memset(&g_preprocess_cp_state, 0, sizeof(g_preprocess_cp_state));
memset(texMem, 0, TMEM_SIZE);
}