From d5eeb9b7136982ddfdc43213ea9051d15e112722 Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 7 Dec 2014 21:51:45 +0100 Subject: [PATCH] VideoSW: rewrite VertexLoader to use the VideoCommon one --- .../VideoBackends/Software/SWVertexLoader.cpp | 329 ++++++------------ .../VideoBackends/Software/SWVertexLoader.h | 32 +- Source/Core/VideoCommon/VertexLoaderUtils.h | 1 + 3 files changed, 117 insertions(+), 245 deletions(-) diff --git a/Source/Core/VideoBackends/Software/SWVertexLoader.cpp b/Source/Core/VideoBackends/Software/SWVertexLoader.cpp index d847f87cfe..ec53bc6c3b 100644 --- a/Source/Core/VideoBackends/Software/SWVertexLoader.cpp +++ b/Source/Core/VideoBackends/Software/SWVertexLoader.cpp @@ -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(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 +static T ReadNormalized(I value) +{ + T casted = (T) value; + if (!std::numeric_limits::is_integer && std::numeric_limits::is_integer) + { + // normalize if non-float is converted to a float + casted *= (T) (1.0 / std::numeric_limits::max()); + } + return casted; +} + +template +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(src.Read()); + break; + case VAR_BYTE: + dst[i_dst] = ReadNormalized(src.Read()); + break; + case VAR_UNSIGNED_SHORT: + dst[i_dst] = ReadNormalized(src.Read()); + break; + case VAR_SHORT: + dst[i_dst] = ReadNormalized(src.Read()); + break; + case VAR_FLOAT: + dst[i_dst] = ReadNormalized(src.Read()); + 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(&m_Vertex.position[0], src, vdec.position, 0, 3, false); + + for (int i = 0; i < 3; i++) + { + ReadVertexAttribute(&m_Vertex.normal[i][0], src, vdec.normals[i], 0, 3, false); + } + + for (int i = 0; i < 2; i++) + { + ReadVertexAttribute(m_Vertex.color[i], src, vdec.colors[i], 0, 4, true); + } + + for (int i = 0; i < 8; i++) + { + ReadVertexAttribute(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(&m_Vertex.texMtx[i], src, vdec.texcoords[i], 2, 1, false); + } + } + + ReadVertexAttribute(&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); } diff --git a/Source/Core/VideoBackends/Software/SWVertexLoader.h b/Source/Core/VideoBackends/Software/SWVertexLoader.h index c860f66fdc..4a5d38d52a 100644 --- a/Source/Core/VideoBackends/Software/SWVertexLoader.h +++ b/Source/Core/VideoBackends/Software/SWVertexLoader.h @@ -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> m_VertexLoaderMap; + std::vector m_LoadedVertices; + VertexLoader* m_CurrentLoader; + + u8 m_attributeIndex; + u8 m_primitiveType; + public: SWVertexLoader(); ~SWVertexLoader(); diff --git a/Source/Core/VideoCommon/VertexLoaderUtils.h b/Source/Core/VideoCommon/VertexLoaderUtils.h index f9befb8444..da830d22ef 100644 --- a/Source/Core/VideoCommon/VertexLoaderUtils.h +++ b/Source/Core/VideoCommon/VertexLoaderUtils.h @@ -2,6 +2,7 @@ // Licensed under GPLv2 // Refer to the license.txt file included. +#pragma once #include "Common/Common.h" #include "VideoCommon/VertexManagerBase.h"