Create and use CPArray enum class

This commit is contained in:
Pokechu22 2021-06-20 13:47:57 -07:00
parent 3aaeb2b9ef
commit 1914087998
22 changed files with 171 additions and 126 deletions

View File

@ -190,11 +190,11 @@ u32 AnalyzeCommand(const u8* data, DecodeMode mode)
{
s_DrawingObject = false;
int array = 0xc + (cmd - static_cast<u8>(Opcode::GX_LOAD_INDX_A)) / 8;
CPArray array = static_cast<CPArray>(0xc + (cmd - static_cast<u8>(Opcode::GX_LOAD_INDX_A)) / 8);
u32 value = ReadFifo32(data);
if (mode == DecodeMode::Record)
FifoRecordAnalyzer::ProcessLoadIndexedXf(value, array);
FifoRecordAnalyzer::ProcessLoadIndexedXf(array, value);
break;
}
@ -238,8 +238,8 @@ u32 AnalyzeCommand(const u8* data, DecodeMode mode)
{
for (size_t i = 0; i < offsets.size(); ++i)
{
FifoRecordAnalyzer::WriteVertexArray(static_cast<int>(i), data + offsets[i], vertexSize,
numVertices);
FifoRecordAnalyzer::WriteVertexArray(static_cast<CPArray>(i), data + offsets[i],
vertexSize, numVertices);
}
}
@ -284,11 +284,11 @@ void LoadCPReg(u32 subCmd, u32 value, CPMemory& cpMem)
break;
case ARRAY_BASE:
cpMem.arrayBases[subCmd & CP_ARRAY_MASK] = value;
cpMem.arrayBases[static_cast<CPArray>(subCmd & CP_ARRAY_MASK)] = value;
break;
case ARRAY_STRIDE:
cpMem.arrayStrides[subCmd & CP_ARRAY_MASK] = value & 0xFF;
cpMem.arrayStrides[static_cast<CPArray>(subCmd & CP_ARRAY_MASK)] = value & 0xFF;
break;
}
}

View File

@ -6,6 +6,8 @@
#include <array>
#include "Common/CommonTypes.h"
#include "Common/EnumMap.h"
#include "VideoCommon/CPMemory.h"
namespace FifoAnalyzer
@ -22,8 +24,8 @@ struct CPMemory
{
TVtxDesc vtxDesc;
std::array<VAT, CP_NUM_VAT_REG> vtxAttr;
std::array<u32, CP_NUM_ARRAYS> arrayBases{};
std::array<u32, CP_NUM_ARRAYS> arrayStrides{};
Common::EnumMap<u32, CPArray::XF_D> arrayBases{};
Common::EnumMap<u32, CPArray::XF_D> arrayStrides{};
};
void LoadCPReg(u32 subCmd, u32 value, CPMemory& cpMem);

View File

@ -30,7 +30,7 @@ void FifoRecordAnalyzer::Initialize(const u32* cpMem)
std::copy(strides_start, strides_end, s_CpMem.arrayStrides.begin());
}
void FifoRecordAnalyzer::ProcessLoadIndexedXf(u32 val, int array)
void FifoRecordAnalyzer::ProcessLoadIndexedXf(CPArray array, u32 val)
{
int index = val >> 16;
int size = ((val >> 12) & 0xF) + 1;
@ -40,19 +40,19 @@ void FifoRecordAnalyzer::ProcessLoadIndexedXf(u32 val, int array)
FifoRecorder::GetInstance().UseMemory(address, size * 4, MemoryUpdate::XF_DATA);
}
void FifoRecordAnalyzer::WriteVertexArray(int arrayIndex, const u8* vertexData, int vertexSize,
void FifoRecordAnalyzer::WriteVertexArray(CPArray arrayIndex, const u8* vertexData, int vertexSize,
int numVertices)
{
// Skip if not indexed array
VertexComponentFormat arrayType;
if (arrayIndex == ARRAY_POSITION)
if (arrayIndex == CPArray::Position)
arrayType = s_CpMem.vtxDesc.low.Position;
else if (arrayIndex == ARRAY_NORMAL)
else if (arrayIndex == CPArray::Normal)
arrayType = s_CpMem.vtxDesc.low.Normal;
else if (arrayIndex >= ARRAY_COLOR0 && arrayIndex < ARRAY_COLOR0 + NUM_COLOR_ARRAYS)
arrayType = s_CpMem.vtxDesc.low.Color[arrayIndex - ARRAY_COLOR0];
else if (arrayIndex >= ARRAY_TEXCOORD0 && arrayIndex < ARRAY_TEXCOORD0 + NUM_TEXCOORD_ARRAYS)
arrayType = s_CpMem.vtxDesc.high.TexCoord[arrayIndex - ARRAY_TEXCOORD0];
else if (arrayIndex >= CPArray::Color0 && arrayIndex <= CPArray::Color1)
arrayType = s_CpMem.vtxDesc.low.Color[u8(arrayIndex) - u8(CPArray::Color0)];
else if (arrayIndex >= CPArray::TexCoord0 && arrayIndex <= CPArray::TexCoord7)
arrayType = s_CpMem.vtxDesc.high.TexCoord[u8(arrayIndex) - u8(CPArray::TexCoord0)];
else
{
PanicAlertFmt("Invalid arrayIndex {}", arrayIndex);

View File

@ -5,11 +5,13 @@
#include "Common/CommonTypes.h"
enum class CPArray : u8;
namespace FifoRecordAnalyzer
{
// Must call this before analyzing Fifo commands with FifoAnalyzer::AnalyzeCommand()
void Initialize(const u32* cpMem);
void ProcessLoadIndexedXf(u32 val, int array);
void WriteVertexArray(int arrayIndex, const u8* vertexData, int vertexSize, int numVertices);
void ProcessLoadIndexedXf(CPArray array, u32 val);
void WriteVertexArray(CPArray arrayIndex, const u8* vertexData, int vertexSize, int numVertices);
} // namespace FifoRecordAnalyzer

View File

@ -287,7 +287,7 @@ void FIFOAnalyzer::UpdateDetails()
case Opcode::GX_LOAD_INDX_A:
{
const auto [desc, written] =
GetXFIndexedLoadInfo(ARRAY_XF_A, Common::swap32(&object[object_offset]));
GetXFIndexedLoadInfo(CPArray::XF_A, Common::swap32(&object[object_offset]));
object_offset += 4;
new_label = QStringLiteral("LOAD INDX A %1").arg(QString::fromStdString(desc));
}
@ -295,7 +295,7 @@ void FIFOAnalyzer::UpdateDetails()
case Opcode::GX_LOAD_INDX_B:
{
const auto [desc, written] =
GetXFIndexedLoadInfo(ARRAY_XF_B, Common::swap32(&object[object_offset]));
GetXFIndexedLoadInfo(CPArray::XF_B, Common::swap32(&object[object_offset]));
object_offset += 4;
new_label = QStringLiteral("LOAD INDX B %1").arg(QString::fromStdString(desc));
}
@ -303,7 +303,7 @@ void FIFOAnalyzer::UpdateDetails()
case Opcode::GX_LOAD_INDX_C:
{
const auto [desc, written] =
GetXFIndexedLoadInfo(ARRAY_XF_C, Common::swap32(&object[object_offset]));
GetXFIndexedLoadInfo(CPArray::XF_C, Common::swap32(&object[object_offset]));
object_offset += 4;
new_label = QStringLiteral("LOAD INDX C %1").arg(QString::fromStdString(desc));
}
@ -311,7 +311,7 @@ void FIFOAnalyzer::UpdateDetails()
case Opcode::GX_LOAD_INDX_D:
{
const auto [desc, written] =
GetXFIndexedLoadInfo(ARRAY_XF_D, Common::swap32(&object[object_offset]));
GetXFIndexedLoadInfo(CPArray::XF_D, Common::swap32(&object[object_offset]));
object_offset += 4;
new_label = QStringLiteral("LOAD INDX D %1").arg(QString::fromStdString(desc));
}
@ -619,7 +619,7 @@ void FIFOAnalyzer::UpdateDescription()
}
else if (opcode == Opcode::GX_LOAD_INDX_A)
{
const auto [desc, written] = GetXFIndexedLoadInfo(ARRAY_XF_A, Common::swap32(cmddata + 1));
const auto [desc, written] = GetXFIndexedLoadInfo(CPArray::XF_A, Common::swap32(cmddata + 1));
text = QString::fromStdString(desc);
text += QLatin1Char{'\n'};
@ -629,7 +629,7 @@ void FIFOAnalyzer::UpdateDescription()
}
else if (opcode == Opcode::GX_LOAD_INDX_B)
{
const auto [desc, written] = GetXFIndexedLoadInfo(ARRAY_XF_B, Common::swap32(cmddata + 1));
const auto [desc, written] = GetXFIndexedLoadInfo(CPArray::XF_B, Common::swap32(cmddata + 1));
text = QString::fromStdString(desc);
text += QLatin1Char{'\n'};
@ -641,7 +641,7 @@ void FIFOAnalyzer::UpdateDescription()
}
else if (opcode == Opcode::GX_LOAD_INDX_C)
{
const auto [desc, written] = GetXFIndexedLoadInfo(ARRAY_XF_C, Common::swap32(cmddata + 1));
const auto [desc, written] = GetXFIndexedLoadInfo(CPArray::XF_C, Common::swap32(cmddata + 1));
text = QString::fromStdString(desc);
text += QLatin1Char{'\n'};
@ -652,7 +652,7 @@ void FIFOAnalyzer::UpdateDescription()
}
else if (opcode == Opcode::GX_LOAD_INDX_D)
{
const auto [desc, written] = GetXFIndexedLoadInfo(ARRAY_XF_D, Common::swap32(cmddata + 1));
const auto [desc, written] = GetXFIndexedLoadInfo(CPArray::XF_D, Common::swap32(cmddata + 1));
text = QString::fromStdString(desc);
text += QLatin1Char{'\n'};

View File

@ -62,11 +62,13 @@ std::pair<std::string, std::string> GetCPRegInfo(u8 cmd, u32 value)
return std::make_pair(fmt::format("CP_VAT_REG_C - Format {}", cmd & CP_VAT_MASK),
fmt::to_string(UVAT_group2{.Hex = value}));
case ARRAY_BASE:
return std::make_pair(fmt::format("ARRAY_BASE Array {}", cmd & CP_ARRAY_MASK),
fmt::format("Base address {:08x}", value));
return std::make_pair(
fmt::format("ARRAY_BASE Array {}", static_cast<CPArray>(cmd & CP_ARRAY_MASK)),
fmt::format("Base address {:08x}", value));
case ARRAY_STRIDE:
return std::make_pair(fmt::format("ARRAY_STRIDE Array {}", cmd - ARRAY_STRIDE),
fmt::format("Stride {:02x}", value & 0xff));
return std::make_pair(
fmt::format("ARRAY_STRIDE Array {}", static_cast<CPArray>(cmd & CP_ARRAY_MASK)),
fmt::format("Stride {:02x}", value & 0xff));
default:
return std::make_pair(fmt::format("Invalid CP register {:02x} = {:08x}", cmd, value), "");
}

View File

@ -11,6 +11,7 @@
#include "Common/BitSet.h"
#include "Common/CommonTypes.h"
#include "Common/EnumFormatter.h"
#include "Common/EnumMap.h"
#include "Common/MsgHandler.h"
enum
@ -53,24 +54,46 @@ enum
};
// Vertex array numbers
enum
enum class CPArray : u8
{
ARRAY_POSITION = 0,
ARRAY_NORMAL = 1,
ARRAY_COLOR0 = 2,
NUM_COLOR_ARRAYS = 2,
ARRAY_TEXCOORD0 = 4,
NUM_TEXCOORD_ARRAYS = 8,
Position = 0,
Normal = 1,
ARRAY_XF_A = 12, // Usually used for position matrices
ARRAY_XF_B = 13, // Usually used for normal matrices
ARRAY_XF_C = 14, // Usually used for tex coord matrices
ARRAY_XF_D = 15, // Usually used for light objects
Color0 = 2,
Color1 = 3,
// Number of arrays related to vertex components (position, normal, color, tex coord)
// Excludes the 4 arrays used for indexed XF loads
NUM_VERTEX_COMPONENT_ARRAYS = 12,
TexCoord0 = 4,
TexCoord1 = 5,
TexCoord2 = 6,
TexCoord3 = 7,
TexCoord4 = 8,
TexCoord5 = 9,
TexCoord6 = 10,
TexCoord7 = 11,
XF_A = 12, // Usually used for position matrices
XF_B = 13, // Usually used for normal matrices
XF_C = 14, // Usually used for tex coord matrices
XF_D = 15, // Usually used for light objects
};
template <>
struct fmt::formatter<CPArray> : EnumFormatter<CPArray::XF_D>
{
static constexpr array_type names = {"Position", "Normal", "Color 0", "Color 1",
"Tex Coord 0", "Tex Coord 1", "Tex Coord 2", "Tex Coord 3",
"Tex Coord 4", "Tex Coord 5", "Tex Coord 6", "Tex Coord 7",
"XF A", "XF B", "XF C", "XF D"};
formatter() : EnumFormatter(names) {}
};
// Intended for offsetting from Color0/TexCoord0
constexpr CPArray operator+(CPArray array, u8 offset)
{
return static_cast<CPArray>(static_cast<u8>(array) + offset);
}
// Number of arrays related to vertex components (position, normal, color, tex coord)
// Excludes the 4 arrays used for indexed XF loads
constexpr u8 NUM_VERTEX_COMPONENT_ARRAYS = 12;
// Vertex components
enum class VertexComponentFormat
@ -607,8 +630,8 @@ class VertexLoaderBase;
// STATE_TO_SAVE
struct CPState final
{
u32 array_bases[CP_NUM_ARRAYS]{};
u32 array_strides[CP_NUM_ARRAYS]{};
Common::EnumMap<u32, CPArray::XF_D> array_bases;
Common::EnumMap<u32, CPArray::XF_D> array_strides;
TMatrixIndexA matrix_index_a{};
TMatrixIndexB matrix_index_b{};
TVtxDesc vtx_desc;

View File

@ -166,12 +166,12 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
// GX_LOAD_INDX_B (40) -> 0xD
// GX_LOAD_INDX_C (48) -> 0xE
// GX_LOAD_INDX_D (56) -> 0xF
const int ref_array = (cmd_byte / 8) + 8;
const auto array = static_cast<CPArray>((cmd_byte / 8) + 8);
if constexpr (is_preprocess)
PreprocessIndexedXF(src.Read<u32>(), ref_array);
PreprocessIndexedXF(array, src.Read<u32>());
else
LoadIndexedXF(src.Read<u32>(), ref_array);
LoadIndexedXF(array, src.Read<u32>());
}
break;

View File

@ -6,6 +6,7 @@
#include <array>
#include "Common/CommonTypes.h"
#include "VideoCommon/CPMemory.h"
#include "VideoCommon/DataReader.h"
#include "VideoCommon/VertexLoaderManager.h"
@ -59,7 +60,7 @@ VertexLoaderARM64::VertexLoaderARM64(const TVtxDesc& vtx_desc, const VAT& vtx_at
WriteProtect();
}
void VertexLoaderARM64::GetVertexAddr(int array, VertexComponentFormat attribute, ARM64Reg reg)
void VertexLoaderARM64::GetVertexAddr(CPArray array, VertexComponentFormat attribute, ARM64Reg reg)
{
if (IsIndexed(attribute))
{
@ -95,7 +96,7 @@ void VertexLoaderARM64::GetVertexAddr(int array, VertexComponentFormat attribute
REV16(scratch1_reg, scratch1_reg);
}
if (array == ARRAY_POSITION)
if (array == CPArray::Position)
{
EOR(scratch2_reg, scratch1_reg,
attribute == VertexComponentFormat::Index8 ? LogicalImm(0xFF, 32) :
@ -103,17 +104,18 @@ void VertexLoaderARM64::GetVertexAddr(int array, VertexComponentFormat attribute
m_skip_vertex = CBZ(scratch2_reg);
}
LDR(IndexType::Unsigned, scratch2_reg, stride_reg, array * 4);
LDR(IndexType::Unsigned, scratch2_reg, stride_reg, static_cast<u8>(array) * 4);
MUL(scratch1_reg, scratch1_reg, scratch2_reg);
LDR(IndexType::Unsigned, EncodeRegTo64(scratch2_reg), arraybase_reg, array * 8);
LDR(IndexType::Unsigned, EncodeRegTo64(scratch2_reg), arraybase_reg,
static_cast<u8>(array) * 8);
ADD(EncodeRegTo64(reg), EncodeRegTo64(scratch1_reg), EncodeRegTo64(scratch2_reg));
}
else
ADD(reg, src_reg, m_src_ofs);
}
s32 VertexLoaderARM64::GetAddressImm(int array, VertexComponentFormat attribute,
s32 VertexLoaderARM64::GetAddressImm(CPArray array, VertexComponentFormat attribute,
Arm64Gen::ARM64Reg reg, u32 align)
{
if (IsIndexed(attribute) || (m_src_ofs > 255 && (m_src_ofs & (align - 1))))
@ -448,8 +450,8 @@ void VertexLoaderARM64::GenerateVertexLoader()
int load_size = GetLoadSize(load_bytes);
load_size <<= 3;
s32 offset = GetAddressImm(ARRAY_POSITION, m_VtxDesc.low.Position, EncodeRegTo64(scratch1_reg),
load_size);
s32 offset = GetAddressImm(CPArray::Position, m_VtxDesc.low.Position,
EncodeRegTo64(scratch1_reg), load_size);
ReadVertex(m_VtxDesc.low.Position, m_VtxAttr.g0.PosFormat, pos_elements, pos_elements,
m_VtxAttr.g0.ByteDequant, m_VtxAttr.g0.PosFrac, &m_native_vtx_decl.position, offset);
}
@ -470,7 +472,7 @@ void VertexLoaderARM64::GenerateVertexLoader()
int load_bytes = elem_size * 3;
int load_size = GetLoadSize(load_bytes);
offset = GetAddressImm(ARRAY_NORMAL, m_VtxDesc.low.Normal, EncodeRegTo64(scratch1_reg),
offset = GetAddressImm(CPArray::Normal, m_VtxDesc.low.Normal, EncodeRegTo64(scratch1_reg),
load_size << 3);
if (offset == -1)
@ -488,7 +490,7 @@ void VertexLoaderARM64::GenerateVertexLoader()
}
}
for (size_t i = 0; i < m_VtxDesc.low.Color.Size(); i++)
for (u8 i = 0; i < m_VtxDesc.low.Color.Size(); i++)
{
m_native_vtx_decl.colors[i].components = 4;
m_native_vtx_decl.colors[i].type = VAR_UNSIGNED_BYTE;
@ -501,7 +503,7 @@ void VertexLoaderARM64::GenerateVertexLoader()
m_VtxAttr.GetColorFormat(i) == ColorFormat::RGBA4444)
align = 2;
s32 offset = GetAddressImm(ARRAY_COLOR0 + int(i), m_VtxDesc.low.Color[i],
s32 offset = GetAddressImm(CPArray::Color0 + i, m_VtxDesc.low.Color[i],
EncodeRegTo64(scratch1_reg), align);
ReadColor(m_VtxDesc.low.Color[i], m_VtxAttr.GetColorFormat(i), offset);
m_native_vtx_decl.colors[i].components = 4;
@ -513,7 +515,7 @@ void VertexLoaderARM64::GenerateVertexLoader()
}
}
for (size_t i = 0; i < m_VtxDesc.high.TexCoord.Size(); i++)
for (u8 i = 0; i < m_VtxDesc.high.TexCoord.Size(); i++)
{
m_native_vtx_decl.texcoords[i].offset = m_dst_ofs;
m_native_vtx_decl.texcoords[i].type = VAR_FLOAT;
@ -527,7 +529,7 @@ void VertexLoaderARM64::GenerateVertexLoader()
int load_size = GetLoadSize(load_bytes);
load_size <<= 3;
s32 offset = GetAddressImm(ARRAY_TEXCOORD0 + int(i), m_VtxDesc.high.TexCoord[i],
s32 offset = GetAddressImm(CPArray::TexCoord0 + i, m_VtxDesc.high.TexCoord[i],
EncodeRegTo64(scratch1_reg), load_size);
u8 scaling_exponent = m_VtxAttr.GetTexFrac(i);
ReadVertex(m_VtxDesc.high.TexCoord[i], m_VtxAttr.GetTexFormat(i), elements,

View File

@ -11,6 +11,7 @@ class DataReader;
enum class VertexComponentFormat;
enum class ComponentFormat;
enum class ColorFormat;
enum class CPArray : u8;
class VertexLoaderARM64 : public VertexLoaderBase, public Arm64Gen::ARM64CodeBlock
{
@ -25,8 +26,9 @@ private:
u32 m_dst_ofs = 0;
Arm64Gen::FixupBranch m_skip_vertex;
Arm64Gen::ARM64FloatEmitter m_float_emit;
void GetVertexAddr(int array, VertexComponentFormat attribute, Arm64Gen::ARM64Reg reg);
s32 GetAddressImm(int array, VertexComponentFormat attribute, Arm64Gen::ARM64Reg reg, u32 align);
void GetVertexAddr(CPArray array, VertexComponentFormat attribute, Arm64Gen::ARM64Reg reg);
s32 GetAddressImm(CPArray array, VertexComponentFormat attribute, Arm64Gen::ARM64Reg reg,
u32 align);
int ReadVertex(VertexComponentFormat attribute, ComponentFormat format, int count_in,
int count_out, bool dequantize, u8 scaling_exponent,
AttributeFormat* native_format, s32 offset = -1);

View File

@ -14,6 +14,7 @@
#include "Common/Assert.h"
#include "Common/CommonTypes.h"
#include "Common/EnumMap.h"
#include "Common/Logging/Log.h"
#include "Core/DolphinAnalytics.h"
@ -48,7 +49,14 @@ static std::mutex s_vertex_loader_map_lock;
static VertexLoaderMap s_vertex_loader_map;
// TODO - change into array of pointers. Keep a map of all seen so far.
u8* cached_arraybases[NUM_VERTEX_COMPONENT_ARRAYS];
Common::EnumMap<u8*, CPArray::TexCoord7> cached_arraybases;
BitSet8 g_main_vat_dirty;
BitSet8 g_preprocess_vat_dirty;
bool g_bases_dirty; // Main only
u8 g_current_vat; // Main only
std::array<VertexLoaderBase*, CP_NUM_VAT_REG> g_main_vertex_loaders;
std::array<VertexLoaderBase*, CP_NUM_VAT_REG> g_preprocess_vertex_loaders;
void Init()
{
@ -80,24 +88,25 @@ void UpdateVertexArrayPointers()
// 12 through 15 are used for loading data into xfmem.
// We also only update the array base if the vertex description states we are going to use it.
if (IsIndexed(g_main_cp_state.vtx_desc.low.Position))
cached_arraybases[ARRAY_POSITION] =
Memory::GetPointer(g_main_cp_state.array_bases[ARRAY_POSITION]);
cached_arraybases[CPArray::Position] =
Memory::GetPointer(g_main_cp_state.array_bases[CPArray::Position]);
if (IsIndexed(g_main_cp_state.vtx_desc.low.Normal))
cached_arraybases[ARRAY_NORMAL] = Memory::GetPointer(g_main_cp_state.array_bases[ARRAY_NORMAL]);
cached_arraybases[CPArray::Normal] =
Memory::GetPointer(g_main_cp_state.array_bases[CPArray::Normal]);
for (size_t i = 0; i < g_main_cp_state.vtx_desc.low.Color.Size(); i++)
for (u8 i = 0; i < g_main_cp_state.vtx_desc.low.Color.Size(); i++)
{
if (IsIndexed(g_main_cp_state.vtx_desc.low.Color[i]))
cached_arraybases[ARRAY_COLOR0 + i] =
Memory::GetPointer(g_main_cp_state.array_bases[ARRAY_COLOR0 + i]);
cached_arraybases[CPArray::Color0 + i] =
Memory::GetPointer(g_main_cp_state.array_bases[CPArray::Color0 + i]);
}
for (size_t i = 0; i < g_main_cp_state.vtx_desc.high.TexCoord.Size(); i++)
for (u8 i = 0; i < g_main_cp_state.vtx_desc.high.TexCoord.Size(); i++)
{
if (IsIndexed(g_main_cp_state.vtx_desc.high.TexCoord[i]))
cached_arraybases[ARRAY_TEXCOORD0 + i] =
Memory::GetPointer(g_main_cp_state.array_bases[ARRAY_TEXCOORD0 + i]);
cached_arraybases[CPArray::TexCoord0 + i] =
Memory::GetPointer(g_main_cp_state.array_bases[CPArray::TexCoord0 + i]);
}
g_main_cp_state.bases_dirty = false;
@ -398,13 +407,13 @@ void LoadCPReg(u32 sub_cmd, u32 value, bool is_preprocess)
// Pointers to vertex arrays in GC RAM
case ARRAY_BASE:
state->array_bases[sub_cmd & CP_ARRAY_MASK] =
state->array_bases[static_cast<CPArray>(sub_cmd & CP_ARRAY_MASK)] =
value & CommandProcessor::GetPhysicalAddressMask();
state->bases_dirty = true;
break;
case ARRAY_STRIDE:
state->array_strides[sub_cmd & CP_ARRAY_MASK] = value & 0xFF;
state->array_strides[static_cast<CPArray>(sub_cmd & CP_ARRAY_MASK)] = value & 0xFF;
break;
default:
@ -427,9 +436,9 @@ void FillCPMemoryArray(u32* memory)
memory[CP_VAT_REG_C + i] = g_main_cp_state.vtx_attr[i].g2.Hex;
}
for (int i = 0; i < CP_NUM_ARRAYS; ++i)
for (u8 i = 0; i < CP_NUM_ARRAYS; ++i)
{
memory[ARRAY_BASE + i] = g_main_cp_state.array_bases[i];
memory[ARRAY_STRIDE + i] = g_main_cp_state.array_strides[i];
memory[ARRAY_BASE + i] = g_main_cp_state.array_bases[static_cast<CPArray>(i)];
memory[ARRAY_STRIDE + i] = g_main_cp_state.array_strides[static_cast<CPArray>(i)];
}
}

View File

@ -8,6 +8,7 @@
#include <unordered_map>
#include "Common/CommonTypes.h"
#include "Common/EnumMap.h"
#include "VideoCommon/CPMemory.h"
class DataReader;
@ -46,7 +47,7 @@ int RunVertices(int vtx_attr_group, OpcodeDecoder::Primitive primitive, int coun
NativeVertexFormat* GetCurrentVertexFormat();
// Resolved pointers to array bases. Used by vertex loaders.
extern u8* cached_arraybases[NUM_VERTEX_COMPONENT_ARRAYS];
extern Common::EnumMap<u8*, CPArray::TexCoord7> cached_arraybases;
void UpdateVertexArrayPointers();
// Position cache for zfreeze (3 vertices, 4 floats each to allow SIMD overwrite).

View File

@ -15,6 +15,7 @@
#include "Common/JitRegister.h"
#include "Common/x64ABI.h"
#include "Common/x64Emitter.h"
#include "VideoCommon/CPMemory.h"
#include "VideoCommon/DataReader.h"
#include "VideoCommon/VertexLoaderManager.h"
@ -54,7 +55,7 @@ VertexLoaderX64::VertexLoaderX64(const TVtxDesc& vtx_desc, const VAT& vtx_att)
JitRegister::Register(region, GetCodePtr(), name.c_str());
}
OpArg VertexLoaderX64::GetVertexAddr(int array, VertexComponentFormat attribute)
OpArg VertexLoaderX64::GetVertexAddr(CPArray array, VertexComponentFormat attribute)
{
OpArg data = MDisp(src_reg, m_src_ofs);
if (IsIndexed(attribute))
@ -62,7 +63,7 @@ OpArg VertexLoaderX64::GetVertexAddr(int array, VertexComponentFormat attribute)
int bits = attribute == VertexComponentFormat::Index8 ? 8 : 16;
LoadAndSwap(bits, scratch1, data);
m_src_ofs += bits / 8;
if (array == ARRAY_POSITION)
if (array == CPArray::Position)
{
CMP(bits, R(scratch1), Imm8(-1));
m_skip_vertex = J_CC(CC_E, true);
@ -433,7 +434,7 @@ void VertexLoaderX64::GenerateVertexLoader()
texmatidx_ofs[i] = m_src_ofs++;
}
OpArg data = GetVertexAddr(ARRAY_POSITION, m_VtxDesc.low.Position);
OpArg data = GetVertexAddr(CPArray::Position, m_VtxDesc.low.Position);
int pos_elements = m_VtxAttr.g0.PosElements == CoordComponentCount::XY ? 2 : 3;
ReadVertex(data, m_VtxDesc.low.Position, m_VtxAttr.g0.PosFormat, pos_elements, pos_elements,
m_VtxAttr.g0.ByteDequant, m_VtxAttr.g0.PosFrac, &m_native_vtx_decl.position);
@ -448,7 +449,7 @@ void VertexLoaderX64::GenerateVertexLoader()
{
if (!i || m_VtxAttr.g0.NormalIndex3)
{
data = GetVertexAddr(ARRAY_NORMAL, m_VtxDesc.low.Normal);
data = GetVertexAddr(CPArray::Normal, m_VtxDesc.low.Normal);
int elem_size = GetElementSize(m_VtxAttr.g0.NormalFormat);
data.AddMemOffset(i * elem_size * 3);
}
@ -457,11 +458,11 @@ void VertexLoaderX64::GenerateVertexLoader()
}
}
for (size_t i = 0; i < m_VtxDesc.low.Color.Size(); i++)
for (u8 i = 0; i < m_VtxDesc.low.Color.Size(); i++)
{
if (m_VtxDesc.low.Color[i] != VertexComponentFormat::NotPresent)
{
data = GetVertexAddr(ARRAY_COLOR0 + int(i), m_VtxDesc.low.Color[i]);
data = GetVertexAddr(CPArray::Color0 + i, m_VtxDesc.low.Color[i]);
ReadColor(data, m_VtxDesc.low.Color[i], m_VtxAttr.GetColorFormat(i));
m_native_vtx_decl.colors[i].components = 4;
m_native_vtx_decl.colors[i].enable = true;
@ -472,12 +473,12 @@ void VertexLoaderX64::GenerateVertexLoader()
}
}
for (size_t i = 0; i < m_VtxDesc.high.TexCoord.Size(); i++)
for (u8 i = 0; i < m_VtxDesc.high.TexCoord.Size(); i++)
{
int elements = m_VtxAttr.GetTexElements(i) == TexComponentCount::ST ? 2 : 1;
if (m_VtxDesc.high.TexCoord[i] != VertexComponentFormat::NotPresent)
{
data = GetVertexAddr(ARRAY_TEXCOORD0 + int(i), m_VtxDesc.high.TexCoord[i]);
data = GetVertexAddr(CPArray::TexCoord0 + i, m_VtxDesc.high.TexCoord[i]);
u8 scaling_exponent = m_VtxAttr.GetTexFrac(i);
ReadVertex(data, m_VtxDesc.high.TexCoord[i], m_VtxAttr.GetTexFormat(i), elements,
m_VtxDesc.low.TexMatIdx[i] ? 2 : elements, m_VtxAttr.g0.ByteDequant,

View File

@ -10,6 +10,7 @@
enum class VertexComponentFormat;
enum class ComponentFormat;
enum class ColorFormat;
enum class CPArray : u8;
class VertexLoaderX64 : public VertexLoaderBase, public Gen::X64CodeBlock
{
@ -23,7 +24,7 @@ private:
u32 m_src_ofs = 0;
u32 m_dst_ofs = 0;
Gen::FixupBranch m_skip_vertex;
Gen::OpArg GetVertexAddr(int array, VertexComponentFormat attribute);
Gen::OpArg GetVertexAddr(CPArray array, VertexComponentFormat attribute);
int ReadVertex(Gen::OpArg data, VertexComponentFormat attribute, ComponentFormat format,
int count_in, int count_out, bool dequantize, u8 scaling_exponent,
AttributeFormat* native_format);

View File

@ -79,8 +79,8 @@ void Color_ReadIndex_16b_565(VertexLoader* loader)
{
const auto index = DataRead<I>();
const u8* const address =
VertexLoaderManager::cached_arraybases[ARRAY_COLOR0 + loader->m_colIndex] +
(index * g_main_cp_state.array_strides[ARRAY_COLOR0 + loader->m_colIndex]);
VertexLoaderManager::cached_arraybases[CPArray::Color0 + loader->m_colIndex] +
(index * g_main_cp_state.array_strides[CPArray::Color0 + loader->m_colIndex]);
u16 value;
std::memcpy(&value, address, sizeof(u16));
@ -92,8 +92,8 @@ template <typename I>
void Color_ReadIndex_24b_888(VertexLoader* loader)
{
const auto index = DataRead<I>();
const u8* address = VertexLoaderManager::cached_arraybases[ARRAY_COLOR0 + loader->m_colIndex] +
(index * g_main_cp_state.array_strides[ARRAY_COLOR0 + loader->m_colIndex]);
const u8* address = VertexLoaderManager::cached_arraybases[CPArray::Color0 + loader->m_colIndex] +
(index * g_main_cp_state.array_strides[CPArray::Color0 + loader->m_colIndex]);
SetCol(loader, Read24(address));
}
@ -101,18 +101,18 @@ template <typename I>
void Color_ReadIndex_32b_888x(VertexLoader* loader)
{
const auto index = DataRead<I>();
const u8* address = VertexLoaderManager::cached_arraybases[ARRAY_COLOR0 + loader->m_colIndex] +
(index * g_main_cp_state.array_strides[ARRAY_COLOR0 + loader->m_colIndex]);
const u8* address = VertexLoaderManager::cached_arraybases[CPArray::Color0 + loader->m_colIndex] +
(index * g_main_cp_state.array_strides[CPArray::Color0 + loader->m_colIndex]);
SetCol(loader, Read24(address));
}
template <typename I>
void Color_ReadIndex_16b_4444(VertexLoader* loader)
{
auto const index = DataRead<I>();
const auto index = DataRead<I>();
const u8* const address =
VertexLoaderManager::cached_arraybases[ARRAY_COLOR0 + loader->m_colIndex] +
(index * g_main_cp_state.array_strides[ARRAY_COLOR0 + loader->m_colIndex]);
VertexLoaderManager::cached_arraybases[CPArray::Color0 + loader->m_colIndex] +
(index * g_main_cp_state.array_strides[CPArray::Color0 + loader->m_colIndex]);
u16 value;
std::memcpy(&value, address, sizeof(u16));
@ -124,8 +124,8 @@ template <typename I>
void Color_ReadIndex_24b_6666(VertexLoader* loader)
{
const auto index = DataRead<I>();
const u8* data = VertexLoaderManager::cached_arraybases[ARRAY_COLOR0 + loader->m_colIndex] +
(index * g_main_cp_state.array_strides[ARRAY_COLOR0 + loader->m_colIndex]) - 1;
const u8* data = VertexLoaderManager::cached_arraybases[CPArray::Color0 + loader->m_colIndex] +
(index * g_main_cp_state.array_strides[CPArray::Color0 + loader->m_colIndex]) - 1;
const u32 val = Common::swap32(data);
SetCol6666(loader, val);
}
@ -134,8 +134,8 @@ template <typename I>
void Color_ReadIndex_32b_8888(VertexLoader* loader)
{
const auto index = DataRead<I>();
const u8* address = VertexLoaderManager::cached_arraybases[ARRAY_COLOR0 + loader->m_colIndex] +
(index * g_main_cp_state.array_strides[ARRAY_COLOR0 + loader->m_colIndex]);
const u8* address = VertexLoaderManager::cached_arraybases[CPArray::Color0 + loader->m_colIndex] +
(index * g_main_cp_state.array_strides[CPArray::Color0 + loader->m_colIndex]);
SetCol(loader, Read32(address));
}

View File

@ -59,7 +59,7 @@ struct Normal_Direct
{
static void function([[maybe_unused]] VertexLoader* loader)
{
auto const source = reinterpret_cast<const T*>(DataGetPosition());
const auto source = reinterpret_cast<const T*>(DataGetPosition());
ReadIndirect<T, N * 3>(source);
DataSkip<N * 3 * sizeof(T)>();
}
@ -72,10 +72,10 @@ void Normal_Index_Offset()
{
static_assert(std::is_unsigned_v<I>, "Only unsigned I is sane!");
auto const index = DataRead<I>();
auto const data = reinterpret_cast<const T*>(
VertexLoaderManager::cached_arraybases[ARRAY_NORMAL] +
(index * g_main_cp_state.array_strides[ARRAY_NORMAL]) + sizeof(T) * 3 * Offset);
const auto index = DataRead<I>();
const auto data = reinterpret_cast<const T*>(
VertexLoaderManager::cached_arraybases[CPArray::Normal] +
(index * g_main_cp_state.array_strides[CPArray::Normal]) + sizeof(T) * 3 * Offset);
ReadIndirect<T, N * 3>(data);
}

View File

@ -60,8 +60,8 @@ void Pos_ReadIndex(VertexLoader* loader)
const auto index = DataRead<I>();
loader->m_vertexSkip = index == std::numeric_limits<I>::max();
const auto data =
reinterpret_cast<const T*>(VertexLoaderManager::cached_arraybases[ARRAY_POSITION] +
(index * g_main_cp_state.array_strides[ARRAY_POSITION]));
reinterpret_cast<const T*>(VertexLoaderManager::cached_arraybases[CPArray::Position] +
(index * g_main_cp_state.array_strides[CPArray::Position]));
const auto scale = loader->m_posScale;
DataReader dst(g_vertex_manager_write_ptr, nullptr);

View File

@ -55,8 +55,8 @@ void TexCoord_ReadIndex(VertexLoader* loader)
const auto index = DataRead<I>();
const auto data = reinterpret_cast<const T*>(
VertexLoaderManager::cached_arraybases[ARRAY_TEXCOORD0 + loader->m_tcIndex] +
(index * g_main_cp_state.array_strides[ARRAY_TEXCOORD0 + loader->m_tcIndex]));
VertexLoaderManager::cached_arraybases[CPArray::TexCoord0 + loader->m_tcIndex] +
(index * g_main_cp_state.array_strides[CPArray::TexCoord0 + loader->m_tcIndex]));
const auto scale = loader->m_tcScale[loader->m_tcIndex];
DataReader dst(g_vertex_manager_write_ptr, nullptr);

View File

@ -459,5 +459,5 @@ static_assert(sizeof(XFMemory) == sizeof(u32) * 0x1058);
extern XFMemory xfmem;
void LoadXFReg(u32 transferSize, u32 address, DataReader src);
void LoadIndexedXF(u32 val, int array);
void PreprocessIndexedXF(u32 val, int refarray);
void LoadIndexedXF(CPArray array, u32 val);
void PreprocessIndexedXF(CPArray array, u32 val);

View File

@ -274,7 +274,7 @@ constexpr std::tuple<u32, u32, u32> ExtractIndexedXF(u32 val)
}
// TODO - verify that it is correct. Seems to work, though.
void LoadIndexedXF(u32 val, int refarray)
void LoadIndexedXF(CPArray array, u32 val)
{
const auto [index, address, size] = ExtractIndexedXF(val);
// load stuff from array to address in xf mem
@ -287,8 +287,8 @@ void LoadIndexedXF(u32 val, int refarray)
}
else
{
newData = (u32*)Memory::GetPointer(g_main_cp_state.array_bases[refarray] +
g_main_cp_state.array_strides[refarray] * index);
newData = (u32*)Memory::GetPointer(g_main_cp_state.array_bases[array] +
g_main_cp_state.array_strides[array] * index);
}
bool changed = false;
for (u32 i = 0; i < size; ++i)
@ -307,12 +307,12 @@ void LoadIndexedXF(u32 val, int refarray)
}
}
void PreprocessIndexedXF(u32 val, int refarray)
void PreprocessIndexedXF(CPArray array, u32 val)
{
const auto [index, address, size] = ExtractIndexedXF(val);
const u8* new_data = Memory::GetPointer(g_preprocess_cp_state.array_bases[refarray] +
g_preprocess_cp_state.array_strides[refarray] * index);
const u8* new_data = Memory::GetPointer(g_preprocess_cp_state.array_bases[array] +
g_preprocess_cp_state.array_strides[array] * index);
const size_t buf_size = size * sizeof(u32);
Fifo::PushFifoAuxBuffer(new_data, buf_size);
@ -655,7 +655,7 @@ std::pair<std::string, std::string> GetXFTransferInfo(const u8* data)
return std::make_pair(fmt::to_string(name), fmt::to_string(desc));
}
std::pair<std::string, std::string> GetXFIndexedLoadInfo(u8 array, u32 value)
std::pair<std::string, std::string> GetXFIndexedLoadInfo(CPArray array, u32 value)
{
const auto [index, address, size] = ExtractIndexedXF(value);

View File

@ -12,4 +12,4 @@ std::pair<std::string, std::string> GetXFRegInfo(u32 address, u32 value);
std::string GetXFMemName(u32 address);
std::string GetXFMemDescription(u32 address, u32 value);
std::pair<std::string, std::string> GetXFTransferInfo(const u8* data);
std::pair<std::string, std::string> GetXFIndexedLoadInfo(u8 array, u32 value);
std::pair<std::string, std::string> GetXFIndexedLoadInfo(CPArray array, u32 value);

View File

@ -174,8 +174,8 @@ TEST_P(VertexLoaderParamTest, PositionAll)
Input<u8>(i);
else
Input<u16>(i);
VertexLoaderManager::cached_arraybases[ARRAY_POSITION] = m_src.GetPointer();
g_main_cp_state.array_strides[ARRAY_POSITION] = elem_count * elem_size;
VertexLoaderManager::cached_arraybases[CPArray::Position] = m_src.GetPointer();
g_main_cp_state.array_strides[CPArray::Position] = elem_count * elem_size;
}
CreateAndCheckSizes(input_size, elem_count * sizeof(float));
for (float value : values)
@ -243,8 +243,8 @@ TEST_F(VertexLoaderTest, PositionIndex16FloatXY)
CreateAndCheckSizes(sizeof(u16), 2 * sizeof(float));
Input<u16>(1);
Input<u16>(0);
VertexLoaderManager::cached_arraybases[ARRAY_POSITION] = m_src.GetPointer();
g_main_cp_state.array_strides[ARRAY_POSITION] = sizeof(float); // ;)
VertexLoaderManager::cached_arraybases[CPArray::Position] = m_src.GetPointer();
g_main_cp_state.array_strides[CPArray::Position] = sizeof(float); // ;)
Input(1.f);
Input(2.f);
Input(3.f);
@ -357,8 +357,8 @@ TEST_F(VertexLoaderTest, LargeFloatVertexSpeed)
for (int i = 0; i < NUM_VERTEX_COMPONENT_ARRAYS; i++)
{
VertexLoaderManager::cached_arraybases[i] = m_src.GetPointer();
g_main_cp_state.array_strides[i] = 129;
VertexLoaderManager::cached_arraybases[static_cast<CPArray>(i)] = m_src.GetPointer();
g_main_cp_state.array_strides[static_cast<CPArray>(i)] = 129;
}
// This test is only done 100x in a row since it's ~20x slower using the