diff options
| author | Ryan Houdek <Sonicadvance1@gmail.com> | 2014-12-22 03:02:02 -0600 |
|---|---|---|
| committer | Ryan Houdek <Sonicadvance1@gmail.com> | 2014-12-22 03:02:02 -0600 |
| commit | 5af426df33c744870d7c232662bed49f1de694d0 (patch) | |
| tree | cea8ca1b7459079107832ec0ec771ab9ca144a85 /Source/Core/VideoCommon/VertexLoader.cpp | |
| parent | a00aa1a7703aa985274e89bde4065f4a376530f3 (diff) | |
| parent | 1efd00227d3c38458d44193c4aa554f70a3b9c55 (diff) | |
Merge pull request #1713 from degasus/vertex-loader
virtual vertex loader
Diffstat (limited to 'Source/Core/VideoCommon/VertexLoader.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/VertexLoader.cpp | 286 |
1 files changed, 74 insertions, 212 deletions
diff --git a/Source/Core/VideoCommon/VertexLoader.cpp b/Source/Core/VideoCommon/VertexLoader.cpp index f293564e85..e2a2073ccf 100644 --- a/Source/Core/VideoCommon/VertexLoader.cpp +++ b/Source/Core/VideoCommon/VertexLoader.cpp @@ -4,7 +4,6 @@ #include "Common/CommonTypes.h" #include "Common/MemoryUtil.h" -#include "Common/StringUtil.h" #include "Common/x64ABI.h" #include "Common/x64Emitter.h" @@ -30,97 +29,88 @@ #define inline #endif -// Matrix components are first in GC format but later in PC format - we need to store it temporarily -// when decoding each vertex. -static u8 s_curposmtx = g_main_cp_state.matrix_index_a.PosNormalMtxIdx; -static u8 s_curtexmtx[8]; -static int s_texmtxwrite = 0; -static int s_texmtxread = 0; - -// Vertex loaders read these. Although the scale ones should be baked into the shader. -int tcIndex; -int colIndex; -int colElements[2]; -// Duplicated (4x and 2x respectively) and used in SSE code in the vertex loader JIT -GC_ALIGNED128(float posScale[4]); -GC_ALIGNED64(float tcScale[8][2]); - // This pointer is used as the source/dst for all fixed function loader calls u8* g_video_buffer_read_ptr; u8* g_vertex_manager_write_ptr; -static const float fractionTable[32] = { - 1.0f / (1U << 0), 1.0f / (1U << 1), 1.0f / (1U << 2), 1.0f / (1U << 3), - 1.0f / (1U << 4), 1.0f / (1U << 5), 1.0f / (1U << 6), 1.0f / (1U << 7), - 1.0f / (1U << 8), 1.0f / (1U << 9), 1.0f / (1U << 10), 1.0f / (1U << 11), - 1.0f / (1U << 12), 1.0f / (1U << 13), 1.0f / (1U << 14), 1.0f / (1U << 15), - 1.0f / (1U << 16), 1.0f / (1U << 17), 1.0f / (1U << 18), 1.0f / (1U << 19), - 1.0f / (1U << 20), 1.0f / (1U << 21), 1.0f / (1U << 22), 1.0f / (1U << 23), - 1.0f / (1U << 24), 1.0f / (1U << 25), 1.0f / (1U << 26), 1.0f / (1U << 27), - 1.0f / (1U << 28), 1.0f / (1U << 29), 1.0f / (1U << 30), 1.0f / (1U << 31), -}; - using namespace Gen; -static void LOADERDECL PosMtx_ReadDirect_UByte() + +void* VertexLoader::operator new (size_t size) +{ + return AllocateAlignedMemory(size, 16); +} + +void VertexLoader::operator delete (void *p) +{ + FreeAlignedMemory(p); +} + +static void LOADERDECL PosMtx_ReadDirect_UByte(VertexLoader* loader) { - BoundingBox::posMtxIdx = s_curposmtx = DataReadU8() & 0x3f; - PRIM_LOG("posmtx: %d, ", s_curposmtx); + BoundingBox::posMtxIdx = loader->m_curposmtx = DataReadU8() & 0x3f; + PRIM_LOG("posmtx: %d, ", loader->m_curposmtx); } -static void LOADERDECL PosMtx_Write() +static void LOADERDECL PosMtx_Write(VertexLoader* loader) { // u8, 0, 0, 0 - DataWrite<u32>(s_curposmtx); + DataWrite<u32>(loader->m_curposmtx); } -static void LOADERDECL TexMtx_ReadDirect_UByte() +static void LOADERDECL TexMtx_ReadDirect_UByte(VertexLoader* loader) { - BoundingBox::texMtxIdx[s_texmtxread] = s_curtexmtx[s_texmtxread] = DataReadU8() & 0x3f; + BoundingBox::texMtxIdx[loader->m_texmtxread] = loader->m_curtexmtx[loader->m_texmtxread] = DataReadU8() & 0x3f; - PRIM_LOG("texmtx%d: %d, ", s_texmtxread, s_curtexmtx[s_texmtxread]); - s_texmtxread++; + PRIM_LOG("texmtx%d: %d, ", loader->m_texmtxread, loader->m_curtexmtx[loader->m_texmtxread]); + loader->m_texmtxread++; } -static void LOADERDECL TexMtx_Write_Float() +static void LOADERDECL TexMtx_Write_Float(VertexLoader* loader) { - DataWrite(float(s_curtexmtx[s_texmtxwrite++])); + DataWrite(float(loader->m_curtexmtx[loader->m_texmtxwrite++])); } -static void LOADERDECL TexMtx_Write_Float2() +static void LOADERDECL TexMtx_Write_Float2(VertexLoader* loader) { DataWrite(0.f); - DataWrite(float(s_curtexmtx[s_texmtxwrite++])); + DataWrite(float(loader->m_curtexmtx[loader->m_texmtxwrite++])); } -static void LOADERDECL TexMtx_Write_Float4() +static void LOADERDECL TexMtx_Write_Float4(VertexLoader* loader) { #if _M_SSE >= 0x200 - __m128 output = _mm_cvtsi32_ss(_mm_castsi128_ps(_mm_setzero_si128()), s_curtexmtx[s_texmtxwrite++]); + __m128 output = _mm_cvtsi32_ss(_mm_castsi128_ps(_mm_setzero_si128()), loader->m_curtexmtx[loader->m_texmtxwrite++]); _mm_storeu_ps((float*)g_vertex_manager_write_ptr, _mm_shuffle_ps(output, output, 0x45 /* 1, 1, 0, 1 */)); g_vertex_manager_write_ptr += sizeof(float) * 4; #else DataWrite(0.f); DataWrite(0.f); - DataWrite(float(s_curtexmtx[s_texmtxwrite++])); + DataWrite(float(loader->m_curtexmtx[loader->m_texmtxwrite++])); // Just to fill out with 0. DataWrite(0.f); #endif } +static void LOADERDECL SkipVertex(VertexLoader* loader) +{ + if (loader->m_vertexSkip) + { + // reset the output buffer + g_vertex_manager_write_ptr -= loader->m_native_vtx_decl.stride; + + loader->m_skippedVertices++; + } +} + VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr) +: VertexLoaderBase(vtx_desc, vtx_attr) { m_compiledCode = nullptr; - m_numLoadedVertices = 0; - m_VertexSize = 0; - m_native_vertex_format = nullptr; VertexLoader_Normal::Init(); VertexLoader_Position::Init(); VertexLoader_TextCoord::Init(); - m_VtxDesc = vtx_desc; - SetVAT(vtx_attr); - #ifdef USE_VERTEX_LOADER_JIT AllocCodeSpace(COMPILED_CODE_SIZE); CompileVertexTranslator(); @@ -130,6 +120,13 @@ VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr) CompileVertexTranslator(); #endif + // generate frac factors + m_posScale[0] = m_posScale[1] = m_posScale[2] = m_posScale[3] = 1.0f / (1U << m_VtxAttr.PosFrac); + for (int i = 0; i < 8; i++) + m_tcScale[i][0] = m_tcScale[i][1] = 1.0f / (1U << m_VtxAttr.texCoord[i].Frac); + + for (int i = 0; i < 2; i++) + m_colElements[i] = m_VtxAttr.color[i].Elements; } VertexLoader::~VertexLoader() @@ -150,11 +147,14 @@ void VertexLoader::CompileVertexTranslator() m_compiledCode = GetCodePtr(); // We only use RAX (caller saved) and RBX (callee saved). - ABI_PushRegistersAndAdjustStack({RBX}, 8); + ABI_PushRegistersAndAdjustStack({RBX, RBP}, 8); // save count MOV(64, R(RBX), R(ABI_PARAM1)); + // save loader + MOV(64, R(RBP), R(ABI_PARAM2)); + // Start loop here const u8 *loop_start = GetCodePtr(); @@ -162,17 +162,17 @@ void VertexLoader::CompileVertexTranslator() if (m_VtxDesc.Tex0Coord || m_VtxDesc.Tex1Coord || m_VtxDesc.Tex2Coord || m_VtxDesc.Tex3Coord || m_VtxDesc.Tex4Coord || m_VtxDesc.Tex5Coord || m_VtxDesc.Tex6Coord || m_VtxDesc.Tex7Coord) { - WriteSetVariable(32, &tcIndex, Imm32(0)); + WriteSetVariable(32, &m_tcIndex, Imm32(0)); } if (m_VtxDesc.Color0 || m_VtxDesc.Color1) { - WriteSetVariable(32, &colIndex, Imm32(0)); + WriteSetVariable(32, &m_colIndex, Imm32(0)); } if (m_VtxDesc.Tex0MatIdx || m_VtxDesc.Tex1MatIdx || m_VtxDesc.Tex2MatIdx || m_VtxDesc.Tex3MatIdx || m_VtxDesc.Tex4MatIdx || m_VtxDesc.Tex5MatIdx || m_VtxDesc.Tex6MatIdx || m_VtxDesc.Tex7MatIdx) { - WriteSetVariable(32, &s_texmtxwrite, Imm32(0)); - WriteSetVariable(32, &s_texmtxread, Imm32(0)); + WriteSetVariable(32, &m_texmtxwrite, Imm32(0)); + WriteSetVariable(32, &m_texmtxread, Imm32(0)); } #else // Reset pipeline @@ -404,6 +404,12 @@ void VertexLoader::CompileVertexTranslator() nat_offset += 4; } + // indexed position formats may skip a the vertex + if (m_VtxDesc.Position & 2) + { + WriteCall(SkipVertex); + } + m_native_components = components; m_native_vtx_decl.stride = nat_offset; @@ -412,7 +418,7 @@ void VertexLoader::CompileVertexTranslator() SUB(64, R(RBX), Imm8(1)); J_CC(CC_NZ, loop_start); - ABI_PopRegistersAndAdjustStack({RBX}, 8); + ABI_PopRegistersAndAdjustStack({RBX, RBP}, 8); RET(); #endif } @@ -420,6 +426,7 @@ void VertexLoader::CompileVertexTranslator() void VertexLoader::WriteCall(TPipelineFunction func) { #ifdef USE_VERTEX_LOADER_JIT + MOV(64, R(ABI_PARAM1), R(RBP)); ABI_CallFunction((const void*)func); #else m_PipelineStages[m_numPipelineStages++] = func; @@ -444,179 +451,34 @@ void VertexLoader::WriteSetVariable(int bits, void *address, OpArg value) } #endif -void VertexLoader::SetupRunVertices(const VAT& vat, int primitive, int const count) +int VertexLoader::RunVertices(int primitive, int count, DataReader src, DataReader dst) { - m_numLoadedVertices += count; + dst.WritePointer(&g_vertex_manager_write_ptr); + src.WritePointer(&g_video_buffer_read_ptr); - // Load position and texcoord scale factors. - m_VtxAttr.PosFrac = vat.g0.PosFrac; - m_VtxAttr.texCoord[0].Frac = vat.g0.Tex0Frac; - m_VtxAttr.texCoord[1].Frac = vat.g1.Tex1Frac; - m_VtxAttr.texCoord[2].Frac = vat.g1.Tex2Frac; - m_VtxAttr.texCoord[3].Frac = vat.g1.Tex3Frac; - m_VtxAttr.texCoord[4].Frac = vat.g2.Tex4Frac; - m_VtxAttr.texCoord[5].Frac = vat.g2.Tex5Frac; - m_VtxAttr.texCoord[6].Frac = vat.g2.Tex6Frac; - m_VtxAttr.texCoord[7].Frac = vat.g2.Tex7Frac; - - posScale[0] = posScale[1] = posScale[2] = posScale[3] = fractionTable[m_VtxAttr.PosFrac]; - if (m_native_components & VB_HAS_UVALL) - for (int i = 0; i < 8; i++) - tcScale[i][0] = tcScale[i][1] = fractionTable[m_VtxAttr.texCoord[i].Frac]; - for (int i = 0; i < 2; i++) - colElements[i] = m_VtxAttr.color[i].Elements; + m_numLoadedVertices += count; + m_skippedVertices = 0; // Prepare bounding box if (!g_ActiveConfig.backend_info.bSupportsBBox) - BoundingBox::Prepare(vat, primitive, m_VtxDesc, m_native_vtx_decl); -} + BoundingBox::Prepare(m_vat, primitive, m_VtxDesc, m_native_vtx_decl); -void VertexLoader::ConvertVertices ( int count ) -{ #ifdef USE_VERTEX_LOADER_JIT if (count > 0) { - ((void (*)(int))(void*)m_compiledCode)(count); + ((void (*)(int, VertexLoader* loader))(void*)m_compiledCode)(count, this); } #else for (int s = 0; s < count; s++) { - tcIndex = 0; - colIndex = 0; - s_texmtxwrite = s_texmtxread = 0; + m_tcIndex = 0; + m_colIndex = 0; + m_texmtxwrite = m_texmtxread = 0; for (int i = 0; i < m_numPipelineStages; i++) - m_PipelineStages[i](); + m_PipelineStages[i](this); PRIM_LOG("\n"); } #endif -} - -int VertexLoader::RunVertices(const VAT& vat, int primitive, int count, DataReader src, DataReader dst) -{ - dst.WritePointer(&g_vertex_manager_write_ptr); - src.WritePointer(&g_video_buffer_read_ptr); - SetupRunVertices(vat, primitive, count); - ConvertVertices(count); - return count; -} - -void VertexLoader::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; - - if (!m_VtxAttr.ByteDequant) - { - ERROR_LOG(VIDEO, "ByteDequant is set to zero"); - } -}; - -void VertexLoader::AppendToString(std::string *dest) const -{ - dest->reserve(250); - static const char *posMode[4] = { - "Inv", - "Dir", - "I8", - "I16", - }; - static const char *posFormats[5] = { - "u8", "s8", "u16", "s16", "flt", - }; - static const char *colorFormat[8] = { - "565", - "888", - "888x", - "4444", - "6666", - "8888", - "Inv", - "Inv", - }; - - dest->append(StringFromFormat("%ib skin: %i P: %i %s-%s ", - m_VertexSize, (u32)m_VtxDesc.PosMatIdx, - m_VtxAttr.PosElements ? 3 : 2, posMode[m_VtxDesc.Position], posFormats[m_VtxAttr.PosFormat])); - - if (m_VtxDesc.Normal) - { - dest->append(StringFromFormat("Nrm: %i %s-%s ", - m_VtxAttr.NormalElements, posMode[m_VtxDesc.Normal], posFormats[m_VtxAttr.NormalFormat])); - } - - u64 color_mode[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1}; - for (int i = 0; i < 2; i++) - { - if (color_mode[i]) - { - dest->append(StringFromFormat("C%i: %i %s-%s ", i, m_VtxAttr.color[i].Elements, posMode[color_mode[i]], colorFormat[m_VtxAttr.color[i].Comp])); - } - } - u64 tex_mode[8] = { - m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord, - m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, m_VtxDesc.Tex7Coord - }; - for (int i = 0; i < 8; i++) - { - if (tex_mode[i]) - { - dest->append(StringFromFormat("T%i: %i %s-%s ", - i, m_VtxAttr.texCoord[i].Elements, posMode[tex_mode[i]], posFormats[m_VtxAttr.texCoord[i].Format])); - } - } - dest->append(StringFromFormat(" - %i v\n", m_numLoadedVertices)); -} - -NativeVertexFormat* VertexLoader::GetNativeVertexFormat() -{ - if (m_native_vertex_format) - return m_native_vertex_format; - auto& native = s_native_vertex_map[m_native_vtx_decl]; - if (!native) - { - auto raw_pointer = g_vertex_manager->CreateNativeVertexFormat(); - native = std::unique_ptr<NativeVertexFormat>(raw_pointer); - native->Initialize(m_native_vtx_decl); - native->m_components = m_native_components; - } - m_native_vertex_format = native.get(); - return native.get(); + return count - m_skippedVertices; } - -std::unordered_map<PortableVertexDeclaration, std::unique_ptr<NativeVertexFormat>> VertexLoader::s_native_vertex_map; |
