mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-21 13:20:27 -06:00
VideoSW: Use more VideoCommon
Now we require lots of empty functions, but this removes by far more duplicated code.
This commit is contained in:
@ -7,22 +7,40 @@
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#include "VideoBackends/Software/CPMemLoader.h"
|
||||
#include "VideoBackends/Software/Clipper.h"
|
||||
#include "VideoBackends/Software/DebugUtil.h"
|
||||
#include "VideoBackends/Software/NativeVertexFormat.h"
|
||||
#include "VideoBackends/Software/Rasterizer.h"
|
||||
#include "VideoBackends/Software/SetupUnit.h"
|
||||
#include "VideoBackends/Software/SWStatistics.h"
|
||||
#include "VideoBackends/Software/SWVertexLoader.h"
|
||||
#include "VideoBackends/Software/Tev.h"
|
||||
#include "VideoBackends/Software/TransformUnit.h"
|
||||
#include "VideoBackends/Software/XFMemLoader.h"
|
||||
|
||||
#include "VideoCommon/IndexGenerator.h"
|
||||
#include "VideoCommon/OpcodeDecoding.h"
|
||||
#include "VideoCommon/PixelShaderManager.h"
|
||||
#include "VideoCommon/Statistics.h"
|
||||
#include "VideoCommon/VertexLoaderBase.h"
|
||||
#include "VideoCommon/VertexLoaderManager.h"
|
||||
#include "VideoCommon/VertexLoaderUtils.h"
|
||||
#include "VideoCommon/XFMemory.h"
|
||||
|
||||
|
||||
SWVertexLoader::SWVertexLoader() :
|
||||
m_VertexSize(0)
|
||||
class NullNativeVertexFormat : public NativeVertexFormat
|
||||
{
|
||||
public:
|
||||
NullNativeVertexFormat(const PortableVertexDeclaration& _vtx_decl) { vtx_decl = _vtx_decl; }
|
||||
void SetupVertexPointers() override {}
|
||||
};
|
||||
|
||||
NativeVertexFormat* SWVertexLoader::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl)
|
||||
{
|
||||
return new NullNativeVertexFormat(vtx_decl);
|
||||
}
|
||||
|
||||
SWVertexLoader::SWVertexLoader()
|
||||
{
|
||||
LocalVBuffer.resize(MAXVBUFFERSIZE);
|
||||
LocalIBuffer.resize(MAXIBUFFERSIZE);
|
||||
m_SetupUnit = new SetupUnit;
|
||||
}
|
||||
|
||||
@ -32,25 +50,89 @@ SWVertexLoader::~SWVertexLoader()
|
||||
m_SetupUnit = nullptr;
|
||||
}
|
||||
|
||||
void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
||||
void SWVertexLoader::ResetBuffer(u32 stride)
|
||||
{
|
||||
memset(&m_Vertex, 0, sizeof(m_Vertex));
|
||||
s_pCurBufferPointer = s_pBaseBufferPointer = LocalVBuffer.data();
|
||||
s_pEndBufferPointer = s_pCurBufferPointer + LocalVBuffer.size();
|
||||
IndexGenerator::Start(GetIndexBuffer());
|
||||
}
|
||||
|
||||
m_attributeIndex = attributeIndex;
|
||||
void SWVertexLoader::vFlush(bool useDstAlpha)
|
||||
{
|
||||
DebugUtil::OnObjectBegin();
|
||||
|
||||
VertexLoaderUID uid(g_main_cp_state.vtx_desc, g_main_cp_state.vtx_attr[m_attributeIndex]);
|
||||
m_CurrentLoader = m_VertexLoaderMap[uid].get();
|
||||
|
||||
if (!m_CurrentLoader)
|
||||
u8 primitiveType = 0;
|
||||
switch (current_primitive_type)
|
||||
{
|
||||
m_VertexLoaderMap[uid] = VertexLoaderBase::CreateVertexLoader(g_main_cp_state.vtx_desc, g_main_cp_state.vtx_attr[m_attributeIndex]);
|
||||
m_CurrentLoader = m_VertexLoaderMap[uid].get();
|
||||
case PRIMITIVE_POINTS:
|
||||
primitiveType = GX_DRAW_POINTS;
|
||||
break;
|
||||
case PRIMITIVE_LINES:
|
||||
primitiveType = GX_DRAW_LINES;
|
||||
break;
|
||||
case PRIMITIVE_TRIANGLES:
|
||||
primitiveType = g_ActiveConfig.backend_info.bSupportsPrimitiveRestart ? GX_DRAW_TRIANGLE_STRIP : GX_DRAW_TRIANGLES;
|
||||
break;
|
||||
}
|
||||
|
||||
m_VertexSize = m_CurrentLoader->m_VertexSize;
|
||||
m_CurrentVat = &g_main_cp_state.vtx_attr[m_attributeIndex];
|
||||
m_SetupUnit->Init(primitiveType);
|
||||
|
||||
// set all states with are stored within video sw
|
||||
Clipper::SetViewOffset();
|
||||
Rasterizer::SetScissor();
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Rasterizer::SetTevReg(i, Tev::RED_C, false, PixelShaderManager::constants.colors[i][0]);
|
||||
Rasterizer::SetTevReg(i, Tev::GRN_C, false, PixelShaderManager::constants.colors[i][1]);
|
||||
Rasterizer::SetTevReg(i, Tev::BLU_C, false, PixelShaderManager::constants.colors[i][2]);
|
||||
Rasterizer::SetTevReg(i, Tev::ALP_C, false, PixelShaderManager::constants.colors[i][3]);
|
||||
Rasterizer::SetTevReg(i, Tev::RED_C, true, PixelShaderManager::constants.kcolors[i][0]);
|
||||
Rasterizer::SetTevReg(i, Tev::GRN_C, true, PixelShaderManager::constants.kcolors[i][1]);
|
||||
Rasterizer::SetTevReg(i, Tev::BLU_C, true, PixelShaderManager::constants.kcolors[i][2]);
|
||||
Rasterizer::SetTevReg(i, Tev::ALP_C, true, PixelShaderManager::constants.kcolors[i][3]);
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < IndexGenerator::GetIndexLen(); i++)
|
||||
{
|
||||
u16 index = LocalIBuffer[i];
|
||||
|
||||
if (index == 0xffff)
|
||||
{
|
||||
// primitive restart
|
||||
m_SetupUnit->Init(primitiveType);
|
||||
continue;
|
||||
}
|
||||
memset(&m_Vertex, 0, sizeof(m_Vertex));
|
||||
|
||||
// Super Mario Sunshine requires those to be zero for those debug boxes.
|
||||
memset(&m_Vertex.color, 0, sizeof(m_Vertex.color));
|
||||
|
||||
// parse the videocommon format to our own struct format (m_Vertex)
|
||||
SetFormat(g_main_cp_state.last_id, primitiveType);
|
||||
ParseVertex(VertexLoaderManager::GetCurrentVertexFormat()->GetVertexDeclaration(), index);
|
||||
|
||||
// transform this vertex so that it can be used for rasterization (outVertex)
|
||||
OutputVertexData* outVertex = m_SetupUnit->GetVertex();
|
||||
TransformUnit::TransformPosition(&m_Vertex, outVertex);
|
||||
memset(&outVertex->normal, 0, sizeof(outVertex->normal));
|
||||
if (VertexLoaderManager::g_current_components & VB_HAS_NRM0)
|
||||
{
|
||||
TransformUnit::TransformNormal(&m_Vertex, (VertexLoaderManager::g_current_components & VB_HAS_NRM2) != 0, outVertex);
|
||||
}
|
||||
TransformUnit::TransformColor(&m_Vertex, outVertex);
|
||||
TransformUnit::TransformTexCoord(&m_Vertex, outVertex, m_TexGenSpecialCase);
|
||||
|
||||
// assemble and rasterize the primitive
|
||||
m_SetupUnit->SetupVertex();
|
||||
|
||||
INCSTAT(stats.thisFrame.numVerticesLoaded)
|
||||
}
|
||||
|
||||
DebugUtil::OnObjectEnd();
|
||||
}
|
||||
|
||||
void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
||||
{
|
||||
// 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 ||
|
||||
@ -81,8 +163,6 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
||||
((g_main_cp_state.vtx_desc.Hex & 0x60600L) == g_main_cp_state.vtx_desc.Hex) && // only pos and tex coord 0
|
||||
(g_main_cp_state.vtx_desc.Tex0Coord != NOT_PRESENT) &&
|
||||
(xfmem.texMtxInfo[0].projection == XF_TEXPROJ_ST);
|
||||
|
||||
m_SetupUnit->Init(primitiveType);
|
||||
}
|
||||
|
||||
template <typename T, typename I>
|
||||
@ -138,9 +218,10 @@ static void ReadVertexAttribute(T* dst, DataReader src, const AttributeFormat& f
|
||||
}
|
||||
}
|
||||
|
||||
void SWVertexLoader::ParseVertex(const PortableVertexDeclaration& vdec)
|
||||
void SWVertexLoader::ParseVertex(const PortableVertexDeclaration& vdec, int index)
|
||||
{
|
||||
DataReader src(m_LoadedVertices.data(), m_LoadedVertices.data() + m_LoadedVertices.size());
|
||||
DataReader src(LocalVBuffer.data(), LocalVBuffer.data() + LocalVBuffer.size());
|
||||
src.Skip(index * vdec.stride);
|
||||
|
||||
ReadVertexAttribute<float>(&m_Vertex.position[0], src, vdec.position, 0, 3, false);
|
||||
|
||||
@ -167,52 +248,3 @@ void SWVertexLoader::ParseVertex(const PortableVertexDeclaration& vdec)
|
||||
|
||||
ReadVertexAttribute<u8>(&m_Vertex.posMtx, src, vdec.posmtx, 0, 1, false);
|
||||
}
|
||||
|
||||
void SWVertexLoader::LoadVertex()
|
||||
{
|
||||
const PortableVertexDeclaration& vdec = m_CurrentLoader->m_native_vtx_decl;
|
||||
|
||||
// reserve memory for the destination of the vertex loader
|
||||
m_LoadedVertices.resize(vdec.stride + 4);
|
||||
|
||||
VertexLoaderManager::UpdateVertexArrayPointers();
|
||||
|
||||
// convert the vertex from the gc format to the videocommon (hardware optimized) format
|
||||
u8* old = g_video_buffer_read_ptr;
|
||||
int converted_vertices = m_CurrentLoader->RunVertices(
|
||||
DataReader(g_video_buffer_read_ptr, nullptr), // src
|
||||
DataReader(m_LoadedVertices.data(), m_LoadedVertices.data() + m_LoadedVertices.size()), // dst
|
||||
1 // vertices
|
||||
);
|
||||
g_video_buffer_read_ptr = old + m_CurrentLoader->m_VertexSize;
|
||||
|
||||
if (converted_vertices == 0)
|
||||
return;
|
||||
|
||||
// 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();
|
||||
TransformUnit::TransformPosition(&m_Vertex, outVertex);
|
||||
memset(&outVertex->normal, 0, sizeof(outVertex->normal));
|
||||
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::DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(m_VertexSize);
|
||||
p.Do(*m_CurrentVat);
|
||||
m_SetupUnit->DoState(p);
|
||||
p.Do(m_TexGenSpecialCase);
|
||||
}
|
||||
|
Reference in New Issue
Block a user