From e86ddacb18affaef2d773b0c86fdf57f93d594c4 Mon Sep 17 00:00:00 2001 From: comex Date: Wed, 27 Aug 2014 13:38:00 -0400 Subject: [PATCH] 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. --- Source/Core/VideoCommon/CPMemory.cpp | 10 +++ Source/Core/VideoCommon/CPMemory.h | 11 ++- .../Core/VideoCommon/VertexLoaderManager.cpp | 80 ++++++++++--------- Source/Core/VideoCommon/VertexLoaderManager.h | 2 +- Source/Core/VideoCommon/VideoState.cpp | 1 + 5 files changed, 64 insertions(+), 40 deletions(-) diff --git a/Source/Core/VideoCommon/CPMemory.cpp b/Source/Core/VideoCommon/CPMemory.cpp index 22bc95c57d..739a3e66e3 100644 --- a/Source/Core/VideoCommon/CPMemory.cpp +++ b/Source/Core/VideoCommon/CPMemory.cpp @@ -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)); } diff --git a/Source/Core/VideoCommon/CPMemory.h b/Source/Core/VideoCommon/CPMemory.h index 9232a6b4f8..ae8ff08303 100644 --- a/Source/Core/VideoCommon/CPMemory.h +++ b/Source/Core/VideoCommon/CPMemory.h @@ -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); diff --git a/Source/Core/VideoCommon/VertexLoaderManager.cpp b/Source/Core/VideoCommon/VertexLoaderManager.cpp index 88c8b2d668..ca925d0302 100644 --- a/Source/Core/VideoCommon/VertexLoaderManager.cpp +++ b/Source/Core/VideoCommon/VertexLoaderManager.cpp @@ -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 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(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; } } diff --git a/Source/Core/VideoCommon/VertexLoaderManager.h b/Source/Core/VideoCommon/VertexLoaderManager.h index 32a64b6cd8..8995ad2d7a 100644 --- a/Source/Core/VideoCommon/VertexLoaderManager.h +++ b/Source/Core/VideoCommon/VertexLoaderManager.h @@ -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); diff --git a/Source/Core/VideoCommon/VideoState.cpp b/Source/Core/VideoCommon/VideoState.cpp index 72232e2737..dd0eb2fb88 100644 --- a/Source/Core/VideoCommon/VideoState.cpp +++ b/Source/Core/VideoCommon/VideoState.cpp @@ -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); }