mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
Merge pull request #9540 from Pokechu22/better-fifo-analyzer-part-2
Fifo analyzer quality of life improvements
This commit is contained in:
@ -63,6 +63,11 @@ enum
|
||||
ARRAY_TEXCOORD0 = 4,
|
||||
NUM_TEXCOORD_ARRAYS = 8,
|
||||
|
||||
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
|
||||
|
||||
// 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,
|
||||
@ -317,10 +322,10 @@ union UVAT_group0
|
||||
// 21:29
|
||||
BitField<21, 1, TexComponentCount> Tex0CoordElements;
|
||||
BitField<22, 3, ComponentFormat> Tex0CoordFormat;
|
||||
BitField<25, 5, u32> Tex0Frac;
|
||||
BitField<25, 5, u8, u32> Tex0Frac;
|
||||
// 30:31
|
||||
BitField<30, 1, u32> ByteDequant;
|
||||
BitField<31, 1, u32> NormalIndex3;
|
||||
BitField<30, 1, bool, u32> ByteDequant;
|
||||
BitField<31, 1, bool, u32> NormalIndex3;
|
||||
};
|
||||
template <>
|
||||
struct fmt::formatter<UVAT_group0>
|
||||
@ -363,20 +368,20 @@ union UVAT_group1
|
||||
// 0:8
|
||||
BitField<0, 1, TexComponentCount> Tex1CoordElements;
|
||||
BitField<1, 3, ComponentFormat> Tex1CoordFormat;
|
||||
BitField<4, 5, u32> Tex1Frac;
|
||||
BitField<4, 5, u8, u32> Tex1Frac;
|
||||
// 9:17
|
||||
BitField<9, 1, TexComponentCount> Tex2CoordElements;
|
||||
BitField<10, 3, ComponentFormat> Tex2CoordFormat;
|
||||
BitField<13, 5, u32> Tex2Frac;
|
||||
BitField<13, 5, u8, u32> Tex2Frac;
|
||||
// 18:26
|
||||
BitField<18, 1, TexComponentCount> Tex3CoordElements;
|
||||
BitField<19, 3, ComponentFormat> Tex3CoordFormat;
|
||||
BitField<22, 5, u32> Tex3Frac;
|
||||
BitField<22, 5, u8, u32> Tex3Frac;
|
||||
// 27:30
|
||||
BitField<27, 1, TexComponentCount> Tex4CoordElements;
|
||||
BitField<28, 3, ComponentFormat> Tex4CoordFormat;
|
||||
// 31
|
||||
BitField<31, 1, u32> VCacheEnhance;
|
||||
BitField<31, 1, bool, u32> VCacheEnhance;
|
||||
};
|
||||
template <>
|
||||
struct fmt::formatter<UVAT_group1>
|
||||
@ -410,19 +415,19 @@ union UVAT_group2
|
||||
{
|
||||
u32 Hex;
|
||||
// 0:4
|
||||
BitField<0, 5, u32> Tex4Frac;
|
||||
BitField<0, 5, u8, u32> Tex4Frac;
|
||||
// 5:13
|
||||
BitField<5, 1, TexComponentCount> Tex5CoordElements;
|
||||
BitField<6, 3, ComponentFormat> Tex5CoordFormat;
|
||||
BitField<9, 5, u32> Tex5Frac;
|
||||
BitField<9, 5, u8, u32> Tex5Frac;
|
||||
// 14:22
|
||||
BitField<14, 1, TexComponentCount> Tex6CoordElements;
|
||||
BitField<15, 3, ComponentFormat> Tex6CoordFormat;
|
||||
BitField<18, 5, u32> Tex6Frac;
|
||||
BitField<18, 5, u8, u32> Tex6Frac;
|
||||
// 23:31
|
||||
BitField<23, 1, TexComponentCount> Tex7CoordElements;
|
||||
BitField<24, 3, ComponentFormat> Tex7CoordFormat;
|
||||
BitField<27, 5, u32> Tex7Frac;
|
||||
BitField<27, 5, u8, u32> Tex7Frac;
|
||||
};
|
||||
template <>
|
||||
struct fmt::formatter<UVAT_group2>
|
||||
@ -450,30 +455,123 @@ struct fmt::formatter<UVAT_group2>
|
||||
}
|
||||
};
|
||||
|
||||
struct ColorAttr
|
||||
struct VAT
|
||||
{
|
||||
ColorComponentCount Elements;
|
||||
ColorFormat Comp;
|
||||
};
|
||||
UVAT_group0 g0;
|
||||
UVAT_group1 g1;
|
||||
UVAT_group2 g2;
|
||||
|
||||
struct TexAttr
|
||||
{
|
||||
TexComponentCount Elements;
|
||||
ComponentFormat Format;
|
||||
u8 Frac;
|
||||
constexpr ColorComponentCount GetColorElements(size_t idx) const
|
||||
{
|
||||
switch (idx)
|
||||
{
|
||||
case 0:
|
||||
return g0.Color0Elements;
|
||||
case 1:
|
||||
return g0.Color1Elements;
|
||||
default:
|
||||
PanicAlertFmt("Invalid color index {}", idx);
|
||||
return ColorComponentCount::RGB;
|
||||
}
|
||||
}
|
||||
constexpr ColorFormat GetColorFormat(size_t idx) const
|
||||
{
|
||||
switch (idx)
|
||||
{
|
||||
case 0:
|
||||
return g0.Color0Comp;
|
||||
case 1:
|
||||
return g0.Color1Comp;
|
||||
default:
|
||||
PanicAlertFmt("Invalid color index {}", idx);
|
||||
return ColorFormat::RGB565;
|
||||
}
|
||||
}
|
||||
constexpr TexComponentCount GetTexElements(size_t idx) const
|
||||
{
|
||||
switch (idx)
|
||||
{
|
||||
case 0:
|
||||
return g0.Tex0CoordElements;
|
||||
case 1:
|
||||
return g1.Tex1CoordElements;
|
||||
case 2:
|
||||
return g1.Tex2CoordElements;
|
||||
case 3:
|
||||
return g1.Tex3CoordElements;
|
||||
case 4:
|
||||
return g1.Tex4CoordElements;
|
||||
case 5:
|
||||
return g2.Tex5CoordElements;
|
||||
case 6:
|
||||
return g2.Tex6CoordElements;
|
||||
case 7:
|
||||
return g2.Tex7CoordElements;
|
||||
default:
|
||||
PanicAlertFmt("Invalid tex coord index {}", idx);
|
||||
return TexComponentCount::S;
|
||||
}
|
||||
}
|
||||
constexpr ComponentFormat GetTexFormat(size_t idx) const
|
||||
{
|
||||
switch (idx)
|
||||
{
|
||||
case 0:
|
||||
return g0.Tex0CoordFormat;
|
||||
case 1:
|
||||
return g1.Tex1CoordFormat;
|
||||
case 2:
|
||||
return g1.Tex2CoordFormat;
|
||||
case 3:
|
||||
return g1.Tex3CoordFormat;
|
||||
case 4:
|
||||
return g1.Tex4CoordFormat;
|
||||
case 5:
|
||||
return g2.Tex5CoordFormat;
|
||||
case 6:
|
||||
return g2.Tex6CoordFormat;
|
||||
case 7:
|
||||
return g2.Tex7CoordFormat;
|
||||
default:
|
||||
PanicAlertFmt("Invalid tex coord index {}", idx);
|
||||
return ComponentFormat::UByte;
|
||||
}
|
||||
}
|
||||
constexpr u8 GetTexFrac(size_t idx) const
|
||||
{
|
||||
switch (idx)
|
||||
{
|
||||
case 0:
|
||||
return g0.Tex0Frac;
|
||||
case 1:
|
||||
return g1.Tex1Frac;
|
||||
case 2:
|
||||
return g1.Tex2Frac;
|
||||
case 3:
|
||||
return g1.Tex3Frac;
|
||||
case 4:
|
||||
return g2.Tex4Frac;
|
||||
case 5:
|
||||
return g2.Tex5Frac;
|
||||
case 6:
|
||||
return g2.Tex6Frac;
|
||||
case 7:
|
||||
return g2.Tex7Frac;
|
||||
default:
|
||||
PanicAlertFmt("Invalid tex coord index {}", idx);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct TVtxAttr
|
||||
template <>
|
||||
struct fmt::formatter<VAT>
|
||||
{
|
||||
CoordComponentCount PosElements;
|
||||
ComponentFormat PosFormat;
|
||||
u8 PosFrac;
|
||||
NormalComponentCount NormalElements;
|
||||
ComponentFormat NormalFormat;
|
||||
ColorAttr color[2];
|
||||
TexAttr texCoord[8];
|
||||
bool ByteDequant;
|
||||
u8 NormalIndex3;
|
||||
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
|
||||
template <typename FormatContext>
|
||||
auto format(const VAT& vat, FormatContext& ctx)
|
||||
{
|
||||
return format_to(ctx.out(), "{}\n{}\n{}", vat.g0, vat.g1, vat.g2);
|
||||
}
|
||||
};
|
||||
|
||||
// Matrix indices
|
||||
@ -518,13 +616,6 @@ struct fmt::formatter<TMatrixIndexB>
|
||||
}
|
||||
};
|
||||
|
||||
struct VAT
|
||||
{
|
||||
UVAT_group0 g0;
|
||||
UVAT_group1 g1;
|
||||
UVAT_group2 g2;
|
||||
};
|
||||
|
||||
class VertexLoaderBase;
|
||||
|
||||
// STATE_TO_SAVE
|
||||
|
@ -72,21 +72,16 @@ VertexLoader::VertexLoader(const TVtxDesc& vtx_desc, const VAT& vtx_attr)
|
||||
CompileVertexTranslator();
|
||||
|
||||
// generate frac factors
|
||||
m_posScale = 1.0f / (1U << m_VtxAttr.PosFrac);
|
||||
for (int i = 0; i < 8; i++)
|
||||
m_tcScale[i] = 1.0f / (1U << m_VtxAttr.texCoord[i].Frac);
|
||||
m_posScale = 1.0f / (1U << m_VtxAttr.g0.PosFrac);
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
m_tcScale[i] = 1.0f / (1U << m_VtxAttr.GetTexFrac(i));
|
||||
}
|
||||
|
||||
void VertexLoader::CompileVertexTranslator()
|
||||
{
|
||||
m_VertexSize = 0;
|
||||
const TVtxAttr& vtx_attr = m_VtxAttr;
|
||||
|
||||
// Reset pipeline
|
||||
m_numPipelineStages = 0;
|
||||
|
||||
u32 components = 0;
|
||||
|
||||
// Position in pc vertex format.
|
||||
int nat_offset = 0;
|
||||
|
||||
@ -94,72 +89,25 @@ void VertexLoader::CompileVertexTranslator()
|
||||
if (m_VtxDesc.low.PosMatIdx)
|
||||
{
|
||||
WriteCall(PosMtx_ReadDirect_UByte);
|
||||
components |= VB_HAS_POSMTXIDX;
|
||||
m_native_vtx_decl.posmtx.components = 4;
|
||||
m_native_vtx_decl.posmtx.enable = true;
|
||||
m_native_vtx_decl.posmtx.offset = nat_offset;
|
||||
m_native_vtx_decl.posmtx.type = VAR_UNSIGNED_BYTE;
|
||||
m_native_vtx_decl.posmtx.integer = true;
|
||||
nat_offset += 4;
|
||||
m_VertexSize += 1;
|
||||
}
|
||||
|
||||
if (m_VtxDesc.low.Tex0MatIdx)
|
||||
for (auto texmtxidx : m_VtxDesc.low.TexMatIdx)
|
||||
{
|
||||
m_VertexSize += 1;
|
||||
components |= VB_HAS_TEXMTXIDX0;
|
||||
WriteCall(TexMtx_ReadDirect_UByte);
|
||||
}
|
||||
if (m_VtxDesc.low.Tex1MatIdx)
|
||||
{
|
||||
m_VertexSize += 1;
|
||||
components |= VB_HAS_TEXMTXIDX1;
|
||||
WriteCall(TexMtx_ReadDirect_UByte);
|
||||
}
|
||||
if (m_VtxDesc.low.Tex2MatIdx)
|
||||
{
|
||||
m_VertexSize += 1;
|
||||
components |= VB_HAS_TEXMTXIDX2;
|
||||
WriteCall(TexMtx_ReadDirect_UByte);
|
||||
}
|
||||
if (m_VtxDesc.low.Tex3MatIdx)
|
||||
{
|
||||
m_VertexSize += 1;
|
||||
components |= VB_HAS_TEXMTXIDX3;
|
||||
WriteCall(TexMtx_ReadDirect_UByte);
|
||||
}
|
||||
if (m_VtxDesc.low.Tex4MatIdx)
|
||||
{
|
||||
m_VertexSize += 1;
|
||||
components |= VB_HAS_TEXMTXIDX4;
|
||||
WriteCall(TexMtx_ReadDirect_UByte);
|
||||
}
|
||||
if (m_VtxDesc.low.Tex5MatIdx)
|
||||
{
|
||||
m_VertexSize += 1;
|
||||
components |= VB_HAS_TEXMTXIDX5;
|
||||
WriteCall(TexMtx_ReadDirect_UByte);
|
||||
}
|
||||
if (m_VtxDesc.low.Tex6MatIdx)
|
||||
{
|
||||
m_VertexSize += 1;
|
||||
components |= VB_HAS_TEXMTXIDX6;
|
||||
WriteCall(TexMtx_ReadDirect_UByte);
|
||||
}
|
||||
if (m_VtxDesc.low.Tex7MatIdx)
|
||||
{
|
||||
m_VertexSize += 1;
|
||||
components |= VB_HAS_TEXMTXIDX7;
|
||||
WriteCall(TexMtx_ReadDirect_UByte);
|
||||
if (texmtxidx)
|
||||
WriteCall(TexMtx_ReadDirect_UByte);
|
||||
}
|
||||
|
||||
// Write vertex position loader
|
||||
WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.low.Position, m_VtxAttr.PosFormat,
|
||||
m_VtxAttr.PosElements));
|
||||
WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.low.Position, m_VtxAttr.g0.PosFormat,
|
||||
m_VtxAttr.g0.PosElements));
|
||||
|
||||
m_VertexSize += VertexLoader_Position::GetSize(m_VtxDesc.low.Position, m_VtxAttr.PosFormat,
|
||||
m_VtxAttr.PosElements);
|
||||
int pos_elements = m_VtxAttr.PosElements == CoordComponentCount::XY ? 2 : 3;
|
||||
int pos_elements = m_VtxAttr.g0.PosElements == CoordComponentCount::XY ? 2 : 3;
|
||||
m_native_vtx_decl.position.components = pos_elements;
|
||||
m_native_vtx_decl.position.enable = true;
|
||||
m_native_vtx_decl.position.offset = nat_offset;
|
||||
@ -170,22 +118,19 @@ void VertexLoader::CompileVertexTranslator()
|
||||
// Normals
|
||||
if (m_VtxDesc.low.Normal != VertexComponentFormat::NotPresent)
|
||||
{
|
||||
m_VertexSize += VertexLoader_Normal::GetSize(m_VtxDesc.low.Normal, m_VtxAttr.NormalFormat,
|
||||
m_VtxAttr.NormalElements, m_VtxAttr.NormalIndex3);
|
||||
|
||||
TPipelineFunction pFunc =
|
||||
VertexLoader_Normal::GetFunction(m_VtxDesc.low.Normal, m_VtxAttr.NormalFormat,
|
||||
m_VtxAttr.NormalElements, m_VtxAttr.NormalIndex3);
|
||||
VertexLoader_Normal::GetFunction(m_VtxDesc.low.Normal, m_VtxAttr.g0.NormalFormat,
|
||||
m_VtxAttr.g0.NormalElements, m_VtxAttr.g0.NormalIndex3);
|
||||
|
||||
if (pFunc == nullptr)
|
||||
{
|
||||
PanicAlertFmt("VertexLoader_Normal::GetFunction({} {} {} {}) returned zero!",
|
||||
m_VtxDesc.low.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements,
|
||||
m_VtxAttr.NormalIndex3);
|
||||
m_VtxDesc.low.Normal, m_VtxAttr.g0.NormalFormat, m_VtxAttr.g0.NormalElements,
|
||||
m_VtxAttr.g0.NormalIndex3);
|
||||
}
|
||||
WriteCall(pFunc);
|
||||
|
||||
for (int i = 0; i < (vtx_attr.NormalElements == NormalComponentCount::NBT ? 3 : 1); i++)
|
||||
for (int i = 0; i < (m_VtxAttr.g0.NormalElements == NormalComponentCount::NBT ? 3 : 1); i++)
|
||||
{
|
||||
m_native_vtx_decl.normals[i].components = 3;
|
||||
m_native_vtx_decl.normals[i].enable = true;
|
||||
@ -194,10 +139,6 @@ void VertexLoader::CompileVertexTranslator()
|
||||
m_native_vtx_decl.normals[i].integer = false;
|
||||
nat_offset += 12;
|
||||
}
|
||||
|
||||
components |= VB_HAS_NRM0;
|
||||
if (m_VtxAttr.NormalElements == NormalComponentCount::NBT)
|
||||
components |= VB_HAS_NRM1 | VB_HAS_NRM2;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_VtxDesc.low.Color.Size(); i++)
|
||||
@ -205,101 +146,17 @@ void VertexLoader::CompileVertexTranslator()
|
||||
m_native_vtx_decl.colors[i].components = 4;
|
||||
m_native_vtx_decl.colors[i].type = VAR_UNSIGNED_BYTE;
|
||||
m_native_vtx_decl.colors[i].integer = false;
|
||||
switch (m_VtxDesc.low.Color[i])
|
||||
{
|
||||
case VertexComponentFormat::NotPresent:
|
||||
break;
|
||||
case VertexComponentFormat::Direct:
|
||||
switch (m_VtxAttr.color[i].Comp)
|
||||
{
|
||||
case ColorFormat::RGB565:
|
||||
m_VertexSize += 2;
|
||||
WriteCall(Color_ReadDirect_16b_565);
|
||||
break;
|
||||
case ColorFormat::RGB888:
|
||||
m_VertexSize += 3;
|
||||
WriteCall(Color_ReadDirect_24b_888);
|
||||
break;
|
||||
case ColorFormat::RGB888x:
|
||||
m_VertexSize += 4;
|
||||
WriteCall(Color_ReadDirect_32b_888x);
|
||||
break;
|
||||
case ColorFormat::RGBA4444:
|
||||
m_VertexSize += 2;
|
||||
WriteCall(Color_ReadDirect_16b_4444);
|
||||
break;
|
||||
case ColorFormat::RGBA6666:
|
||||
m_VertexSize += 3;
|
||||
WriteCall(Color_ReadDirect_24b_6666);
|
||||
break;
|
||||
case ColorFormat::RGBA8888:
|
||||
m_VertexSize += 4;
|
||||
WriteCall(Color_ReadDirect_32b_8888);
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case VertexComponentFormat::Index8:
|
||||
m_VertexSize += 1;
|
||||
switch (m_VtxAttr.color[i].Comp)
|
||||
{
|
||||
case ColorFormat::RGB565:
|
||||
WriteCall(Color_ReadIndex8_16b_565);
|
||||
break;
|
||||
case ColorFormat::RGB888:
|
||||
WriteCall(Color_ReadIndex8_24b_888);
|
||||
break;
|
||||
case ColorFormat::RGB888x:
|
||||
WriteCall(Color_ReadIndex8_32b_888x);
|
||||
break;
|
||||
case ColorFormat::RGBA4444:
|
||||
WriteCall(Color_ReadIndex8_16b_4444);
|
||||
break;
|
||||
case ColorFormat::RGBA6666:
|
||||
WriteCall(Color_ReadIndex8_24b_6666);
|
||||
break;
|
||||
case ColorFormat::RGBA8888:
|
||||
WriteCall(Color_ReadIndex8_32b_8888);
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case VertexComponentFormat::Index16:
|
||||
m_VertexSize += 2;
|
||||
switch (m_VtxAttr.color[i].Comp)
|
||||
{
|
||||
case ColorFormat::RGB565:
|
||||
WriteCall(Color_ReadIndex16_16b_565);
|
||||
break;
|
||||
case ColorFormat::RGB888:
|
||||
WriteCall(Color_ReadIndex16_24b_888);
|
||||
break;
|
||||
case ColorFormat::RGB888x:
|
||||
WriteCall(Color_ReadIndex16_32b_888x);
|
||||
break;
|
||||
case ColorFormat::RGBA4444:
|
||||
WriteCall(Color_ReadIndex16_16b_4444);
|
||||
break;
|
||||
case ColorFormat::RGBA6666:
|
||||
WriteCall(Color_ReadIndex16_24b_6666);
|
||||
break;
|
||||
case ColorFormat::RGBA8888:
|
||||
WriteCall(Color_ReadIndex16_32b_8888);
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Common for the three bottom cases
|
||||
|
||||
TPipelineFunction pFunc =
|
||||
VertexLoader_Color::GetFunction(m_VtxDesc.low.Color[i], m_VtxAttr.GetColorFormat(i));
|
||||
|
||||
if (pFunc != nullptr)
|
||||
WriteCall(pFunc);
|
||||
else
|
||||
ASSERT(m_VtxDesc.low.Color[i] == VertexComponentFormat::NotPresent);
|
||||
|
||||
if (m_VtxDesc.low.Color[i] != VertexComponentFormat::NotPresent)
|
||||
{
|
||||
components |= VB_HAS_COL0 << i;
|
||||
m_native_vtx_decl.colors[i].offset = nat_offset;
|
||||
m_native_vtx_decl.colors[i].enable = true;
|
||||
nat_offset += 4;
|
||||
@ -314,8 +171,8 @@ void VertexLoader::CompileVertexTranslator()
|
||||
m_native_vtx_decl.texcoords[i].integer = false;
|
||||
|
||||
const auto tc = m_VtxDesc.high.TexCoord[i].Value();
|
||||
const auto format = m_VtxAttr.texCoord[i].Format;
|
||||
const auto elements = m_VtxAttr.texCoord[i].Elements;
|
||||
const auto format = m_VtxAttr.GetTexFormat(i);
|
||||
const auto elements = m_VtxAttr.GetTexElements(i);
|
||||
|
||||
if (tc != VertexComponentFormat::NotPresent)
|
||||
{
|
||||
@ -326,26 +183,21 @@ void VertexLoader::CompileVertexTranslator()
|
||||
ASSERT_MSG(VIDEO, elements == TexComponentCount::S || elements == TexComponentCount::ST,
|
||||
"Invalid number of texture coordinates elements!\n(elements = %d)", (u32)elements);
|
||||
|
||||
components |= VB_HAS_UV0 << i;
|
||||
WriteCall(VertexLoader_TextCoord::GetFunction(tc, format, elements));
|
||||
m_VertexSize += VertexLoader_TextCoord::GetSize(tc, format, elements);
|
||||
}
|
||||
|
||||
if (components & (VB_HAS_TEXMTXIDX0 << i))
|
||||
if (m_VtxDesc.low.TexMatIdx[i])
|
||||
{
|
||||
m_native_vtx_decl.texcoords[i].enable = true;
|
||||
m_native_vtx_decl.texcoords[i].components = 3;
|
||||
nat_offset += 12;
|
||||
if (tc != VertexComponentFormat::NotPresent)
|
||||
{
|
||||
// if texmtx is included, texcoord will always be 3 floats, z will be the texmtx index
|
||||
m_native_vtx_decl.texcoords[i].components = 3;
|
||||
nat_offset += 12;
|
||||
WriteCall(m_VtxAttr.texCoord[i].Elements == TexComponentCount::ST ? TexMtx_Write_Float :
|
||||
TexMtx_Write_Float2);
|
||||
WriteCall(elements == TexComponentCount::ST ? TexMtx_Write_Float : TexMtx_Write_Float2);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_native_vtx_decl.texcoords[i].components = 3;
|
||||
nat_offset += 12;
|
||||
WriteCall(TexMtx_Write_Float3);
|
||||
}
|
||||
}
|
||||
@ -354,26 +206,29 @@ void VertexLoader::CompileVertexTranslator()
|
||||
if (tc != VertexComponentFormat::NotPresent)
|
||||
{
|
||||
m_native_vtx_decl.texcoords[i].enable = true;
|
||||
m_native_vtx_decl.texcoords[i].components =
|
||||
vtx_attr.texCoord[i].Elements == TexComponentCount::ST ? 2 : 1;
|
||||
nat_offset += 4 * (vtx_attr.texCoord[i].Elements == TexComponentCount::ST ? 2 : 1);
|
||||
m_native_vtx_decl.texcoords[i].components = elements == TexComponentCount::ST ? 2 : 1;
|
||||
nat_offset += 4 * (elements == TexComponentCount::ST ? 2 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (tc == VertexComponentFormat::NotPresent)
|
||||
{
|
||||
// if there's more tex coords later, have to write a dummy call
|
||||
size_t j = i + 1;
|
||||
for (; j < m_VtxDesc.high.TexCoord.Size(); ++j)
|
||||
bool has_more = false;
|
||||
for (size_t j = 0; j < m_VtxDesc.high.TexCoord.Size(); ++j)
|
||||
{
|
||||
if (m_VtxDesc.high.TexCoord[j] != VertexComponentFormat::NotPresent)
|
||||
{
|
||||
has_more = true;
|
||||
WriteCall(VertexLoader_TextCoord::GetDummyFunction()); // important to get indices right!
|
||||
break;
|
||||
}
|
||||
else if (m_VtxDesc.low.TexMatIdx[i])
|
||||
{
|
||||
has_more = true;
|
||||
}
|
||||
}
|
||||
// tricky!
|
||||
if (j == 8 && !((components & VB_HAS_TEXMTXIDXALL) & (VB_HAS_TEXMTXIDXALL << (i + 1))))
|
||||
if (!has_more)
|
||||
{
|
||||
// no more tex coords and tex matrices, so exit loop
|
||||
break;
|
||||
@ -387,7 +242,6 @@ void VertexLoader::CompileVertexTranslator()
|
||||
WriteCall(SkipVertex);
|
||||
}
|
||||
|
||||
m_native_components = components;
|
||||
m_native_vtx_decl.stride = nat_offset;
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,6 @@ public:
|
||||
VertexLoader(const TVtxDesc& vtx_desc, const VAT& vtx_attr);
|
||||
|
||||
int RunVertices(DataReader src, DataReader dst, int count) override;
|
||||
std::string GetName() const override { return "OldLoader"; }
|
||||
bool IsInitialized() override { return true; } // This vertex loader supports all formats
|
||||
// They are used for the communication with the loader functions
|
||||
float m_posScale;
|
||||
float m_tcScale[8];
|
||||
|
@ -25,6 +25,20 @@ constexpr ARM64Reg stride_reg = ARM64Reg::X11;
|
||||
constexpr ARM64Reg arraybase_reg = ARM64Reg::X10;
|
||||
constexpr ARM64Reg scale_reg = ARM64Reg::X9;
|
||||
|
||||
static constexpr int GetLoadSize(int load_bytes)
|
||||
{
|
||||
if (load_bytes == 1)
|
||||
return 1;
|
||||
else if (load_bytes <= 2)
|
||||
return 2;
|
||||
else if (load_bytes <= 4)
|
||||
return 4;
|
||||
else if (load_bytes <= 8)
|
||||
return 8;
|
||||
else
|
||||
return 16;
|
||||
}
|
||||
|
||||
alignas(16) static const float scale_factors[] = {
|
||||
1.0 / (1ULL << 0), 1.0 / (1ULL << 1), 1.0 / (1ULL << 2), 1.0 / (1ULL << 3),
|
||||
1.0 / (1ULL << 4), 1.0 / (1ULL << 5), 1.0 / (1ULL << 6), 1.0 / (1ULL << 7),
|
||||
@ -39,9 +53,6 @@ alignas(16) static const float scale_factors[] = {
|
||||
VertexLoaderARM64::VertexLoaderARM64(const TVtxDesc& vtx_desc, const VAT& vtx_att)
|
||||
: VertexLoaderBase(vtx_desc, vtx_att), m_float_emit(this)
|
||||
{
|
||||
if (!IsInitialized())
|
||||
return;
|
||||
|
||||
AllocCodeSpace(4096);
|
||||
ClearCodeSpace();
|
||||
GenerateVertexLoader();
|
||||
@ -120,8 +131,7 @@ int VertexLoaderARM64::ReadVertex(VertexComponentFormat attribute, ComponentForm
|
||||
|
||||
int elem_size = GetElementSize(format);
|
||||
int load_bytes = elem_size * count_in;
|
||||
int load_size =
|
||||
load_bytes == 1 ? 1 : load_bytes <= 2 ? 2 : load_bytes <= 4 ? 4 : load_bytes <= 8 ? 8 : 16;
|
||||
int load_size = GetLoadSize(load_bytes);
|
||||
load_size <<= 3;
|
||||
elem_size <<= 3;
|
||||
|
||||
@ -380,10 +390,11 @@ void VertexLoaderARM64::GenerateVertexLoader()
|
||||
for (size_t i = 0; i < m_VtxDesc.high.TexCoord.Size(); i++)
|
||||
{
|
||||
has_tc |= m_VtxDesc.high.TexCoord[i] != VertexComponentFormat::NotPresent;
|
||||
has_tc_scale |= !!m_VtxAttr.texCoord[i].Frac;
|
||||
has_tc_scale |= (m_VtxAttr.GetTexFrac(i) != 0);
|
||||
}
|
||||
|
||||
bool need_scale = (m_VtxAttr.ByteDequant && m_VtxAttr.PosFrac) || (has_tc && has_tc_scale) ||
|
||||
bool need_scale = (m_VtxAttr.g0.ByteDequant && m_VtxAttr.g0.PosFrac) ||
|
||||
(has_tc && has_tc_scale) ||
|
||||
(m_VtxDesc.low.Normal != VertexComponentFormat::NotPresent);
|
||||
|
||||
AlignCode16();
|
||||
@ -412,7 +423,6 @@ void VertexLoaderARM64::GenerateVertexLoader()
|
||||
STR(IndexType::Unsigned, scratch1_reg, EncodeRegTo64(scratch2_reg), 0);
|
||||
SetJumpTarget(dont_store);
|
||||
|
||||
m_native_components |= VB_HAS_POSMTXIDX;
|
||||
m_native_vtx_decl.posmtx.components = 4;
|
||||
m_native_vtx_decl.posmtx.enable = true;
|
||||
m_native_vtx_decl.posmtx.offset = m_dst_ofs;
|
||||
@ -431,36 +441,33 @@ void VertexLoaderARM64::GenerateVertexLoader()
|
||||
|
||||
// Position
|
||||
{
|
||||
int elem_size = GetElementSize(m_VtxAttr.PosFormat);
|
||||
int pos_elements = m_VtxAttr.PosElements == CoordComponentCount::XY ? 2 : 3;
|
||||
int elem_size = GetElementSize(m_VtxAttr.g0.PosFormat);
|
||||
int pos_elements = m_VtxAttr.g0.PosElements == CoordComponentCount::XY ? 2 : 3;
|
||||
int load_bytes = elem_size * pos_elements;
|
||||
int load_size =
|
||||
load_bytes == 1 ? 1 : load_bytes <= 2 ? 2 : load_bytes <= 4 ? 4 : load_bytes <= 8 ? 8 : 16;
|
||||
int load_size = GetLoadSize(load_bytes);
|
||||
load_size <<= 3;
|
||||
|
||||
s32 offset = GetAddressImm(ARRAY_POSITION, m_VtxDesc.low.Position, EncodeRegTo64(scratch1_reg),
|
||||
load_size);
|
||||
ReadVertex(m_VtxDesc.low.Position, m_VtxAttr.PosFormat, pos_elements, pos_elements,
|
||||
m_VtxAttr.ByteDequant, m_VtxAttr.PosFrac, &m_native_vtx_decl.position, offset);
|
||||
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);
|
||||
}
|
||||
|
||||
if (m_VtxDesc.low.Normal != VertexComponentFormat::NotPresent)
|
||||
{
|
||||
static const u8 map[8] = {7, 6, 15, 14};
|
||||
const u8 scaling_exponent = map[u32(m_VtxAttr.NormalFormat)];
|
||||
const int limit = m_VtxAttr.NormalElements == NormalComponentCount::NBT ? 3 : 1;
|
||||
const u8 scaling_exponent = map[u32(m_VtxAttr.g0.NormalFormat.Value())];
|
||||
const int limit = m_VtxAttr.g0.NormalElements == NormalComponentCount::NBT ? 3 : 1;
|
||||
|
||||
s32 offset = -1;
|
||||
for (int i = 0; i < (m_VtxAttr.NormalElements == NormalComponentCount::NBT ? 3 : 1); i++)
|
||||
for (int i = 0; i < (m_VtxAttr.g0.NormalElements == NormalComponentCount::NBT ? 3 : 1); i++)
|
||||
{
|
||||
if (!i || m_VtxAttr.NormalIndex3)
|
||||
if (!i || m_VtxAttr.g0.NormalIndex3)
|
||||
{
|
||||
int elem_size = GetElementSize(m_VtxAttr.NormalFormat);
|
||||
int elem_size = GetElementSize(m_VtxAttr.g0.NormalFormat);
|
||||
|
||||
int load_bytes = elem_size * 3;
|
||||
int load_size = load_bytes == 1 ?
|
||||
1 :
|
||||
load_bytes <= 2 ? 2 : load_bytes <= 4 ? 4 : load_bytes <= 8 ? 8 : 16;
|
||||
int load_size = GetLoadSize(load_bytes);
|
||||
|
||||
offset = GetAddressImm(ARRAY_NORMAL, m_VtxDesc.low.Normal, EncodeRegTo64(scratch1_reg),
|
||||
load_size << 3);
|
||||
@ -470,7 +477,7 @@ void VertexLoaderARM64::GenerateVertexLoader()
|
||||
else
|
||||
offset += i * elem_size * 3;
|
||||
}
|
||||
int bytes_read = ReadVertex(m_VtxDesc.low.Normal, m_VtxAttr.NormalFormat, 3, 3, true,
|
||||
int bytes_read = ReadVertex(m_VtxDesc.low.Normal, m_VtxAttr.g0.NormalFormat, 3, 3, true,
|
||||
scaling_exponent, &m_native_vtx_decl.normals[i], offset);
|
||||
|
||||
if (offset == -1)
|
||||
@ -478,10 +485,6 @@ void VertexLoaderARM64::GenerateVertexLoader()
|
||||
else
|
||||
offset += bytes_read;
|
||||
}
|
||||
|
||||
m_native_components |= VB_HAS_NRM0;
|
||||
if (m_VtxAttr.NormalElements == NormalComponentCount::NBT)
|
||||
m_native_components |= VB_HAS_NRM1 | VB_HAS_NRM2;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_VtxDesc.low.Color.Size(); i++)
|
||||
@ -493,14 +496,13 @@ void VertexLoaderARM64::GenerateVertexLoader()
|
||||
if (m_VtxDesc.low.Color[i] != VertexComponentFormat::NotPresent)
|
||||
{
|
||||
u32 align = 4;
|
||||
if (m_VtxAttr.color[i].Comp == ColorFormat::RGB565 ||
|
||||
m_VtxAttr.color[i].Comp == ColorFormat::RGBA4444)
|
||||
if (m_VtxAttr.GetColorFormat(i) == ColorFormat::RGB565 ||
|
||||
m_VtxAttr.GetColorFormat(i) == ColorFormat::RGBA4444)
|
||||
align = 2;
|
||||
|
||||
s32 offset = GetAddressImm(ARRAY_COLOR0 + int(i), m_VtxDesc.low.Color[i],
|
||||
EncodeRegTo64(scratch1_reg), align);
|
||||
ReadColor(m_VtxDesc.low.Color[i], m_VtxAttr.color[i].Comp, offset);
|
||||
m_native_components |= VB_HAS_COL0 << i;
|
||||
ReadColor(m_VtxDesc.low.Color[i], m_VtxAttr.GetColorFormat(i), offset);
|
||||
m_native_vtx_decl.colors[i].components = 4;
|
||||
m_native_vtx_decl.colors[i].enable = true;
|
||||
m_native_vtx_decl.colors[i].offset = m_dst_ofs;
|
||||
@ -516,28 +518,23 @@ void VertexLoaderARM64::GenerateVertexLoader()
|
||||
m_native_vtx_decl.texcoords[i].type = VAR_FLOAT;
|
||||
m_native_vtx_decl.texcoords[i].integer = false;
|
||||
|
||||
int elements = m_VtxAttr.texCoord[i].Elements == TexComponentCount::S ? 1 : 2;
|
||||
int elements = m_VtxAttr.GetTexElements(i) == TexComponentCount::S ? 1 : 2;
|
||||
if (m_VtxDesc.high.TexCoord[i] != VertexComponentFormat::NotPresent)
|
||||
{
|
||||
m_native_components |= VB_HAS_UV0 << i;
|
||||
|
||||
int elem_size = GetElementSize(m_VtxAttr.texCoord[i].Format);
|
||||
int elem_size = GetElementSize(m_VtxAttr.GetTexFormat(i));
|
||||
int load_bytes = elem_size * (elements + 2);
|
||||
int load_size = load_bytes == 1 ?
|
||||
1 :
|
||||
load_bytes <= 2 ? 2 : load_bytes <= 4 ? 4 : load_bytes <= 8 ? 8 : 16;
|
||||
int load_size = GetLoadSize(load_bytes);
|
||||
load_size <<= 3;
|
||||
|
||||
s32 offset = GetAddressImm(ARRAY_TEXCOORD0 + int(i), m_VtxDesc.high.TexCoord[i],
|
||||
EncodeRegTo64(scratch1_reg), load_size);
|
||||
u8 scaling_exponent = m_VtxAttr.texCoord[i].Frac;
|
||||
ReadVertex(m_VtxDesc.high.TexCoord[i], m_VtxAttr.texCoord[i].Format, elements,
|
||||
m_VtxDesc.low.TexMatIdx[i] ? 2 : elements, m_VtxAttr.ByteDequant, scaling_exponent,
|
||||
&m_native_vtx_decl.texcoords[i], offset);
|
||||
u8 scaling_exponent = m_VtxAttr.GetTexFrac(i);
|
||||
ReadVertex(m_VtxDesc.high.TexCoord[i], m_VtxAttr.GetTexFormat(i), elements,
|
||||
m_VtxDesc.low.TexMatIdx[i] ? 2 : elements, m_VtxAttr.g0.ByteDequant,
|
||||
scaling_exponent, &m_native_vtx_decl.texcoords[i], offset);
|
||||
}
|
||||
if (m_VtxDesc.low.TexMatIdx[i])
|
||||
{
|
||||
m_native_components |= VB_HAS_TEXMTXIDX0 << i;
|
||||
m_native_vtx_decl.texcoords[i].components = 3;
|
||||
m_native_vtx_decl.texcoords[i].enable = true;
|
||||
m_native_vtx_decl.texcoords[i].type = VAR_FLOAT;
|
||||
@ -603,7 +600,7 @@ void VertexLoaderARM64::GenerateVertexLoader()
|
||||
|
||||
FlushIcache();
|
||||
|
||||
m_VertexSize = m_src_ofs;
|
||||
ASSERT(m_vertex_size == m_src_ofs);
|
||||
m_native_vtx_decl.stride = m_dst_ofs;
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,6 @@ public:
|
||||
VertexLoaderARM64(const TVtxDesc& vtx_desc, const VAT& vtx_att);
|
||||
|
||||
protected:
|
||||
std::string GetName() const override { return "VertexLoaderARM64"; }
|
||||
bool IsInitialized() override { return true; }
|
||||
int RunVertices(DataReader src, DataReader dst, int count) override;
|
||||
|
||||
private:
|
||||
|
@ -19,6 +19,10 @@
|
||||
|
||||
#include "VideoCommon/DataReader.h"
|
||||
#include "VideoCommon/VertexLoader.h"
|
||||
#include "VideoCommon/VertexLoader_Color.h"
|
||||
#include "VideoCommon/VertexLoader_Normal.h"
|
||||
#include "VideoCommon/VertexLoader_Position.h"
|
||||
#include "VideoCommon/VertexLoader_TextCoord.h"
|
||||
|
||||
#ifdef _M_X86_64
|
||||
#include "VideoCommon/VertexLoaderX64.h"
|
||||
@ -26,93 +30,6 @@
|
||||
#include "VideoCommon/VertexLoaderARM64.h"
|
||||
#endif
|
||||
|
||||
VertexLoaderBase::VertexLoaderBase(const TVtxDesc& vtx_desc, const VAT& vtx_attr)
|
||||
: m_VtxDesc{vtx_desc}, m_vat{vtx_attr}
|
||||
{
|
||||
SetVAT(vtx_attr);
|
||||
}
|
||||
|
||||
void VertexLoaderBase::SetVAT(const VAT& vat)
|
||||
{
|
||||
m_VtxAttr.PosElements = vat.g0.PosElements;
|
||||
m_VtxAttr.PosFormat = vat.g0.PosFormat;
|
||||
m_VtxAttr.PosFrac = vat.g0.PosFrac;
|
||||
m_VtxAttr.NormalElements = vat.g0.NormalElements;
|
||||
m_VtxAttr.NormalFormat = vat.g0.NormalFormat;
|
||||
m_VtxAttr.color[0].Elements = vat.g0.Color0Elements;
|
||||
m_VtxAttr.color[0].Comp = vat.g0.Color0Comp;
|
||||
m_VtxAttr.color[1].Elements = vat.g0.Color1Elements;
|
||||
m_VtxAttr.color[1].Comp = vat.g0.Color1Comp;
|
||||
m_VtxAttr.texCoord[0].Elements = vat.g0.Tex0CoordElements;
|
||||
m_VtxAttr.texCoord[0].Format = vat.g0.Tex0CoordFormat;
|
||||
m_VtxAttr.texCoord[0].Frac = vat.g0.Tex0Frac;
|
||||
m_VtxAttr.ByteDequant = vat.g0.ByteDequant;
|
||||
m_VtxAttr.NormalIndex3 = vat.g0.NormalIndex3;
|
||||
|
||||
m_VtxAttr.texCoord[1].Elements = vat.g1.Tex1CoordElements;
|
||||
m_VtxAttr.texCoord[1].Format = vat.g1.Tex1CoordFormat;
|
||||
m_VtxAttr.texCoord[1].Frac = vat.g1.Tex1Frac;
|
||||
m_VtxAttr.texCoord[2].Elements = vat.g1.Tex2CoordElements;
|
||||
m_VtxAttr.texCoord[2].Format = vat.g1.Tex2CoordFormat;
|
||||
m_VtxAttr.texCoord[2].Frac = vat.g1.Tex2Frac;
|
||||
m_VtxAttr.texCoord[3].Elements = vat.g1.Tex3CoordElements;
|
||||
m_VtxAttr.texCoord[3].Format = vat.g1.Tex3CoordFormat;
|
||||
m_VtxAttr.texCoord[3].Frac = vat.g1.Tex3Frac;
|
||||
m_VtxAttr.texCoord[4].Elements = vat.g1.Tex4CoordElements;
|
||||
m_VtxAttr.texCoord[4].Format = vat.g1.Tex4CoordFormat;
|
||||
|
||||
m_VtxAttr.texCoord[4].Frac = vat.g2.Tex4Frac;
|
||||
m_VtxAttr.texCoord[5].Elements = vat.g2.Tex5CoordElements;
|
||||
m_VtxAttr.texCoord[5].Format = vat.g2.Tex5CoordFormat;
|
||||
m_VtxAttr.texCoord[5].Frac = vat.g2.Tex5Frac;
|
||||
m_VtxAttr.texCoord[6].Elements = vat.g2.Tex6CoordElements;
|
||||
m_VtxAttr.texCoord[6].Format = vat.g2.Tex6CoordFormat;
|
||||
m_VtxAttr.texCoord[6].Frac = vat.g2.Tex6Frac;
|
||||
m_VtxAttr.texCoord[7].Elements = vat.g2.Tex7CoordElements;
|
||||
m_VtxAttr.texCoord[7].Format = vat.g2.Tex7CoordFormat;
|
||||
m_VtxAttr.texCoord[7].Frac = vat.g2.Tex7Frac;
|
||||
};
|
||||
|
||||
std::string VertexLoaderBase::ToString() const
|
||||
{
|
||||
std::string dest;
|
||||
dest.reserve(250);
|
||||
|
||||
dest += GetName();
|
||||
dest += ": ";
|
||||
|
||||
dest += fmt::format("{}b skin: {} P: {} {}-{} ", m_VertexSize, m_VtxDesc.low.PosMatIdx,
|
||||
m_VtxAttr.PosElements, m_VtxDesc.low.Position, m_VtxAttr.PosFormat);
|
||||
|
||||
if (m_VtxDesc.low.Normal != VertexComponentFormat::NotPresent)
|
||||
{
|
||||
dest += fmt::format("Nrm: {} {}-{} ", m_VtxAttr.NormalElements, m_VtxDesc.low.Normal,
|
||||
m_VtxAttr.NormalFormat);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < g_main_cp_state.vtx_desc.low.Color.Size(); i++)
|
||||
{
|
||||
if (g_main_cp_state.vtx_desc.low.Color[i] == VertexComponentFormat::NotPresent)
|
||||
continue;
|
||||
|
||||
const auto& color = m_VtxAttr.color[i];
|
||||
dest += fmt::format("C{}: {} {}-{} ", i, color.Elements, g_main_cp_state.vtx_desc.low.Color[i],
|
||||
color.Comp);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < g_main_cp_state.vtx_desc.high.TexCoord.Size(); i++)
|
||||
{
|
||||
if (g_main_cp_state.vtx_desc.high.TexCoord[i] == VertexComponentFormat::NotPresent)
|
||||
continue;
|
||||
|
||||
const auto& tex_coord = m_VtxAttr.texCoord[i];
|
||||
dest += fmt::format("T{}: {} {}-{} ", i, tex_coord.Elements,
|
||||
g_main_cp_state.vtx_desc.high.TexCoord[i], tex_coord.Format);
|
||||
}
|
||||
dest += fmt::format(" - {} v", m_numLoadedVertices);
|
||||
return dest;
|
||||
}
|
||||
|
||||
// a hacky implementation to compare two vertex loaders
|
||||
class VertexLoaderTester : public VertexLoaderBase
|
||||
{
|
||||
@ -121,31 +38,25 @@ public:
|
||||
const TVtxDesc& vtx_desc, const VAT& vtx_attr)
|
||||
: VertexLoaderBase(vtx_desc, vtx_attr), a(std::move(a_)), b(std::move(b_))
|
||||
{
|
||||
m_initialized = a && b && a->IsInitialized() && b->IsInitialized();
|
||||
|
||||
if (m_initialized)
|
||||
ASSERT(a && b);
|
||||
if (a->m_vertex_size == b->m_vertex_size && a->m_native_components == b->m_native_components &&
|
||||
a->m_native_vtx_decl.stride == b->m_native_vtx_decl.stride)
|
||||
{
|
||||
m_initialized = a->m_VertexSize == b->m_VertexSize &&
|
||||
a->m_native_components == b->m_native_components &&
|
||||
a->m_native_vtx_decl.stride == b->m_native_vtx_decl.stride;
|
||||
// These are generated from the VAT and vertex desc, so they should match.
|
||||
// m_native_vtx_decl.stride isn't set yet, though.
|
||||
ASSERT(m_vertex_size == a->m_vertex_size && m_native_components == a->m_native_components);
|
||||
|
||||
if (m_initialized)
|
||||
{
|
||||
m_VertexSize = a->m_VertexSize;
|
||||
m_native_components = a->m_native_components;
|
||||
memcpy(&m_native_vtx_decl, &a->m_native_vtx_decl, sizeof(PortableVertexDeclaration));
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG_FMT(VIDEO, "Can't compare vertex loaders that expect different vertex formats!");
|
||||
ERROR_LOG_FMT(VIDEO, "a: m_VertexSize {}, m_native_components {:#010x}, stride {}",
|
||||
a->m_VertexSize, a->m_native_components, a->m_native_vtx_decl.stride);
|
||||
ERROR_LOG_FMT(VIDEO, "b: m_VertexSize {}, m_native_components {:#010x}, stride {}",
|
||||
b->m_VertexSize, b->m_native_components, b->m_native_vtx_decl.stride);
|
||||
}
|
||||
memcpy(&m_native_vtx_decl, &a->m_native_vtx_decl, sizeof(PortableVertexDeclaration));
|
||||
}
|
||||
else
|
||||
{
|
||||
PanicAlertFmt("Can't compare vertex loaders that expect different vertex formats!\n"
|
||||
"a: m_vertex_size {}, m_native_components {:#010x}, stride {}\n"
|
||||
"b: m_vertex_size {}, m_native_components {:#010x}, stride {}",
|
||||
a->m_vertex_size, a->m_native_components, a->m_native_vtx_decl.stride,
|
||||
b->m_vertex_size, b->m_native_components, b->m_native_vtx_decl.stride);
|
||||
}
|
||||
}
|
||||
~VertexLoaderTester() override {}
|
||||
int RunVertices(DataReader src, DataReader dst, int count) override
|
||||
{
|
||||
buffer_a.resize(count * a->m_native_vtx_decl.stride + 4);
|
||||
@ -168,22 +79,17 @@ public:
|
||||
std::min(count_a, count_b) * m_native_vtx_decl.stride))
|
||||
{
|
||||
ERROR_LOG_FMT(VIDEO,
|
||||
"The two vertex loaders have loaded different data "
|
||||
"(guru meditation {:#010x}, {:#010x}, {:#010x}, {:#010x}, {:#010x}).",
|
||||
m_VtxDesc.low.Hex, m_VtxDesc.high.Hex, m_vat.g0.Hex, m_vat.g1.Hex,
|
||||
m_vat.g2.Hex);
|
||||
"The two vertex loaders have loaded different data. Configuration:"
|
||||
"\nVertex desc:\n{}\n\nVertex attr:\n{}",
|
||||
m_VtxDesc, m_VtxAttr);
|
||||
}
|
||||
|
||||
memcpy(dst.GetPointer(), buffer_a.data(), count_a * m_native_vtx_decl.stride);
|
||||
m_numLoadedVertices += count;
|
||||
return count_a;
|
||||
}
|
||||
std::string GetName() const override { return "CompareLoader"; }
|
||||
bool IsInitialized() override { return m_initialized; }
|
||||
|
||||
private:
|
||||
bool m_initialized;
|
||||
|
||||
std::unique_ptr<VertexLoaderBase> a;
|
||||
std::unique_ptr<VertexLoaderBase> b;
|
||||
|
||||
@ -191,36 +97,112 @@ private:
|
||||
std::vector<u8> buffer_b;
|
||||
};
|
||||
|
||||
template <class Function>
|
||||
static void GetComponentSizes(const TVtxDesc& vtx_desc, const VAT& vtx_attr, Function f)
|
||||
{
|
||||
if (vtx_desc.low.PosMatIdx)
|
||||
f(1);
|
||||
for (auto texmtxidx : vtx_desc.low.TexMatIdx)
|
||||
{
|
||||
if (texmtxidx)
|
||||
f(1);
|
||||
}
|
||||
const u32 pos_size = VertexLoader_Position::GetSize(vtx_desc.low.Position, vtx_attr.g0.PosFormat,
|
||||
vtx_attr.g0.PosElements);
|
||||
if (pos_size != 0)
|
||||
f(pos_size);
|
||||
const u32 norm_size =
|
||||
VertexLoader_Normal::GetSize(vtx_desc.low.Normal, vtx_attr.g0.NormalFormat,
|
||||
vtx_attr.g0.NormalElements, vtx_attr.g0.NormalIndex3);
|
||||
if (norm_size != 0)
|
||||
f(norm_size);
|
||||
for (u32 i = 0; i < vtx_desc.low.Color.Size(); i++)
|
||||
{
|
||||
const u32 color_size =
|
||||
VertexLoader_Color::GetSize(vtx_desc.low.Color[i], vtx_attr.GetColorFormat(i));
|
||||
if (color_size != 0)
|
||||
f(color_size);
|
||||
}
|
||||
for (u32 i = 0; i < vtx_desc.high.TexCoord.Size(); i++)
|
||||
{
|
||||
const u32 tc_size = VertexLoader_TextCoord::GetSize(
|
||||
vtx_desc.high.TexCoord[i], vtx_attr.GetTexFormat(i), vtx_attr.GetTexElements(i));
|
||||
if (tc_size != 0)
|
||||
f(tc_size);
|
||||
}
|
||||
}
|
||||
|
||||
u32 VertexLoaderBase::GetVertexSize(const TVtxDesc& vtx_desc, const VAT& vtx_attr)
|
||||
{
|
||||
u32 size = 0;
|
||||
GetComponentSizes(vtx_desc, vtx_attr, [&size](u32 s) { size += s; });
|
||||
return size;
|
||||
}
|
||||
|
||||
u32 VertexLoaderBase::GetVertexComponents(const TVtxDesc& vtx_desc, const VAT& vtx_attr)
|
||||
{
|
||||
u32 components = 0;
|
||||
if (vtx_desc.low.PosMatIdx)
|
||||
components |= VB_HAS_POSMTXIDX;
|
||||
for (u32 i = 0; i < vtx_desc.low.TexMatIdx.Size(); i++)
|
||||
{
|
||||
if (vtx_desc.low.TexMatIdx[i])
|
||||
components |= VB_HAS_TEXMTXIDX0 << i;
|
||||
}
|
||||
// Vertices always have positions; thus there is no VB_HAS_POS as it would always be set
|
||||
if (vtx_desc.low.Normal != VertexComponentFormat::NotPresent)
|
||||
{
|
||||
components |= VB_HAS_NRM0;
|
||||
if (vtx_attr.g0.NormalElements == NormalComponentCount::NBT)
|
||||
components |= VB_HAS_NRM1 | VB_HAS_NRM2;
|
||||
}
|
||||
for (u32 i = 0; i < vtx_desc.low.Color.Size(); i++)
|
||||
{
|
||||
if (vtx_desc.low.Color[i] != VertexComponentFormat::NotPresent)
|
||||
components |= VB_HAS_COL0 << i;
|
||||
}
|
||||
for (u32 i = 0; i < vtx_desc.high.TexCoord.Size(); i++)
|
||||
{
|
||||
if (vtx_desc.high.TexCoord[i] != VertexComponentFormat::NotPresent)
|
||||
components |= VB_HAS_UV0 << i;
|
||||
}
|
||||
return components;
|
||||
}
|
||||
|
||||
std::vector<u32> VertexLoaderBase::GetVertexComponentSizes(const TVtxDesc& vtx_desc,
|
||||
const VAT& vtx_attr)
|
||||
{
|
||||
std::vector<u32> sizes;
|
||||
GetComponentSizes(vtx_desc, vtx_attr, [&sizes](u32 s) { sizes.push_back(s); });
|
||||
return sizes;
|
||||
}
|
||||
|
||||
std::unique_ptr<VertexLoaderBase> VertexLoaderBase::CreateVertexLoader(const TVtxDesc& vtx_desc,
|
||||
const VAT& vtx_attr)
|
||||
{
|
||||
std::unique_ptr<VertexLoaderBase> loader;
|
||||
std::unique_ptr<VertexLoaderBase> loader = nullptr;
|
||||
|
||||
//#define COMPARE_VERTEXLOADERS
|
||||
|
||||
#if defined(COMPARE_VERTEXLOADERS) && defined(_M_X86_64)
|
||||
// first try: Any new VertexLoader vs the old one
|
||||
loader = std::make_unique<VertexLoaderTester>(
|
||||
std::make_unique<VertexLoader>(vtx_desc, vtx_attr), // the software one
|
||||
std::make_unique<VertexLoaderX64>(vtx_desc, vtx_attr), // the new one to compare
|
||||
vtx_desc, vtx_attr);
|
||||
if (loader->IsInitialized())
|
||||
return loader;
|
||||
#elif defined(_M_X86_64)
|
||||
#if defined(_M_X86_64)
|
||||
loader = std::make_unique<VertexLoaderX64>(vtx_desc, vtx_attr);
|
||||
if (loader->IsInitialized())
|
||||
return loader;
|
||||
#elif defined(_M_ARM_64)
|
||||
loader = std::make_unique<VertexLoaderARM64>(vtx_desc, vtx_attr);
|
||||
if (loader->IsInitialized())
|
||||
return loader;
|
||||
#endif
|
||||
|
||||
// last try: The old VertexLoader
|
||||
loader = std::make_unique<VertexLoader>(vtx_desc, vtx_attr);
|
||||
if (loader->IsInitialized())
|
||||
return loader;
|
||||
// Use the software loader as a fallback
|
||||
// (not currently applicable, as both VertexLoaderX64 and VertexLoaderARM64
|
||||
// are always usable, but if a loader that only works on some CPUs is created
|
||||
// then this fallback would be used)
|
||||
if (!loader)
|
||||
loader = std::make_unique<VertexLoader>(vtx_desc, vtx_attr);
|
||||
|
||||
PanicAlertFmt("No Vertex Loader found.");
|
||||
return nullptr;
|
||||
#if defined(COMPARE_VERTEXLOADERS)
|
||||
return std::make_unique<VertexLoaderTester>(
|
||||
std::make_unique<VertexLoader>(vtx_desc, vtx_attr), // the software one
|
||||
std::move(loader), // the new one to compare
|
||||
vtx_desc, vtx_attr);
|
||||
#else
|
||||
return loader;
|
||||
#endif
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "VideoCommon/CPMemory.h"
|
||||
@ -60,33 +61,31 @@ struct hash<VertexLoaderUID>
|
||||
class VertexLoaderBase
|
||||
{
|
||||
public:
|
||||
static u32 GetVertexSize(const TVtxDesc& vtx_desc, const VAT& vtx_attr);
|
||||
static u32 GetVertexComponents(const TVtxDesc& vtx_desc, const VAT& vtx_attr);
|
||||
static std::vector<u32> GetVertexComponentSizes(const TVtxDesc& vtx_desc, const VAT& vtx_attr);
|
||||
static std::unique_ptr<VertexLoaderBase> CreateVertexLoader(const TVtxDesc& vtx_desc,
|
||||
const VAT& vtx_attr);
|
||||
virtual ~VertexLoaderBase() {}
|
||||
virtual int RunVertices(DataReader src, DataReader dst, int count) = 0;
|
||||
|
||||
virtual bool IsInitialized() = 0;
|
||||
|
||||
// For debugging / profiling
|
||||
std::string ToString() const;
|
||||
|
||||
virtual std::string GetName() const = 0;
|
||||
|
||||
// per loader public state
|
||||
int m_VertexSize = 0; // number of bytes of a raw GC vertex
|
||||
PortableVertexDeclaration m_native_vtx_decl{};
|
||||
u32 m_native_components = 0;
|
||||
const u32 m_vertex_size; // number of bytes of a raw GC vertex
|
||||
const u32 m_native_components;
|
||||
|
||||
// used by VertexLoaderManager
|
||||
NativeVertexFormat* m_native_vertex_format = nullptr;
|
||||
int m_numLoadedVertices = 0;
|
||||
|
||||
protected:
|
||||
VertexLoaderBase(const TVtxDesc& vtx_desc, const VAT& vtx_attr);
|
||||
void SetVAT(const VAT& vat);
|
||||
VertexLoaderBase(const TVtxDesc& vtx_desc, const VAT& vtx_attr)
|
||||
: m_VtxDesc{vtx_desc}, m_VtxAttr{vtx_attr}, m_vertex_size{GetVertexSize(vtx_desc, vtx_attr)},
|
||||
m_native_components{GetVertexComponents(vtx_desc, vtx_attr)}
|
||||
{
|
||||
}
|
||||
|
||||
// GC vertex format
|
||||
TVtxAttr m_VtxAttr; // VAT decoded into easy format
|
||||
TVtxDesc m_VtxDesc; // Not really used currently - or well it is, but could be easily avoided.
|
||||
VAT m_vat;
|
||||
const VAT m_VtxAttr;
|
||||
const TVtxDesc m_VtxDesc;
|
||||
};
|
||||
|
@ -114,34 +114,6 @@ struct entry
|
||||
};
|
||||
} // namespace
|
||||
|
||||
std::string VertexLoadersToString()
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(s_vertex_loader_map_lock);
|
||||
std::vector<entry> entries;
|
||||
|
||||
size_t total_size = 0;
|
||||
for (const auto& map_entry : s_vertex_loader_map)
|
||||
{
|
||||
entry e = {map_entry.second->ToString(),
|
||||
static_cast<u64>(map_entry.second->m_numLoadedVertices)};
|
||||
|
||||
total_size += e.text.size() + 1;
|
||||
entries.push_back(std::move(e));
|
||||
}
|
||||
|
||||
sort(entries.begin(), entries.end());
|
||||
|
||||
std::string dest;
|
||||
dest.reserve(total_size);
|
||||
for (const entry& entry : entries)
|
||||
{
|
||||
dest += entry.text;
|
||||
dest += '\n';
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void MarkAllDirty()
|
||||
{
|
||||
g_main_cp_state.attr_dirty = BitSet32::AllTrue(8);
|
||||
@ -275,7 +247,7 @@ int RunVertices(int vtx_attr_group, int primitive, int count, DataReader src, bo
|
||||
|
||||
VertexLoaderBase* loader = RefreshLoader(vtx_attr_group, is_preprocess);
|
||||
|
||||
int size = count * loader->m_VertexSize;
|
||||
int size = count * loader->m_vertex_size;
|
||||
if ((int)src.size() < size)
|
||||
return -1;
|
||||
|
||||
|
@ -38,9 +38,6 @@ NativeVertexFormat* GetUberVertexFormat(const PortableVertexDeclaration& decl);
|
||||
// Returns -1 if buf_size is insufficient, else the amount of bytes consumed
|
||||
int RunVertices(int vtx_attr_group, int primitive, int count, DataReader src, bool is_preprocess);
|
||||
|
||||
// For debugging
|
||||
std::string VertexLoadersToString();
|
||||
|
||||
NativeVertexFormat* GetCurrentVertexFormat();
|
||||
|
||||
// Resolved pointers to array bases. Used by vertex loaders.
|
||||
|
@ -45,15 +45,13 @@ static OpArg MPIC(const void* ptr)
|
||||
VertexLoaderX64::VertexLoaderX64(const TVtxDesc& vtx_desc, const VAT& vtx_att)
|
||||
: VertexLoaderBase(vtx_desc, vtx_att)
|
||||
{
|
||||
if (!IsInitialized())
|
||||
return;
|
||||
|
||||
AllocCodeSpace(4096);
|
||||
ClearCodeSpace();
|
||||
GenerateVertexLoader();
|
||||
WriteProtect();
|
||||
|
||||
const std::string name = ToString();
|
||||
const std::string name =
|
||||
fmt::format("VertexLoaderX64\nVtx desc: \n{}\nVAT:\n{}", vtx_desc, vtx_att);
|
||||
JitRegister::Register(region, GetCodePtr(), name.c_str());
|
||||
}
|
||||
|
||||
@ -420,7 +418,6 @@ void VertexLoaderX64::GenerateVertexLoader()
|
||||
MOV(32, MPIC(VertexLoaderManager::position_matrix_index, count_reg, SCALE_4), R(scratch1));
|
||||
SetJumpTarget(dont_store);
|
||||
|
||||
m_native_components |= VB_HAS_POSMTXIDX;
|
||||
m_native_vtx_decl.posmtx.components = 4;
|
||||
m_native_vtx_decl.posmtx.enable = true;
|
||||
m_native_vtx_decl.posmtx.offset = m_dst_ofs;
|
||||
@ -438,31 +435,27 @@ void VertexLoaderX64::GenerateVertexLoader()
|
||||
}
|
||||
|
||||
OpArg data = GetVertexAddr(ARRAY_POSITION, m_VtxDesc.low.Position);
|
||||
int pos_elements = m_VtxAttr.PosElements == CoordComponentCount::XY ? 2 : 3;
|
||||
ReadVertex(data, m_VtxDesc.low.Position, m_VtxAttr.PosFormat, pos_elements, pos_elements,
|
||||
m_VtxAttr.ByteDequant, m_VtxAttr.PosFrac, &m_native_vtx_decl.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);
|
||||
|
||||
if (m_VtxDesc.low.Normal != VertexComponentFormat::NotPresent)
|
||||
{
|
||||
static const u8 map[8] = {7, 6, 15, 14};
|
||||
const u8 scaling_exponent = map[u32(m_VtxAttr.NormalFormat)];
|
||||
const int limit = m_VtxAttr.NormalElements == NormalComponentCount::NBT ? 3 : 1;
|
||||
const u8 scaling_exponent = map[u32(m_VtxAttr.g0.NormalFormat.Value())];
|
||||
const int limit = m_VtxAttr.g0.NormalElements == NormalComponentCount::NBT ? 3 : 1;
|
||||
|
||||
for (int i = 0; i < limit; i++)
|
||||
{
|
||||
if (!i || m_VtxAttr.NormalIndex3)
|
||||
if (!i || m_VtxAttr.g0.NormalIndex3)
|
||||
{
|
||||
data = GetVertexAddr(ARRAY_NORMAL, m_VtxDesc.low.Normal);
|
||||
int elem_size = GetElementSize(m_VtxAttr.NormalFormat);
|
||||
int elem_size = GetElementSize(m_VtxAttr.g0.NormalFormat);
|
||||
data.AddMemOffset(i * elem_size * 3);
|
||||
}
|
||||
data.AddMemOffset(ReadVertex(data, m_VtxDesc.low.Normal, m_VtxAttr.NormalFormat, 3, 3, true,
|
||||
scaling_exponent, &m_native_vtx_decl.normals[i]));
|
||||
data.AddMemOffset(ReadVertex(data, m_VtxDesc.low.Normal, m_VtxAttr.g0.NormalFormat, 3, 3,
|
||||
true, scaling_exponent, &m_native_vtx_decl.normals[i]));
|
||||
}
|
||||
|
||||
m_native_components |= VB_HAS_NRM0;
|
||||
if (m_VtxAttr.NormalElements == NormalComponentCount::NBT)
|
||||
m_native_components |= VB_HAS_NRM1 | VB_HAS_NRM2;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_VtxDesc.low.Color.Size(); i++)
|
||||
@ -470,8 +463,7 @@ void VertexLoaderX64::GenerateVertexLoader()
|
||||
if (m_VtxDesc.low.Color[i] != VertexComponentFormat::NotPresent)
|
||||
{
|
||||
data = GetVertexAddr(ARRAY_COLOR0 + int(i), m_VtxDesc.low.Color[i]);
|
||||
ReadColor(data, m_VtxDesc.low.Color[i], m_VtxAttr.color[i].Comp);
|
||||
m_native_components |= VB_HAS_COL0 << 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;
|
||||
m_native_vtx_decl.colors[i].offset = m_dst_ofs;
|
||||
@ -483,19 +475,17 @@ void VertexLoaderX64::GenerateVertexLoader()
|
||||
|
||||
for (size_t i = 0; i < m_VtxDesc.high.TexCoord.Size(); i++)
|
||||
{
|
||||
int elements = m_VtxAttr.texCoord[i].Elements == TexComponentCount::ST ? 2 : 1;
|
||||
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]);
|
||||
u8 scaling_exponent = m_VtxAttr.texCoord[i].Frac;
|
||||
ReadVertex(data, m_VtxDesc.high.TexCoord[i], m_VtxAttr.texCoord[i].Format, elements,
|
||||
m_VtxDesc.low.TexMatIdx[i] ? 2 : elements, m_VtxAttr.ByteDequant, scaling_exponent,
|
||||
&m_native_vtx_decl.texcoords[i]);
|
||||
m_native_components |= VB_HAS_UV0 << 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,
|
||||
scaling_exponent, &m_native_vtx_decl.texcoords[i]);
|
||||
}
|
||||
if (m_VtxDesc.low.TexMatIdx[i])
|
||||
{
|
||||
m_native_components |= VB_HAS_TEXMTXIDX0 << i;
|
||||
m_native_vtx_decl.texcoords[i].components = 3;
|
||||
m_native_vtx_decl.texcoords[i].enable = true;
|
||||
m_native_vtx_decl.texcoords[i].type = VAR_FLOAT;
|
||||
@ -546,7 +536,7 @@ void VertexLoaderX64::GenerateVertexLoader()
|
||||
RET();
|
||||
}
|
||||
|
||||
m_VertexSize = m_src_ofs;
|
||||
ASSERT(m_vertex_size == m_src_ofs);
|
||||
m_native_vtx_decl.stride = m_dst_ofs;
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,6 @@ public:
|
||||
VertexLoaderX64(const TVtxDesc& vtx_desc, const VAT& vtx_att);
|
||||
|
||||
protected:
|
||||
std::string GetName() const override { return "VertexLoaderX64"; }
|
||||
bool IsInitialized() override { return true; }
|
||||
int RunVertices(DataReader src, DataReader dst, int count) override;
|
||||
|
||||
private:
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <cstring>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/Swap.h"
|
||||
|
||||
#include "VideoCommon/VertexLoader.h"
|
||||
@ -136,7 +137,6 @@ void Color_ReadIndex_32b_8888(VertexLoader* loader)
|
||||
(index * g_main_cp_state.array_strides[ARRAY_COLOR0 + loader->m_colIndex]);
|
||||
SetCol(loader, Read32(address));
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
void Color_ReadDirect_24b_888(VertexLoader* loader)
|
||||
{
|
||||
@ -149,10 +149,12 @@ void Color_ReadDirect_32b_888x(VertexLoader* loader)
|
||||
SetCol(loader, Read24(DataGetPosition()));
|
||||
DataSkip(4);
|
||||
}
|
||||
|
||||
void Color_ReadDirect_16b_565(VertexLoader* loader)
|
||||
{
|
||||
SetCol565(loader, DataRead<u16>());
|
||||
}
|
||||
|
||||
void Color_ReadDirect_16b_4444(VertexLoader* loader)
|
||||
{
|
||||
u16 value;
|
||||
@ -161,62 +163,52 @@ void Color_ReadDirect_16b_4444(VertexLoader* loader)
|
||||
SetCol4444(loader, value);
|
||||
DataSkip(2);
|
||||
}
|
||||
|
||||
void Color_ReadDirect_24b_6666(VertexLoader* loader)
|
||||
{
|
||||
SetCol6666(loader, Common::swap32(DataGetPosition() - 1));
|
||||
DataSkip(3);
|
||||
}
|
||||
|
||||
void Color_ReadDirect_32b_8888(VertexLoader* loader)
|
||||
{
|
||||
SetCol(loader, DataReadU32Unswapped());
|
||||
}
|
||||
|
||||
void Color_ReadIndex8_16b_565(VertexLoader* loader)
|
||||
constexpr TPipelineFunction s_table_read_color[4][6] = {
|
||||
{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{Color_ReadDirect_16b_565, Color_ReadDirect_24b_888, Color_ReadDirect_32b_888x,
|
||||
Color_ReadDirect_16b_4444, Color_ReadDirect_24b_6666, Color_ReadDirect_32b_8888},
|
||||
{Color_ReadIndex_16b_565<u8>, Color_ReadIndex_24b_888<u8>, Color_ReadIndex_32b_888x<u8>,
|
||||
Color_ReadIndex_16b_4444<u8>, Color_ReadIndex_24b_6666<u8>, Color_ReadIndex_32b_8888<u8>},
|
||||
{Color_ReadIndex_16b_565<u16>, Color_ReadIndex_24b_888<u16>, Color_ReadIndex_32b_888x<u16>,
|
||||
Color_ReadIndex_16b_4444<u16>, Color_ReadIndex_24b_6666<u16>, Color_ReadIndex_32b_8888<u16>},
|
||||
};
|
||||
|
||||
constexpr u32 s_table_read_color_vertex_size[4][6] = {
|
||||
{0, 0, 0, 0, 0, 0},
|
||||
{2, 3, 4, 2, 3, 4},
|
||||
{1, 1, 1, 1, 1, 1},
|
||||
{2, 2, 2, 2, 2, 2},
|
||||
};
|
||||
} // Anonymous namespace
|
||||
|
||||
u32 VertexLoader_Color::GetSize(VertexComponentFormat type, ColorFormat format)
|
||||
{
|
||||
Color_ReadIndex_16b_565<u8>(loader);
|
||||
}
|
||||
void Color_ReadIndex8_24b_888(VertexLoader* loader)
|
||||
{
|
||||
Color_ReadIndex_24b_888<u8>(loader);
|
||||
}
|
||||
void Color_ReadIndex8_32b_888x(VertexLoader* loader)
|
||||
{
|
||||
Color_ReadIndex_32b_888x<u8>(loader);
|
||||
}
|
||||
void Color_ReadIndex8_16b_4444(VertexLoader* loader)
|
||||
{
|
||||
Color_ReadIndex_16b_4444<u8>(loader);
|
||||
}
|
||||
void Color_ReadIndex8_24b_6666(VertexLoader* loader)
|
||||
{
|
||||
Color_ReadIndex_24b_6666<u8>(loader);
|
||||
}
|
||||
void Color_ReadIndex8_32b_8888(VertexLoader* loader)
|
||||
{
|
||||
Color_ReadIndex_32b_8888<u8>(loader);
|
||||
if (format > ColorFormat::RGBA8888)
|
||||
{
|
||||
PanicAlertFmt("Invalid color format {}", format);
|
||||
return 0;
|
||||
}
|
||||
return s_table_read_color_vertex_size[u32(type)][u32(format)];
|
||||
}
|
||||
|
||||
void Color_ReadIndex16_16b_565(VertexLoader* loader)
|
||||
TPipelineFunction VertexLoader_Color::GetFunction(VertexComponentFormat type, ColorFormat format)
|
||||
{
|
||||
Color_ReadIndex_16b_565<u16>(loader);
|
||||
}
|
||||
void Color_ReadIndex16_24b_888(VertexLoader* loader)
|
||||
{
|
||||
Color_ReadIndex_24b_888<u16>(loader);
|
||||
}
|
||||
void Color_ReadIndex16_32b_888x(VertexLoader* loader)
|
||||
{
|
||||
Color_ReadIndex_32b_888x<u16>(loader);
|
||||
}
|
||||
void Color_ReadIndex16_16b_4444(VertexLoader* loader)
|
||||
{
|
||||
Color_ReadIndex_16b_4444<u16>(loader);
|
||||
}
|
||||
void Color_ReadIndex16_24b_6666(VertexLoader* loader)
|
||||
{
|
||||
Color_ReadIndex_24b_6666<u16>(loader);
|
||||
}
|
||||
void Color_ReadIndex16_32b_8888(VertexLoader* loader)
|
||||
{
|
||||
Color_ReadIndex_32b_8888<u16>(loader);
|
||||
if (format > ColorFormat::RGBA8888)
|
||||
{
|
||||
PanicAlertFmt("Invalid color format {}", format);
|
||||
return nullptr;
|
||||
}
|
||||
return s_table_read_color[u32(type)][u32(format)];
|
||||
}
|
||||
|
@ -4,25 +4,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
class VertexLoader;
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "VideoCommon/VertexLoader.h"
|
||||
|
||||
void Color_ReadDirect_24b_888(VertexLoader* loader);
|
||||
void Color_ReadDirect_32b_888x(VertexLoader* loader);
|
||||
void Color_ReadDirect_16b_565(VertexLoader* loader);
|
||||
void Color_ReadDirect_16b_4444(VertexLoader* loader);
|
||||
void Color_ReadDirect_24b_6666(VertexLoader* loader);
|
||||
void Color_ReadDirect_32b_8888(VertexLoader* loader);
|
||||
enum class VertexComponentFormat;
|
||||
enum class ColorFormat;
|
||||
|
||||
void Color_ReadIndex8_16b_565(VertexLoader* loader);
|
||||
void Color_ReadIndex8_24b_888(VertexLoader* loader);
|
||||
void Color_ReadIndex8_32b_888x(VertexLoader* loader);
|
||||
void Color_ReadIndex8_16b_4444(VertexLoader* loader);
|
||||
void Color_ReadIndex8_24b_6666(VertexLoader* loader);
|
||||
void Color_ReadIndex8_32b_8888(VertexLoader* loader);
|
||||
|
||||
void Color_ReadIndex16_16b_565(VertexLoader* loader);
|
||||
void Color_ReadIndex16_24b_888(VertexLoader* loader);
|
||||
void Color_ReadIndex16_32b_888x(VertexLoader* loader);
|
||||
void Color_ReadIndex16_16b_4444(VertexLoader* loader);
|
||||
void Color_ReadIndex16_24b_6666(VertexLoader* loader);
|
||||
void Color_ReadIndex16_32b_8888(VertexLoader* loader);
|
||||
class VertexLoader_Color
|
||||
{
|
||||
public:
|
||||
static u32 GetSize(VertexComponentFormat type, ColorFormat format);
|
||||
static TPipelineFunction GetFunction(VertexComponentFormat type, ColorFormat format);
|
||||
};
|
||||
|
@ -259,12 +259,19 @@ void LoadXFReg(u32 transferSize, u32 baseAddress, DataReader src)
|
||||
}
|
||||
}
|
||||
|
||||
constexpr std::tuple<u32, u32, u32> ExtractIndexedXF(u32 val)
|
||||
{
|
||||
const u32 index = val >> 16;
|
||||
const u32 address = val & 0xFFF; // check mask
|
||||
const u32 size = ((val >> 12) & 0xF) + 1;
|
||||
|
||||
return {index, address, size};
|
||||
}
|
||||
|
||||
// TODO - verify that it is correct. Seems to work, though.
|
||||
void LoadIndexedXF(u32 val, int refarray)
|
||||
{
|
||||
int index = val >> 16;
|
||||
int address = val & 0xFFF; // check mask
|
||||
int size = ((val >> 12) & 0xF) + 1;
|
||||
const auto [index, address, size] = ExtractIndexedXF(val);
|
||||
// load stuff from array to address in xf mem
|
||||
|
||||
u32* currData = (u32*)(&xfmem) + address;
|
||||
@ -279,7 +286,7 @@ void LoadIndexedXF(u32 val, int refarray)
|
||||
g_main_cp_state.array_strides[refarray] * index);
|
||||
}
|
||||
bool changed = false;
|
||||
for (int i = 0; i < size; ++i)
|
||||
for (u32 i = 0; i < size; ++i)
|
||||
{
|
||||
if (currData[i] != Common::swap32(newData[i]))
|
||||
{
|
||||
@ -290,15 +297,14 @@ void LoadIndexedXF(u32 val, int refarray)
|
||||
}
|
||||
if (changed)
|
||||
{
|
||||
for (int i = 0; i < size; ++i)
|
||||
for (u32 i = 0; i < size; ++i)
|
||||
currData[i] = Common::swap32(newData[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void PreprocessIndexedXF(u32 val, int refarray)
|
||||
{
|
||||
const u32 index = val >> 16;
|
||||
const u32 size = ((val >> 12) & 0xF) + 1;
|
||||
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);
|
||||
@ -643,3 +649,18 @@ 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)
|
||||
{
|
||||
const auto [index, address, size] = ExtractIndexedXF(value);
|
||||
|
||||
const auto desc = fmt::format("Load {} bytes to XF address {:03x} from CP array {} row {}", size,
|
||||
address, array, index);
|
||||
fmt::memory_buffer written;
|
||||
for (u32 i = 0; i < size; i++)
|
||||
{
|
||||
fmt::format_to(written, "{}\n", GetXFMemName(address + i));
|
||||
}
|
||||
|
||||
return std::make_pair(desc, fmt::to_string(written));
|
||||
}
|
||||
|
@ -13,3 +13,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);
|
||||
|
Reference in New Issue
Block a user