VideoSW: rewrite VertexLoader to use the VideoCommon one

This commit is contained in:
degasus 2014-12-07 21:51:45 +01:00
parent d02eb3ca59
commit d5eeb9b713
3 changed files with 117 additions and 245 deletions

View File

@ -21,13 +21,8 @@
#include "VideoCommon/VertexManagerBase.h"
SWVertexLoader::SWVertexLoader() :
m_VertexSize(0),
m_NumAttributeLoaders(0)
m_VertexSize(0)
{
VertexLoader_Normal::Init();
VertexLoader_Position::Init();
VertexLoader_TextCoord::Init();
m_SetupUnit = new SetupUnit;
}
@ -39,55 +34,22 @@ SWVertexLoader::~SWVertexLoader()
void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
{
m_CurrentVat = &g_main_cp_state.vtx_attr[attributeIndex];
m_attributeIndex = attributeIndex;
m_primitiveType = primitiveType;
posScale[0] = posScale[1] = posScale[2] = posScale[3] = 1.0f / float(1 << m_CurrentVat->g0.PosFrac);
tcScale[0][0] = tcScale[0][1] = 1.0f / float(1 << m_CurrentVat->g0.Tex0Frac);
tcScale[1][0] = tcScale[1][1] = 1.0f / float(1 << m_CurrentVat->g1.Tex1Frac);
tcScale[2][0] = tcScale[2][1] = 1.0f / float(1 << m_CurrentVat->g1.Tex2Frac);
tcScale[3][0] = tcScale[3][1] = 1.0f / float(1 << m_CurrentVat->g1.Tex3Frac);
tcScale[4][0] = tcScale[4][1] = 1.0f / float(1 << m_CurrentVat->g2.Tex4Frac);
tcScale[5][0] = tcScale[5][1] = 1.0f / float(1 << m_CurrentVat->g2.Tex5Frac);
tcScale[6][0] = tcScale[6][1] = 1.0f / float(1 << m_CurrentVat->g2.Tex6Frac);
tcScale[7][0] = tcScale[7][1] = 1.0f / float(1 << m_CurrentVat->g2.Tex7Frac);
VertexLoaderUID uid(g_main_cp_state.vtx_desc, g_main_cp_state.vtx_attr[m_attributeIndex]);
m_CurrentLoader = m_VertexLoaderMap[uid].get();
//TexMtx
const u64 tmDesc[8] = {
g_main_cp_state.vtx_desc.Tex0MatIdx, g_main_cp_state.vtx_desc.Tex1MatIdx, g_main_cp_state.vtx_desc.Tex2MatIdx, g_main_cp_state.vtx_desc.Tex3MatIdx,
g_main_cp_state.vtx_desc.Tex4MatIdx, g_main_cp_state.vtx_desc.Tex5MatIdx, g_main_cp_state.vtx_desc.Tex6MatIdx, g_main_cp_state.vtx_desc.Tex7MatIdx
};
if (!m_CurrentLoader)
{
m_CurrentLoader = new VertexLoader(g_main_cp_state.vtx_desc, g_main_cp_state.vtx_attr[m_attributeIndex]);
m_VertexLoaderMap[uid] = std::unique_ptr<VertexLoader>(m_CurrentLoader);
}
// Colors
const u64 colDesc[2] = {g_main_cp_state.vtx_desc.Color0, g_main_cp_state.vtx_desc.Color1};
colElements[0] = m_CurrentVat->g0.Color0Elements;
colElements[1] = m_CurrentVat->g0.Color1Elements;
const u32 colComp[2] = {m_CurrentVat->g0.Color0Comp, m_CurrentVat->g0.Color1Comp};
m_VertexSize = m_CurrentLoader->GetVertexSize();
m_CurrentVat = &g_main_cp_state.vtx_attr[m_attributeIndex];
// TextureCoord
const u64 tcDesc[8] = {
g_main_cp_state.vtx_desc.Tex0Coord, g_main_cp_state.vtx_desc.Tex1Coord, g_main_cp_state.vtx_desc.Tex2Coord, g_main_cp_state.vtx_desc.Tex3Coord,
g_main_cp_state.vtx_desc.Tex4Coord, g_main_cp_state.vtx_desc.Tex5Coord, g_main_cp_state.vtx_desc.Tex6Coord, g_main_cp_state.vtx_desc.Tex7Coord
};
const u32 tcElements[8] = {
m_CurrentVat->g0.Tex0CoordElements, m_CurrentVat->g1.Tex1CoordElements, m_CurrentVat->g1.Tex2CoordElements,
m_CurrentVat->g1.Tex3CoordElements, m_CurrentVat->g1.Tex4CoordElements, m_CurrentVat->g2.Tex5CoordElements,
m_CurrentVat->g2.Tex6CoordElements, m_CurrentVat->g2.Tex7CoordElements
};
const u32 tcFormat[8] = {
m_CurrentVat->g0.Tex0CoordFormat, m_CurrentVat->g1.Tex1CoordFormat, m_CurrentVat->g1.Tex2CoordFormat,
m_CurrentVat->g1.Tex3CoordFormat, m_CurrentVat->g1.Tex4CoordFormat, m_CurrentVat->g2.Tex5CoordFormat,
m_CurrentVat->g2.Tex6CoordFormat, m_CurrentVat->g2.Tex7CoordFormat
};
m_VertexSize = 0;
// Reset pipeline
m_positionLoader = nullptr;
m_normalLoader = nullptr;
m_NumAttributeLoaders = 0;
// Reset vertex
// matrix index from xf regs or cp memory?
if (xfmem.MatrixIndexA.PosNormalMtxIdx != g_main_cp_state.matrix_index_a.PosNormalMtxIdx ||
xfmem.MatrixIndexA.Tex0MtxIdx != g_main_cp_state.matrix_index_a.Tex0MtxIdx ||
@ -107,7 +69,6 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
showedAlert = true;
}
#if(1)
m_Vertex.posMtx = xfmem.MatrixIndexA.PosNormalMtxIdx;
m_Vertex.texMtx[0] = xfmem.MatrixIndexA.Tex0MtxIdx;
m_Vertex.texMtx[1] = xfmem.MatrixIndexA.Tex1MtxIdx;
@ -117,120 +78,7 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
m_Vertex.texMtx[5] = xfmem.MatrixIndexB.Tex5MtxIdx;
m_Vertex.texMtx[6] = xfmem.MatrixIndexB.Tex6MtxIdx;
m_Vertex.texMtx[7] = xfmem.MatrixIndexB.Tex7MtxIdx;
#else
m_Vertex.posMtx = g_main_cp_state.matrix_index_a.PosNormalMtxIdx;
m_Vertex.texMtx[0] = g_main_cp_state.matrix_index_a.Tex0MtxIdx;
m_Vertex.texMtx[1] = g_main_cp_state.matrix_index_a.Tex1MtxIdx;
m_Vertex.texMtx[2] = g_main_cp_state.matrix_index_a.Tex2MtxIdx;
m_Vertex.texMtx[3] = g_main_cp_state.matrix_index_a.Tex3MtxIdx;
m_Vertex.texMtx[4] = g_main_cp_state.matrix_index_b.Tex4MtxIdx;
m_Vertex.texMtx[5] = g_main_cp_state.matrix_index_b.Tex5MtxIdx;
m_Vertex.texMtx[6] = g_main_cp_state.matrix_index_b.Tex6MtxIdx;
m_Vertex.texMtx[7] = g_main_cp_state.matrix_index_b.Tex7MtxIdx;
#endif
if (g_main_cp_state.vtx_desc.PosMatIdx != NOT_PRESENT)
{
AddAttributeLoader(LoadPosMtx);
m_VertexSize++;
}
for (int i = 0; i < 8; ++i)
{
if (tmDesc[i] != NOT_PRESENT)
{
AddAttributeLoader(LoadTexMtx, i);
m_VertexSize++;
}
}
// Write vertex position loader
m_positionLoader = VertexLoader_Position::GetFunction(g_main_cp_state.vtx_desc.Position, m_CurrentVat->g0.PosFormat, m_CurrentVat->g0.PosElements);
m_VertexSize += VertexLoader_Position::GetSize(g_main_cp_state.vtx_desc.Position, m_CurrentVat->g0.PosFormat, m_CurrentVat->g0.PosElements);
AddAttributeLoader(LoadPosition);
// Normals
if (g_main_cp_state.vtx_desc.Normal != NOT_PRESENT)
{
m_VertexSize += VertexLoader_Normal::GetSize(g_main_cp_state.vtx_desc.Normal,
m_CurrentVat->g0.NormalFormat, m_CurrentVat->g0.NormalElements, m_CurrentVat->g0.NormalIndex3);
m_normalLoader = VertexLoader_Normal::GetFunction(g_main_cp_state.vtx_desc.Normal,
m_CurrentVat->g0.NormalFormat, m_CurrentVat->g0.NormalElements, m_CurrentVat->g0.NormalIndex3);
if (m_normalLoader == nullptr)
{
ERROR_LOG(VIDEO, "VertexLoader_Normal::GetFunction returned zero!");
}
AddAttributeLoader(LoadNormal);
}
for (int i = 0; i < 2; i++)
{
switch (colDesc[i])
{
case NOT_PRESENT:
m_colorLoader[i] = nullptr;
break;
case DIRECT:
switch (colComp[i])
{
case FORMAT_16B_565: m_VertexSize += 2; m_colorLoader[i] = (Color_ReadDirect_16b_565); break;
case FORMAT_24B_888: m_VertexSize += 3; m_colorLoader[i] = (Color_ReadDirect_24b_888); break;
case FORMAT_32B_888x: m_VertexSize += 4; m_colorLoader[i] = (Color_ReadDirect_32b_888x); break;
case FORMAT_16B_4444: m_VertexSize += 2; m_colorLoader[i] = (Color_ReadDirect_16b_4444); break;
case FORMAT_24B_6666: m_VertexSize += 3; m_colorLoader[i] = (Color_ReadDirect_24b_6666); break;
case FORMAT_32B_8888: m_VertexSize += 4; m_colorLoader[i] = (Color_ReadDirect_32b_8888); break;
default: _assert_(0); break;
}
AddAttributeLoader(LoadColor, i);
break;
case INDEX8:
m_VertexSize += 1;
switch (colComp[i])
{
case FORMAT_16B_565: m_colorLoader[i] = (Color_ReadIndex8_16b_565); break;
case FORMAT_24B_888: m_colorLoader[i] = (Color_ReadIndex8_24b_888); break;
case FORMAT_32B_888x: m_colorLoader[i] = (Color_ReadIndex8_32b_888x); break;
case FORMAT_16B_4444: m_colorLoader[i] = (Color_ReadIndex8_16b_4444); break;
case FORMAT_24B_6666: m_colorLoader[i] = (Color_ReadIndex8_24b_6666); break;
case FORMAT_32B_8888: m_colorLoader[i] = (Color_ReadIndex8_32b_8888); break;
default: _assert_(0); break;
}
AddAttributeLoader(LoadColor, i);
break;
case INDEX16:
m_VertexSize += 2;
switch (colComp[i])
{
case FORMAT_16B_565: m_colorLoader[i] = (Color_ReadIndex16_16b_565); break;
case FORMAT_24B_888: m_colorLoader[i] = (Color_ReadIndex16_24b_888); break;
case FORMAT_32B_888x: m_colorLoader[i] = (Color_ReadIndex16_32b_888x); break;
case FORMAT_16B_4444: m_colorLoader[i] = (Color_ReadIndex16_16b_4444); break;
case FORMAT_24B_6666: m_colorLoader[i] = (Color_ReadIndex16_24b_6666); break;
case FORMAT_32B_8888: m_colorLoader[i] = (Color_ReadIndex16_32b_8888); break;
default: _assert_(0); break;
}
AddAttributeLoader(LoadColor, i);
break;
}
}
// Texture matrix indices (remove if corresponding texture coordinate isn't enabled)
for (int i = 0; i < 8; i++)
{
const int desc = (int)tcDesc[i];
const int format = tcFormat[i];
const int elements = tcElements[i];
_assert_msg_(VIDEO, NOT_PRESENT <= desc && desc <= INDEX16, "Invalid texture coordinates description!\n(desc = %d)", desc);
_assert_msg_(VIDEO, FORMAT_UBYTE <= format && format <= FORMAT_FLOAT, "Invalid texture coordinates format!\n(format = %d)", format);
_assert_msg_(VIDEO, 0 <= elements && elements <= 1, "Invalid number of texture coordinates elements!\n(elements = %d)", elements);
m_texCoordLoader[i] = VertexLoader_TextCoord::GetFunction(desc, format, elements);
m_VertexSize += VertexLoader_TextCoord::GetSize(desc, format, elements);
if (m_texCoordLoader[i])
AddAttributeLoader(LoadTexCoord, i);
}
// special case if only pos and tex coord 0 and tex coord input is AB11
m_TexGenSpecialCase =
@ -241,87 +89,122 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
m_SetupUnit->Init(primitiveType);
}
template <typename T, typename I>
static T ReadNormalized(I value)
{
T casted = (T) value;
if (!std::numeric_limits<T>::is_integer && std::numeric_limits<I>::is_integer)
{
// normalize if non-float is converted to a float
casted *= (T) (1.0 / std::numeric_limits<I>::max());
}
return casted;
}
template <typename T, bool swap = false>
static void ReadVertexAttribute(T* dst, DataReader src, const AttributeFormat& format, int base_component, int max_components, bool reverse)
{
if (format.enable)
{
src.Skip(format.offset);
src.Skip(base_component * (1<<(format.type>>1)));
for (int i = 0; i < std::min(format.components - base_component, max_components); i++)
{
int i_dst = reverse ? max_components - i - 1 : i;
switch (format.type)
{
case VAR_UNSIGNED_BYTE:
dst[i_dst] = ReadNormalized<T, u8>(src.Read<u8, swap>());
break;
case VAR_BYTE:
dst[i_dst] = ReadNormalized<T, s8>(src.Read<s8, swap>());
break;
case VAR_UNSIGNED_SHORT:
dst[i_dst] = ReadNormalized<T, u16>(src.Read<u16, swap>());
break;
case VAR_SHORT:
dst[i_dst] = ReadNormalized<T, s16>(src.Read<s16, swap>());
break;
case VAR_FLOAT:
dst[i_dst] = ReadNormalized<T, float>(src.Read<float, swap>());
break;
}
_assert_msg_(VIDEO, !format.integer || format.type != VAR_FLOAT, "only non-float values are allowed to be streamed as integer");
}
}
}
void SWVertexLoader::ParseVertex(const PortableVertexDeclaration& vdec)
{
DataReader src(m_LoadedVertices.data(), m_LoadedVertices.data() + m_LoadedVertices.size());
ReadVertexAttribute<float>(&m_Vertex.position[0], src, vdec.position, 0, 3, false);
for (int i = 0; i < 3; i++)
{
ReadVertexAttribute<float>(&m_Vertex.normal[i][0], src, vdec.normals[i], 0, 3, false);
}
for (int i = 0; i < 2; i++)
{
ReadVertexAttribute<u8>(m_Vertex.color[i], src, vdec.colors[i], 0, 4, true);
}
for (int i = 0; i < 8; i++)
{
ReadVertexAttribute<float>(m_Vertex.texCoords[i], src, vdec.texcoords[i], 0, 2, false);
// the texmtr is stored as third component of the texCoord
if (vdec.texcoords[i].components >= 3)
{
ReadVertexAttribute<u8>(&m_Vertex.texMtx[i], src, vdec.texcoords[i], 2, 1, false);
}
}
ReadVertexAttribute<u8>(&m_Vertex.posMtx, src, vdec.posmtx, 0, 1, false);
}
void SWVertexLoader::LoadVertex()
{
for (int i = 0; i < m_NumAttributeLoaders; i++)
m_AttributeLoaders[i].loader(this, &m_Vertex, m_AttributeLoaders[i].index);
const PortableVertexDeclaration& vdec = m_CurrentLoader->GetNativeVertexDeclaration();
// reserve memory for the destination of the vertex loader
m_LoadedVertices.resize(vdec.stride + 4);
// convert the vertex from the gc format to the videocommon (hardware optimized) format
u8* old = g_video_buffer_read_ptr;
m_CurrentLoader->RunVertices(
g_main_cp_state.vtx_attr[m_attributeIndex], m_primitiveType, 1,
DataReader(g_video_buffer_read_ptr, nullptr), // src
DataReader(m_LoadedVertices.data(), m_LoadedVertices.data() + m_LoadedVertices.size()) // dst
);
g_video_buffer_read_ptr = old + m_CurrentLoader->GetVertexSize();
// parse the videocommon format to our own struct format (m_Vertex)
ParseVertex(vdec);
// transform this vertex so that it can be used for rasterization (outVertex)
OutputVertexData* outVertex = m_SetupUnit->GetVertex();
// transform input data
TransformUnit::TransformPosition(&m_Vertex, outVertex);
if (g_main_cp_state.vtx_desc.Normal != NOT_PRESENT)
{
TransformUnit::TransformNormal(&m_Vertex, m_CurrentVat->g0.NormalElements, outVertex);
}
TransformUnit::TransformColor(&m_Vertex, outVertex);
TransformUnit::TransformTexCoord(&m_Vertex, outVertex, m_TexGenSpecialCase);
// assemble and rasterize the primitive
m_SetupUnit->SetupVertex();
INCSTAT(swstats.thisFrame.numVerticesLoaded)
}
void SWVertexLoader::AddAttributeLoader(AttributeLoader loader, u8 index)
{
_assert_msg_(VIDEO, m_NumAttributeLoaders < 21, "Too many attribute loaders");
m_AttributeLoaders[m_NumAttributeLoaders].loader = loader;
m_AttributeLoaders[m_NumAttributeLoaders++].index = index;
}
void SWVertexLoader::LoadPosMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
{
vertex->posMtx = DataReadU8() & 0x3f;
}
void SWVertexLoader::LoadTexMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
{
vertex->texMtx[index] = DataReadU8() & 0x3f;
}
void SWVertexLoader::LoadPosition(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
{
g_vertex_manager_write_ptr = (u8*)&vertex->position;
vertexLoader->m_positionLoader();
}
void SWVertexLoader::LoadNormal(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
{
g_vertex_manager_write_ptr = (u8*)&vertex->normal;
vertexLoader->m_normalLoader();
}
void SWVertexLoader::LoadColor(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
{
u32 color;
g_vertex_manager_write_ptr = (u8*)&color;
colIndex = index;
vertexLoader->m_colorLoader[index]();
// rgba -> abgr
*(u32*)vertex->color[index] = Common::swap32(color);
}
void SWVertexLoader::LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
{
g_vertex_manager_write_ptr = (u8*)&vertex->texCoords[index];
tcIndex = index;
vertexLoader->m_texCoordLoader[index]();
}
void SWVertexLoader::DoState(PointerWrap &p)
{
p.DoArray(m_AttributeLoaders, sizeof m_AttributeLoaders);
p.Do(m_VertexSize);
p.Do(*m_CurrentVat);
p.Do(m_positionLoader);
p.Do(m_normalLoader);
p.DoArray(m_colorLoader, sizeof m_colorLoader);
p.Do(m_NumAttributeLoaders);
m_SetupUnit->DoState(p);
p.Do(m_TexGenSpecialCase);
}

View File

@ -9,6 +9,8 @@
#include "VideoBackends/Software/CPMemLoader.h"
#include "VideoBackends/Software/NativeVertexFormat.h"
#include "VideoCommon/VertexLoader.h"
class PointerWrap;
class SetupUnit;
@ -18,35 +20,21 @@ class SWVertexLoader
VAT* m_CurrentVat;
TPipelineFunction m_positionLoader;
TPipelineFunction m_normalLoader;
TPipelineFunction m_colorLoader[2];
TPipelineFunction m_texCoordLoader[8];
InputVertexData m_Vertex;
typedef void (*AttributeLoader)(SWVertexLoader*, InputVertexData*, u8);
struct AttrLoaderCall
{
AttributeLoader loader;
u8 index;
};
AttrLoaderCall m_AttributeLoaders[1+8+1+1+2+8];
int m_NumAttributeLoaders;
void AddAttributeLoader(AttributeLoader loader, u8 index=0);
// attribute loader functions
static void LoadPosMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
static void LoadTexMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
static void LoadPosition(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
static void LoadNormal(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
static void LoadColor(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
static void LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
void ParseVertex(const PortableVertexDeclaration& vdec);
SetupUnit *m_SetupUnit;
bool m_TexGenSpecialCase;
std::map<VertexLoaderUID, std::unique_ptr<VertexLoader>> m_VertexLoaderMap;
std::vector<u8> m_LoadedVertices;
VertexLoader* m_CurrentLoader;
u8 m_attributeIndex;
u8 m_primitiveType;
public:
SWVertexLoader();
~SWVertexLoader();

View File

@ -2,6 +2,7 @@
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include "Common/Common.h"
#include "VideoCommon/VertexManagerBase.h"