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:
parent
f0131c2e09
commit
e86ddacb18
Source/Core/VideoCommon
|
@ -10,9 +10,12 @@
|
||||||
u8 *cached_arraybases[16];
|
u8 *cached_arraybases[16];
|
||||||
|
|
||||||
CPState g_main_cp_state;
|
CPState g_main_cp_state;
|
||||||
|
CPState g_preprocess_cp_state;
|
||||||
|
|
||||||
void DoCPState(PointerWrap& p)
|
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_bases, 16);
|
||||||
p.DoArray(g_main_cp_state.array_strides, 16);
|
p.DoArray(g_main_cp_state.array_strides, 16);
|
||||||
p.Do(g_main_cp_state.matrix_index_a);
|
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.Do(g_main_cp_state.vtx_desc.Hex);
|
||||||
p.DoArray(g_main_cp_state.vtx_attr, 8);
|
p.DoArray(g_main_cp_state.vtx_attr, 8);
|
||||||
p.DoMarker("CP Memory");
|
p.DoMarker("CP Memory");
|
||||||
|
if (p.mode == PointerWrap::MODE_READ)
|
||||||
|
CopyPreprocessCPStateFromMain();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CopyPreprocessCPStateFromMain()
|
||||||
|
{
|
||||||
|
memcpy(&g_preprocess_cp_state, &g_main_cp_state, sizeof(CPState));
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,6 +238,8 @@ struct VAT
|
||||||
UVAT_group2 g2;
|
UVAT_group2 g2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class VertexLoader;
|
||||||
|
|
||||||
// STATE_TO_SAVE
|
// STATE_TO_SAVE
|
||||||
struct CPState final
|
struct CPState final
|
||||||
{
|
{
|
||||||
|
@ -248,18 +250,25 @@ struct CPState final
|
||||||
TVtxDesc vtx_desc;
|
TVtxDesc vtx_desc;
|
||||||
// Most games only use the first VtxAttr and simply reconfigure it all the time as needed.
|
// Most games only use the first VtxAttr and simply reconfigure it all the time as needed.
|
||||||
VAT vtx_attr[8];
|
VAT vtx_attr[8];
|
||||||
|
|
||||||
|
// Attributes that actually belong to VertexLoaderManager:
|
||||||
|
int attr_dirty; // bitfield
|
||||||
|
VertexLoader* vertex_loaders[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
class PointerWrap;
|
class PointerWrap;
|
||||||
|
|
||||||
extern void DoCPState(PointerWrap& p);
|
extern void DoCPState(PointerWrap& p);
|
||||||
|
|
||||||
|
extern void CopyPreprocessCPStateFromMain();
|
||||||
|
|
||||||
extern CPState g_main_cp_state;
|
extern CPState g_main_cp_state;
|
||||||
|
extern CPState g_preprocess_cp_state;
|
||||||
|
|
||||||
extern u8 *cached_arraybases[16];
|
extern u8 *cached_arraybases[16];
|
||||||
|
|
||||||
// Might move this into its own file later.
|
// 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
|
// Fills memory with data from CP regs
|
||||||
void FillCPMemoryArray(u32 *memory);
|
void FillCPMemoryArray(u32 *memory);
|
||||||
|
|
|
@ -21,12 +21,8 @@
|
||||||
#include "VideoCommon/VertexShaderManager.h"
|
#include "VideoCommon/VertexShaderManager.h"
|
||||||
#include "VideoCommon/VideoCommon.h"
|
#include "VideoCommon/VideoCommon.h"
|
||||||
|
|
||||||
static int s_attr_dirty; // bitfield
|
|
||||||
|
|
||||||
static NativeVertexFormat* s_current_vtx_fmt;
|
static NativeVertexFormat* s_current_vtx_fmt;
|
||||||
|
|
||||||
static VertexLoader* s_VertexLoaders[8];
|
|
||||||
|
|
||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -53,10 +49,10 @@ static VertexLoaderMap s_vertex_loader_map;
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
MarkAllDirty();
|
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;
|
map_entry = nullptr;
|
||||||
}
|
|
||||||
RecomputeCachedArraybases();
|
RecomputeCachedArraybases();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,15 +100,16 @@ void AppendListToString(std::string *dest)
|
||||||
|
|
||||||
void MarkAllDirty()
|
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;
|
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);
|
std::lock_guard<std::mutex> lk(s_vertex_loader_map_lock);
|
||||||
VertexLoaderMap::iterator iter = s_vertex_loader_map.find(uid);
|
VertexLoaderMap::iterator iter = s_vertex_loader_map.find(uid);
|
||||||
if (iter != s_vertex_loader_map.end())
|
if (iter != s_vertex_loader_map.end())
|
||||||
|
@ -121,14 +118,14 @@ static VertexLoader* RefreshLoader(int vtx_attr_group)
|
||||||
}
|
}
|
||||||
else
|
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);
|
s_vertex_loader_map[uid] = std::unique_ptr<VertexLoader>(loader);
|
||||||
INCSTAT(stats.numVertexLoaders);
|
INCSTAT(stats.numVertexLoaders);
|
||||||
}
|
}
|
||||||
s_VertexLoaders[vtx_attr_group] = loader;
|
state->vertex_loaders[vtx_attr_group] = loader;
|
||||||
s_attr_dirty &= ~(1 << vtx_attr_group);
|
state->attr_dirty &= ~(1 << vtx_attr_group);
|
||||||
} else {
|
} else {
|
||||||
loader = s_VertexLoaders[vtx_attr_group];
|
loader = state->vertex_loaders[vtx_attr_group];
|
||||||
}
|
}
|
||||||
return loader;
|
return loader;
|
||||||
}
|
}
|
||||||
|
@ -137,7 +134,10 @@ bool RunVertices(int vtx_attr_group, int primitive, int count, size_t buf_size,
|
||||||
{
|
{
|
||||||
if (!count)
|
if (!count)
|
||||||
return true;
|
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();
|
size_t size = count * loader->GetVertexSize();
|
||||||
if (buf_size < size)
|
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();
|
NativeVertexFormat* native = loader->GetNativeVertexFormat();
|
||||||
|
|
||||||
|
|
||||||
// If the native vertex format changed, force a flush.
|
// If the native vertex format changed, force a flush.
|
||||||
if (native != s_current_vtx_fmt)
|
if (native != s_current_vtx_fmt)
|
||||||
VertexManager::Flush();
|
VertexManager::Flush();
|
||||||
|
@ -161,7 +160,7 @@ bool RunVertices(int vtx_attr_group, int primitive, int count, size_t buf_size,
|
||||||
VertexManager::PrepareForAdditionalData(primitive, count,
|
VertexManager::PrepareForAdditionalData(primitive, count,
|
||||||
loader->GetNativeVertexDeclaration().stride);
|
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);
|
IndexGenerator::AddIndices(primitive, count);
|
||||||
|
|
||||||
|
@ -170,9 +169,9 @@ bool RunVertices(int vtx_attr_group, int primitive, int count, size_t buf_size,
|
||||||
return true;
|
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()
|
NativeVertexFormat* GetCurrentVertexFormat()
|
||||||
|
@ -182,56 +181,61 @@ NativeVertexFormat* GetCurrentVertexFormat()
|
||||||
|
|
||||||
} // namespace
|
} // 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)
|
switch (sub_cmd & 0xF0)
|
||||||
{
|
{
|
||||||
case 0x30:
|
case 0x30:
|
||||||
VertexShaderManager::SetTexMatrixChangedA(value);
|
if (update_global_state)
|
||||||
|
VertexShaderManager::SetTexMatrixChangedA(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x40:
|
case 0x40:
|
||||||
VertexShaderManager::SetTexMatrixChangedB(value);
|
if (update_global_state)
|
||||||
|
VertexShaderManager::SetTexMatrixChangedB(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x50:
|
case 0x50:
|
||||||
g_main_cp_state.vtx_desc.Hex &= ~0x1FFFF; // keep the Upper bits
|
state->vtx_desc.Hex &= ~0x1FFFF; // keep the Upper bits
|
||||||
g_main_cp_state.vtx_desc.Hex |= value;
|
state->vtx_desc.Hex |= value;
|
||||||
s_attr_dirty = 0xFF;
|
state->attr_dirty = 0xFF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x60:
|
case 0x60:
|
||||||
g_main_cp_state.vtx_desc.Hex &= 0x1FFFF; // keep the lower 17Bits
|
state->vtx_desc.Hex &= 0x1FFFF; // keep the lower 17Bits
|
||||||
g_main_cp_state.vtx_desc.Hex |= (u64)value << 17;
|
state->vtx_desc.Hex |= (u64)value << 17;
|
||||||
s_attr_dirty = 0xFF;
|
state->attr_dirty = 0xFF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x70:
|
case 0x70:
|
||||||
_assert_((sub_cmd & 0x0F) < 8);
|
_assert_((sub_cmd & 0x0F) < 8);
|
||||||
g_main_cp_state.vtx_attr[sub_cmd & 7].g0.Hex = value;
|
state->vtx_attr[sub_cmd & 7].g0.Hex = value;
|
||||||
s_attr_dirty |= 1 << (sub_cmd & 7);
|
state->attr_dirty |= 1 << (sub_cmd & 7);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x80:
|
case 0x80:
|
||||||
_assert_((sub_cmd & 0x0F) < 8);
|
_assert_((sub_cmd & 0x0F) < 8);
|
||||||
g_main_cp_state.vtx_attr[sub_cmd & 7].g1.Hex = value;
|
state->vtx_attr[sub_cmd & 7].g1.Hex = value;
|
||||||
s_attr_dirty |= 1 << (sub_cmd & 7);
|
state->attr_dirty |= 1 << (sub_cmd & 7);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x90:
|
case 0x90:
|
||||||
_assert_((sub_cmd & 0x0F) < 8);
|
_assert_((sub_cmd & 0x0F) < 8);
|
||||||
g_main_cp_state.vtx_attr[sub_cmd & 7].g2.Hex = value;
|
state->vtx_attr[sub_cmd & 7].g2.Hex = value;
|
||||||
s_attr_dirty |= 1 << (sub_cmd & 7);
|
state->attr_dirty |= 1 << (sub_cmd & 7);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Pointers to vertex arrays in GC RAM
|
// Pointers to vertex arrays in GC RAM
|
||||||
case 0xA0:
|
case 0xA0:
|
||||||
g_main_cp_state.array_bases[sub_cmd & 0xF] = value;
|
state->array_bases[sub_cmd & 0xF] = value;
|
||||||
cached_arraybases[sub_cmd & 0xF] = Memory::GetPointer(value);
|
if (update_global_state)
|
||||||
|
cached_arraybases[sub_cmd & 0xF] = Memory::GetPointer(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xB0:
|
case 0xB0:
|
||||||
g_main_cp_state.array_strides[sub_cmd & 0xF] = value & 0xFF;
|
state->array_strides[sub_cmd & 0xF] = value & 0xFF;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace VertexLoaderManager
|
||||||
|
|
||||||
void MarkAllDirty();
|
void MarkAllDirty();
|
||||||
|
|
||||||
int GetVertexSize(int vtx_attr_group);
|
int GetVertexSize(int vtx_attr_group, bool preprocess);
|
||||||
// Returns false if buf_size is insufficient.
|
// 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);
|
bool RunVertices(int vtx_attr_group, int primitive, int count, size_t buf_size, bool skip_drawing = false);
|
||||||
|
|
||||||
|
|
|
@ -68,5 +68,6 @@ void VideoCommon_RunLoop(bool enable)
|
||||||
void VideoCommon_Init()
|
void VideoCommon_Init()
|
||||||
{
|
{
|
||||||
memset(&g_main_cp_state, 0, sizeof(g_main_cp_state));
|
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);
|
memset(texMem, 0, TMEM_SIZE);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue