diff options
| author | degasus <wickmarkus@web.de> | 2014-12-07 21:51:45 +0100 |
|---|---|---|
| committer | degasus <wickmarkus@web.de> | 2014-12-13 10:29:08 +0100 |
| commit | d5eeb9b7136982ddfdc43213ea9051d15e112722 (patch) | |
| tree | 56b40102beb4645ff5142d8e8718ef4ca187b274 /Source/Core/VideoBackends/Software/SWVertexLoader.cpp | |
| parent | d02eb3ca59c8ca435aae617ff1484525c796a330 (diff) | |
VideoSW: rewrite VertexLoader to use the VideoCommon one
Diffstat (limited to 'Source/Core/VideoBackends/Software/SWVertexLoader.cpp')
| -rw-r--r-- | Source/Core/VideoBackends/Software/SWVertexLoader.cpp | 319 |
1 files changed, 101 insertions, 218 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]; - - 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); - - //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 - }; - - // 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}; - - // 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 + m_attributeIndex = attributeIndex; + m_primitiveType = primitiveType; + + 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) + { + 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); + } + + m_VertexSize = m_CurrentLoader->GetVertexSize(); + m_CurrentVat = &g_main_cp_state.vtx_attr[m_attributeIndex]; + + // 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,211 +78,133 @@ 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) + + + // special case if only pos and tex coord 0 and tex coord input is AB11 + m_TexGenSpecialCase = + ((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> +static T ReadNormalized(I value) +{ + T casted = (T) value; + if (!std::numeric_limits<T>::is_integer && std::numeric_limits<I>::is_integer) { - AddAttributeLoader(LoadPosMtx); - m_VertexSize++; + // normalize if non-float is converted to a float + casted *= (T) (1.0 / std::numeric_limits<I>::max()); } + return casted; +} - for (int i = 0; i < 8; ++i) +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) { - if (tmDesc[i] != NOT_PRESENT) + 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++) { - AddAttributeLoader(LoadTexMtx, i); - m_VertexSize++; + 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"); } } +} - // 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); +void SWVertexLoader::ParseVertex(const PortableVertexDeclaration& vdec) +{ + DataReader src(m_LoadedVertices.data(), m_LoadedVertices.data() + m_LoadedVertices.size()); - m_normalLoader = VertexLoader_Normal::GetFunction(g_main_cp_state.vtx_desc.Normal, - m_CurrentVat->g0.NormalFormat, m_CurrentVat->g0.NormalElements, m_CurrentVat->g0.NormalIndex3); + ReadVertexAttribute<float>(&m_Vertex.position[0], src, vdec.position, 0, 3, false); - if (m_normalLoader == nullptr) - { - ERROR_LOG(VIDEO, "VertexLoader_Normal::GetFunction returned zero!"); - } - AddAttributeLoader(LoadNormal); + 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++) { - 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; - } + ReadVertexAttribute<u8>(m_Vertex.color[i], src, vdec.colors[i], 0, 4, true); } - // 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); - } + ReadVertexAttribute<float>(m_Vertex.texCoords[i], src, vdec.texcoords[i], 0, 2, false); - // special case if only pos and tex coord 0 and tex coord input is AB11 - m_TexGenSpecialCase = - ((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); + // 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); + } + } - m_SetupUnit->Init(primitiveType); + 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(); - OutputVertexData* outVertex = m_SetupUnit->GetVertex(); + // reserve memory for the destination of the vertex loader + m_LoadedVertices.resize(vdec.stride + 4); - // transform input data - TransformUnit::TransformPosition(&m_Vertex, outVertex); + // 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(); + 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); } |
