From 69f2ca2230d0c51710456977a6ea9d0449ba2fc7 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 5 Dec 2019 09:36:39 -0500 Subject: [PATCH 1/4] VideoCommon/IndexGenerator: Make use of anonymous namespace More things will be moved into this in subsequent changes. While we're at it, we can also make use of std::array. --- Source/Core/VideoCommon/IndexGenerator.cpp | 44 ++++++++++++---------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/Source/Core/VideoCommon/IndexGenerator.cpp b/Source/Core/VideoCommon/IndexGenerator.cpp index 5e45cc6a5f..761d1da7e5 100644 --- a/Source/Core/VideoCommon/IndexGenerator.cpp +++ b/Source/Core/VideoCommon/IndexGenerator.cpp @@ -2,46 +2,52 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include "VideoCommon/IndexGenerator.h" + +#include #include #include #include "Common/CommonTypes.h" #include "Common/Compiler.h" #include "Common/Logging/Log.h" -#include "VideoCommon/IndexGenerator.h" #include "VideoCommon/OpcodeDecoding.h" #include "VideoCommon/VideoConfig.h" +namespace +{ +constexpr u16 s_primitive_restart = UINT16_MAX; + +using PrimitiveFunction = u16*(*)(u16*, u32, u32); +std::array s_primitive_table; +} // Anonymous namespace + // Init u16* IndexGenerator::index_buffer_current; u16* IndexGenerator::BASEIptr; u32 IndexGenerator::base_index; -static const u16 s_primitive_restart = UINT16_MAX; - -static u16* (*primitive_table[8])(u16*, u32, u32); - void IndexGenerator::Init() { if (g_Config.backend_info.bSupportsPrimitiveRestart) { - primitive_table[OpcodeDecoder::GX_DRAW_QUADS] = AddQuads; - primitive_table[OpcodeDecoder::GX_DRAW_QUADS_2] = AddQuads_nonstandard; - primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLES] = AddList; - primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip; - primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan; + s_primitive_table[OpcodeDecoder::GX_DRAW_QUADS] = AddQuads; + s_primitive_table[OpcodeDecoder::GX_DRAW_QUADS_2] = AddQuads_nonstandard; + s_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLES] = AddList; + s_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip; + s_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan; } else { - primitive_table[OpcodeDecoder::GX_DRAW_QUADS] = AddQuads; - primitive_table[OpcodeDecoder::GX_DRAW_QUADS_2] = AddQuads_nonstandard; - primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLES] = AddList; - primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip; - primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan; + s_primitive_table[OpcodeDecoder::GX_DRAW_QUADS] = AddQuads; + s_primitive_table[OpcodeDecoder::GX_DRAW_QUADS_2] = AddQuads_nonstandard; + s_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLES] = AddList; + s_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip; + s_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan; } - primitive_table[OpcodeDecoder::GX_DRAW_LINES] = &AddLineList; - primitive_table[OpcodeDecoder::GX_DRAW_LINE_STRIP] = &AddLineStrip; - primitive_table[OpcodeDecoder::GX_DRAW_POINTS] = &AddPoints; + s_primitive_table[OpcodeDecoder::GX_DRAW_LINES] = &AddLineList; + s_primitive_table[OpcodeDecoder::GX_DRAW_LINE_STRIP] = &AddLineStrip; + s_primitive_table[OpcodeDecoder::GX_DRAW_POINTS] = &AddPoints; } void IndexGenerator::Start(u16* Indexptr) @@ -53,7 +59,7 @@ void IndexGenerator::Start(u16* Indexptr) void IndexGenerator::AddIndices(int primitive, u32 numVerts) { - index_buffer_current = primitive_table[primitive](index_buffer_current, numVerts, base_index); + index_buffer_current = s_primitive_table[primitive](index_buffer_current, numVerts, base_index); base_index += numVerts; } From fb3fda775f7147c698455fe2399c9c29dd875fa6 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 5 Dec 2019 09:38:49 -0500 Subject: [PATCH 2/4] VideoCommon/IndexGenerator: Move stateless functions into anonymous namespace These don't rely on any of the static members within the IndexGenerator class, so we can make all of these functions fully internal to the translation unit. --- Source/Core/VideoCommon/IndexGenerator.cpp | 377 ++++++++++----------- Source/Core/VideoCommon/IndexGenerator.h | 22 -- 2 files changed, 186 insertions(+), 213 deletions(-) diff --git a/Source/Core/VideoCommon/IndexGenerator.cpp b/Source/Core/VideoCommon/IndexGenerator.cpp index 761d1da7e5..e0a0db8e04 100644 --- a/Source/Core/VideoCommon/IndexGenerator.cpp +++ b/Source/Core/VideoCommon/IndexGenerator.cpp @@ -9,7 +9,6 @@ #include #include "Common/CommonTypes.h" -#include "Common/Compiler.h" #include "Common/Logging/Log.h" #include "VideoCommon/OpcodeDecoding.h" #include "VideoCommon/VideoConfig.h" @@ -20,6 +19,189 @@ constexpr u16 s_primitive_restart = UINT16_MAX; using PrimitiveFunction = u16*(*)(u16*, u32, u32); std::array s_primitive_table; + +template +u16* WriteTriangle(u16* index_ptr, u32 index1, u32 index2, u32 index3) +{ + *index_ptr++ = index1; + *index_ptr++ = index2; + *index_ptr++ = index3; + if (pr) + *index_ptr++ = s_primitive_restart; + return index_ptr; +} + +template +u16* AddList(u16* index_ptr, u32 num_verts, u32 index) +{ + for (u32 i = 2; i < num_verts; i += 3) + { + index_ptr = WriteTriangle(index_ptr, index + i - 2, index + i - 1, index + i); + } + return index_ptr; +} + +template +u16* AddStrip(u16* index_ptr, u32 num_verts, u32 index) +{ + if (pr) + { + for (u32 i = 0; i < num_verts; ++i) + { + *index_ptr++ = index + i; + } + *index_ptr++ = s_primitive_restart; + } + else + { + bool wind = false; + for (u32 i = 2; i < num_verts; ++i) + { + index_ptr = WriteTriangle(index_ptr, index + i - 2, index + i - !wind, index + i - wind); + + wind ^= true; + } + } + return index_ptr; +} + +/** + * FAN simulator: + * + * 2---3 + * / \ / \ + * 1---0---4 + * + * would generate this triangles: + * 012, 023, 034 + * + * rotated (for better striping): + * 120, 302, 034 + * + * as odd ones have to winded, following strip is fine: + * 12034 + * + * so we use 6 indices for 3 triangles + */ + +template +u16* AddFan(u16* index_ptr, u32 num_verts, u32 index) +{ + u32 i = 2; + + if (pr) + { + for (; i + 3 <= num_verts; i += 3) + { + *index_ptr++ = index + i - 1; + *index_ptr++ = index + i + 0; + *index_ptr++ = index; + *index_ptr++ = index + i + 1; + *index_ptr++ = index + i + 2; + *index_ptr++ = s_primitive_restart; + } + + for (; i + 2 <= num_verts; i += 2) + { + *index_ptr++ = index + i - 1; + *index_ptr++ = index + i + 0; + *index_ptr++ = index; + *index_ptr++ = index + i + 1; + *index_ptr++ = s_primitive_restart; + } + } + + for (; i < num_verts; ++i) + { + index_ptr = WriteTriangle(index_ptr, index, index + i - 1, index + i); + } + return index_ptr; +} + +/* + * QUAD simulator + * + * 0---1 4---5 + * |\ | |\ | + * | \ | | \ | + * | \| | \| + * 3---2 7---6 + * + * 012,023, 456,467 ... + * or 120,302, 564,746 + * or as strip: 1203, 5647 + * + * Warning: + * A simple triangle has to be rendered for three vertices. + * ZWW do this for sun rays + */ +template +u16* AddQuads(u16* index_ptr, u32 num_verts, u32 index) +{ + u32 i = 3; + for (; i < num_verts; i += 4) + { + if (pr) + { + *index_ptr++ = index + i - 2; + *index_ptr++ = index + i - 1; + *index_ptr++ = index + i - 3; + *index_ptr++ = index + i - 0; + *index_ptr++ = s_primitive_restart; + } + else + { + index_ptr = WriteTriangle(index_ptr, index + i - 3, index + i - 2, index + i - 1); + index_ptr = WriteTriangle(index_ptr, index + i - 3, index + i - 1, index + i - 0); + } + } + + // three vertices remaining, so render a triangle + if (i == num_verts) + { + index_ptr = WriteTriangle(index_ptr, index + num_verts - 3, index + num_verts - 2, + index + num_verts - 1); + } + return index_ptr; +} + +template +u16* AddQuads_nonstandard(u16* index_ptr, u32 num_verts, u32 index) +{ + WARN_LOG(VIDEO, "Non-standard primitive drawing command GL_DRAW_QUADS_2"); + return AddQuads(index_ptr, num_verts, index); +} + +u16* AddLineList(u16* index_ptr, u32 num_verts, u32 index) +{ + for (u32 i = 1; i < num_verts; i += 2) + { + *index_ptr++ = index + i - 1; + *index_ptr++ = index + i; + } + return index_ptr; +} + +// Shouldn't be used as strips as LineLists are much more common +// so converting them to lists +u16* AddLineStrip(u16* index_ptr, u32 num_verts, u32 index) +{ + for (u32 i = 1; i < num_verts; ++i) + { + *index_ptr++ = index + i - 1; + *index_ptr++ = index + i; + } + return index_ptr; +} + +u16* AddPoints(u16* index_ptr, u32 num_verts, u32 index) +{ + for (u32 i = 0; i != num_verts; ++i) + { + *index_ptr++ = index + i; + } + return index_ptr; +} } // Anonymous namespace // Init @@ -45,9 +227,9 @@ void IndexGenerator::Init() s_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip; s_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan; } - s_primitive_table[OpcodeDecoder::GX_DRAW_LINES] = &AddLineList; - s_primitive_table[OpcodeDecoder::GX_DRAW_LINE_STRIP] = &AddLineStrip; - s_primitive_table[OpcodeDecoder::GX_DRAW_POINTS] = &AddPoints; + s_primitive_table[OpcodeDecoder::GX_DRAW_LINES] = AddLineList; + s_primitive_table[OpcodeDecoder::GX_DRAW_LINE_STRIP] = AddLineStrip; + s_primitive_table[OpcodeDecoder::GX_DRAW_POINTS] = AddPoints; } void IndexGenerator::Start(u16* Indexptr) @@ -70,193 +252,6 @@ void IndexGenerator::AddExternalIndices(const u16* indices, u32 num_indices, u32 base_index += num_vertices; } -// Triangles -template -DOLPHIN_FORCE_INLINE u16* IndexGenerator::WriteTriangle(u16* Iptr, u32 index1, u32 index2, - u32 index3) -{ - *Iptr++ = index1; - *Iptr++ = index2; - *Iptr++ = index3; - if (pr) - *Iptr++ = s_primitive_restart; - return Iptr; -} - -template -u16* IndexGenerator::AddList(u16* Iptr, u32 const numVerts, u32 index) -{ - for (u32 i = 2; i < numVerts; i += 3) - { - Iptr = WriteTriangle(Iptr, index + i - 2, index + i - 1, index + i); - } - return Iptr; -} - -template -u16* IndexGenerator::AddStrip(u16* Iptr, u32 const numVerts, u32 index) -{ - if (pr) - { - for (u32 i = 0; i < numVerts; ++i) - { - *Iptr++ = index + i; - } - *Iptr++ = s_primitive_restart; - } - else - { - bool wind = false; - for (u32 i = 2; i < numVerts; ++i) - { - Iptr = WriteTriangle(Iptr, index + i - 2, index + i - !wind, index + i - wind); - - wind ^= true; - } - } - return Iptr; -} - -/** - * FAN simulator: - * - * 2---3 - * / \ / \ - * 1---0---4 - * - * would generate this triangles: - * 012, 023, 034 - * - * rotated (for better striping): - * 120, 302, 034 - * - * as odd ones have to winded, following strip is fine: - * 12034 - * - * so we use 6 indices for 3 triangles - */ - -template -u16* IndexGenerator::AddFan(u16* Iptr, u32 numVerts, u32 index) -{ - u32 i = 2; - - if (pr) - { - for (; i + 3 <= numVerts; i += 3) - { - *Iptr++ = index + i - 1; - *Iptr++ = index + i + 0; - *Iptr++ = index; - *Iptr++ = index + i + 1; - *Iptr++ = index + i + 2; - *Iptr++ = s_primitive_restart; - } - - for (; i + 2 <= numVerts; i += 2) - { - *Iptr++ = index + i - 1; - *Iptr++ = index + i + 0; - *Iptr++ = index; - *Iptr++ = index + i + 1; - *Iptr++ = s_primitive_restart; - } - } - - for (; i < numVerts; ++i) - { - Iptr = WriteTriangle(Iptr, index, index + i - 1, index + i); - } - return Iptr; -} - -/* - * QUAD simulator - * - * 0---1 4---5 - * |\ | |\ | - * | \ | | \ | - * | \| | \| - * 3---2 7---6 - * - * 012,023, 456,467 ... - * or 120,302, 564,746 - * or as strip: 1203, 5647 - * - * Warning: - * A simple triangle has to be rendered for three vertices. - * ZWW do this for sun rays - */ -template -u16* IndexGenerator::AddQuads(u16* Iptr, u32 numVerts, u32 index) -{ - u32 i = 3; - for (; i < numVerts; i += 4) - { - if (pr) - { - *Iptr++ = index + i - 2; - *Iptr++ = index + i - 1; - *Iptr++ = index + i - 3; - *Iptr++ = index + i - 0; - *Iptr++ = s_primitive_restart; - } - else - { - Iptr = WriteTriangle(Iptr, index + i - 3, index + i - 2, index + i - 1); - Iptr = WriteTriangle(Iptr, index + i - 3, index + i - 1, index + i - 0); - } - } - - // three vertices remaining, so render a triangle - if (i == numVerts) - { - Iptr = - WriteTriangle(Iptr, index + numVerts - 3, index + numVerts - 2, index + numVerts - 1); - } - return Iptr; -} - -template -u16* IndexGenerator::AddQuads_nonstandard(u16* Iptr, u32 numVerts, u32 index) -{ - WARN_LOG(VIDEO, "Non-standard primitive drawing command GL_DRAW_QUADS_2"); - return AddQuads(Iptr, numVerts, index); -} - -// Lines -u16* IndexGenerator::AddLineList(u16* Iptr, u32 numVerts, u32 index) -{ - for (u32 i = 1; i < numVerts; i += 2) - { - *Iptr++ = index + i - 1; - *Iptr++ = index + i; - } - return Iptr; -} - -// shouldn't be used as strips as LineLists are much more common -// so converting them to lists -u16* IndexGenerator::AddLineStrip(u16* Iptr, u32 numVerts, u32 index) -{ - for (u32 i = 1; i < numVerts; ++i) - { - *Iptr++ = index + i - 1; - *Iptr++ = index + i; - } - return Iptr; -} - -// Points -u16* IndexGenerator::AddPoints(u16* Iptr, u32 numVerts, u32 index) -{ - for (u32 i = 0; i != numVerts; ++i) - { - *Iptr++ = index + i; - } - return Iptr; -} - u32 IndexGenerator::GetRemainingIndices() { u32 max_index = 65534; // -1 is reserved for primitive restart (ogl + dx11) diff --git a/Source/Core/VideoCommon/IndexGenerator.h b/Source/Core/VideoCommon/IndexGenerator.h index 67f16b66c1..2b91c25cb7 100644 --- a/Source/Core/VideoCommon/IndexGenerator.h +++ b/Source/Core/VideoCommon/IndexGenerator.h @@ -26,28 +26,6 @@ public: static u32 GetRemainingIndices(); private: - // Triangles - template - static u16* AddList(u16* Iptr, u32 numVerts, u32 index); - template - static u16* AddStrip(u16* Iptr, u32 numVerts, u32 index); - template - static u16* AddFan(u16* Iptr, u32 numVerts, u32 index); - template - static u16* AddQuads(u16* Iptr, u32 numVerts, u32 index); - template - static u16* AddQuads_nonstandard(u16* Iptr, u32 numVerts, u32 index); - - // Lines - static u16* AddLineList(u16* Iptr, u32 numVerts, u32 index); - static u16* AddLineStrip(u16* Iptr, u32 numVerts, u32 index); - - // Points - static u16* AddPoints(u16* Iptr, u32 numVerts, u32 index); - - template - static u16* WriteTriangle(u16* Iptr, u32 index1, u32 index2, u32 index3); - static u16* index_buffer_current; static u16* BASEIptr; static u32 base_index; From 159947ab68deea502b6a75cc7b38e461122111c9 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 5 Dec 2019 09:52:16 -0500 Subject: [PATCH 3/4] VideoCommon/IndexGenerator: Make use of if constexpr We can use if constexpr with the template functions that pass in a non-type template parameter, allowing the removal of branches that aren't taken at compile time. Compilers will generally do this by default, however, we now give a gentle prodding to the compiler if this would otherwise not be the case. --- Source/Core/VideoCommon/IndexGenerator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Core/VideoCommon/IndexGenerator.cpp b/Source/Core/VideoCommon/IndexGenerator.cpp index e0a0db8e04..338cdfa9f9 100644 --- a/Source/Core/VideoCommon/IndexGenerator.cpp +++ b/Source/Core/VideoCommon/IndexGenerator.cpp @@ -26,7 +26,7 @@ u16* WriteTriangle(u16* index_ptr, u32 index1, u32 index2, u32 index3) *index_ptr++ = index1; *index_ptr++ = index2; *index_ptr++ = index3; - if (pr) + if constexpr (pr) *index_ptr++ = s_primitive_restart; return index_ptr; } @@ -44,7 +44,7 @@ u16* AddList(u16* index_ptr, u32 num_verts, u32 index) template u16* AddStrip(u16* index_ptr, u32 num_verts, u32 index) { - if (pr) + if constexpr (pr) { for (u32 i = 0; i < num_verts; ++i) { @@ -89,7 +89,7 @@ u16* AddFan(u16* index_ptr, u32 num_verts, u32 index) { u32 i = 2; - if (pr) + if constexpr (pr) { for (; i + 3 <= num_verts; i += 3) { @@ -141,7 +141,7 @@ u16* AddQuads(u16* index_ptr, u32 num_verts, u32 index) u32 i = 3; for (; i < num_verts; i += 4) { - if (pr) + if constexpr (pr) { *index_ptr++ = index + i - 2; *index_ptr++ = index + i - 1; From 10f76746515a9a7bd8122f40c33b65813aa17b38 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 5 Dec 2019 10:01:33 -0500 Subject: [PATCH 4/4] VideoCommon/IndexGenerator: Eliminate static state Now that we've extracted all of the stateless functions that can be hidden, it's time to make the index generator a regular class with active data members. This can just be a member that sits within the vertex manager base class. By deglobalizing the state of the index generator we also get rid of the wonky dual-initializing that was going on within the OpenGL backend. Since the renderer is always initialized before the vertex manager, we now only call Init() once throughout the execution lifecycle. --- .../Core/VideoBackends/D3D/VertexManager.cpp | 2 +- .../VideoBackends/D3D12/VertexManager.cpp | 2 +- Source/Core/VideoBackends/OGL/Render.cpp | 1 - .../Core/VideoBackends/OGL/VertexManager.cpp | 2 +- .../VideoBackends/Software/SWVertexLoader.cpp | 2 +- .../VideoBackends/Vulkan/VertexManager.cpp | 2 +- Source/Core/VideoCommon/IndexGenerator.cpp | 63 +++++++++---------- Source/Core/VideoCommon/IndexGenerator.h | 25 ++++---- .../Core/VideoCommon/VertexLoaderManager.cpp | 3 +- Source/Core/VideoCommon/VertexManagerBase.cpp | 24 ++++--- Source/Core/VideoCommon/VertexManagerBase.h | 6 +- Source/Core/VideoCommon/VideoBackendBase.cpp | 1 - 12 files changed, 69 insertions(+), 64 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/VertexManager.cpp b/Source/Core/VideoBackends/D3D/VertexManager.cpp index f2a844fde2..817f58c656 100644 --- a/Source/Core/VideoBackends/D3D/VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/VertexManager.cpp @@ -210,7 +210,7 @@ void VertexManager::ResetBuffer(u32 vertex_stride) m_base_buffer_pointer = m_cpu_vertex_buffer.data(); m_cur_buffer_pointer = m_base_buffer_pointer; m_end_buffer_pointer = m_base_buffer_pointer + m_cpu_vertex_buffer.size(); - IndexGenerator::Start(m_cpu_index_buffer.data()); + m_index_generator.Start(m_cpu_index_buffer.data()); } void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, diff --git a/Source/Core/VideoBackends/D3D12/VertexManager.cpp b/Source/Core/VideoBackends/D3D12/VertexManager.cpp index 235fa43750..ec733e72c0 100644 --- a/Source/Core/VideoBackends/D3D12/VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D12/VertexManager.cpp @@ -96,7 +96,7 @@ void VertexManager::ResetBuffer(u32 vertex_stride) m_base_buffer_pointer = m_vertex_stream_buffer.GetHostPointer(); m_end_buffer_pointer = m_vertex_stream_buffer.GetCurrentHostPointer() + MAXVBUFFERSIZE; m_cur_buffer_pointer = m_vertex_stream_buffer.GetCurrentHostPointer(); - IndexGenerator::Start(reinterpret_cast(m_index_stream_buffer.GetCurrentHostPointer())); + m_index_generator.Start(reinterpret_cast(m_index_stream_buffer.GetCurrentHostPointer())); } void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 8c077d1a07..14bc05757a 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -786,7 +786,6 @@ Renderer::Renderer(std::unique_ptr main_gl_context, float backbuffer_ if (g_ActiveConfig.backend_info.bSupportsPrimitiveRestart) GLUtil::EnablePrimitiveRestart(m_main_gl_context.get()); - IndexGenerator::Init(); UpdateActiveConfig(); } diff --git a/Source/Core/VideoBackends/OGL/VertexManager.cpp b/Source/Core/VideoBackends/OGL/VertexManager.cpp index 0170a20a0b..7d14e76dd9 100644 --- a/Source/Core/VideoBackends/OGL/VertexManager.cpp +++ b/Source/Core/VideoBackends/OGL/VertexManager.cpp @@ -165,7 +165,7 @@ void VertexManager::ResetBuffer(u32 vertex_stride) m_end_buffer_pointer = buffer.first + MAXVBUFFERSIZE; buffer = m_index_buffer->Map(MAXIBUFFERSIZE * sizeof(u16)); - IndexGenerator::Start((u16*)buffer.first); + m_index_generator.Start(reinterpret_cast(buffer.first)); } void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, diff --git a/Source/Core/VideoBackends/Software/SWVertexLoader.cpp b/Source/Core/VideoBackends/Software/SWVertexLoader.cpp index 266f1046a1..9d273bb1cf 100644 --- a/Source/Core/VideoBackends/Software/SWVertexLoader.cpp +++ b/Source/Core/VideoBackends/Software/SWVertexLoader.cpp @@ -64,7 +64,7 @@ void SWVertexLoader::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_ Rasterizer::SetTevReg(i, Tev::ALP_C, PixelShaderManager::constants.kcolors[i][3]); } - for (u32 i = 0; i < IndexGenerator::GetIndexLen(); i++) + for (u32 i = 0; i < m_index_generator.GetIndexLen(); i++) { const u16 index = m_cpu_index_buffer[i]; memset(static_cast(&m_vertex), 0, sizeof(m_vertex)); diff --git a/Source/Core/VideoBackends/Vulkan/VertexManager.cpp b/Source/Core/VideoBackends/Vulkan/VertexManager.cpp index ffcf1f0927..b6c7713baa 100644 --- a/Source/Core/VideoBackends/Vulkan/VertexManager.cpp +++ b/Source/Core/VideoBackends/Vulkan/VertexManager.cpp @@ -165,7 +165,7 @@ void VertexManager::ResetBuffer(u32 vertex_stride) m_base_buffer_pointer = m_vertex_stream_buffer->GetHostPointer(); m_end_buffer_pointer = m_vertex_stream_buffer->GetCurrentHostPointer() + MAXVBUFFERSIZE; m_cur_buffer_pointer = m_vertex_stream_buffer->GetCurrentHostPointer(); - IndexGenerator::Start(reinterpret_cast(m_index_stream_buffer->GetCurrentHostPointer())); + m_index_generator.Start(reinterpret_cast(m_index_stream_buffer->GetCurrentHostPointer())); } void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, diff --git a/Source/Core/VideoCommon/IndexGenerator.cpp b/Source/Core/VideoCommon/IndexGenerator.cpp index 338cdfa9f9..68113b6fcb 100644 --- a/Source/Core/VideoCommon/IndexGenerator.cpp +++ b/Source/Core/VideoCommon/IndexGenerator.cpp @@ -17,9 +17,6 @@ namespace { constexpr u16 s_primitive_restart = UINT16_MAX; -using PrimitiveFunction = u16*(*)(u16*, u32, u32); -std::array s_primitive_table; - template u16* WriteTriangle(u16* index_ptr, u32 index1, u32 index2, u32 index3) { @@ -204,56 +201,54 @@ u16* AddPoints(u16* index_ptr, u32 num_verts, u32 index) } } // Anonymous namespace -// Init -u16* IndexGenerator::index_buffer_current; -u16* IndexGenerator::BASEIptr; -u32 IndexGenerator::base_index; - void IndexGenerator::Init() { if (g_Config.backend_info.bSupportsPrimitiveRestart) { - s_primitive_table[OpcodeDecoder::GX_DRAW_QUADS] = AddQuads; - s_primitive_table[OpcodeDecoder::GX_DRAW_QUADS_2] = AddQuads_nonstandard; - s_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLES] = AddList; - s_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip; - s_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan; + m_primitive_table[OpcodeDecoder::GX_DRAW_QUADS] = AddQuads; + m_primitive_table[OpcodeDecoder::GX_DRAW_QUADS_2] = AddQuads_nonstandard; + m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLES] = AddList; + m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip; + m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan; } else { - s_primitive_table[OpcodeDecoder::GX_DRAW_QUADS] = AddQuads; - s_primitive_table[OpcodeDecoder::GX_DRAW_QUADS_2] = AddQuads_nonstandard; - s_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLES] = AddList; - s_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip; - s_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan; + m_primitive_table[OpcodeDecoder::GX_DRAW_QUADS] = AddQuads; + m_primitive_table[OpcodeDecoder::GX_DRAW_QUADS_2] = AddQuads_nonstandard; + m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLES] = AddList; + m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip; + m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan; } - s_primitive_table[OpcodeDecoder::GX_DRAW_LINES] = AddLineList; - s_primitive_table[OpcodeDecoder::GX_DRAW_LINE_STRIP] = AddLineStrip; - s_primitive_table[OpcodeDecoder::GX_DRAW_POINTS] = AddPoints; + m_primitive_table[OpcodeDecoder::GX_DRAW_LINES] = AddLineList; + m_primitive_table[OpcodeDecoder::GX_DRAW_LINE_STRIP] = AddLineStrip; + m_primitive_table[OpcodeDecoder::GX_DRAW_POINTS] = AddPoints; } -void IndexGenerator::Start(u16* Indexptr) +void IndexGenerator::Start(u16* index_ptr) { - index_buffer_current = Indexptr; - BASEIptr = Indexptr; - base_index = 0; + m_index_buffer_current = index_ptr; + m_base_index_ptr = index_ptr; + m_base_index = 0; } -void IndexGenerator::AddIndices(int primitive, u32 numVerts) +void IndexGenerator::AddIndices(int primitive, u32 num_vertices) { - index_buffer_current = s_primitive_table[primitive](index_buffer_current, numVerts, base_index); - base_index += numVerts; + m_index_buffer_current = + m_primitive_table[primitive](m_index_buffer_current, num_vertices, m_base_index); + m_base_index += num_vertices; } void IndexGenerator::AddExternalIndices(const u16* indices, u32 num_indices, u32 num_vertices) { - std::memcpy(index_buffer_current, indices, sizeof(u16) * num_indices); - index_buffer_current += num_indices; - base_index += num_vertices; + std::memcpy(m_index_buffer_current, indices, sizeof(u16) * num_indices); + m_index_buffer_current += num_indices; + m_base_index += num_vertices; } -u32 IndexGenerator::GetRemainingIndices() +u32 IndexGenerator::GetRemainingIndices() const { - u32 max_index = 65534; // -1 is reserved for primitive restart (ogl + dx11) - return max_index - base_index; + // -1 is reserved for primitive restart (OGL + DX11) + constexpr u32 max_index = 65534; + + return max_index - m_base_index; } diff --git a/Source/Core/VideoCommon/IndexGenerator.h b/Source/Core/VideoCommon/IndexGenerator.h index 2b91c25cb7..1d9b34942a 100644 --- a/Source/Core/VideoCommon/IndexGenerator.h +++ b/Source/Core/VideoCommon/IndexGenerator.h @@ -7,26 +7,29 @@ #pragma once +#include #include "Common/CommonTypes.h" class IndexGenerator { public: - // Init - static void Init(); - static void Start(u16* Indexptr); + void Init(); + void Start(u16* index_ptr); - static void AddIndices(int primitive, u32 numVertices); + void AddIndices(int primitive, u32 num_vertices); - static void AddExternalIndices(const u16* indices, u32 num_indices, u32 num_vertices); + void AddExternalIndices(const u16* indices, u32 num_indices, u32 num_vertices); // returns numprimitives - static u32 GetNumVerts() { return base_index; } - static u32 GetIndexLen() { return (u32)(index_buffer_current - BASEIptr); } - static u32 GetRemainingIndices(); + u32 GetNumVerts() const { return m_base_index; } + u32 GetIndexLen() const { return static_cast(m_index_buffer_current - m_base_index_ptr); } + u32 GetRemainingIndices() const; private: - static u16* index_buffer_current; - static u16* BASEIptr; - static u32 base_index; + u16* m_index_buffer_current = nullptr; + u16* m_base_index_ptr = nullptr; + u32 m_base_index = 0; + + using PrimitiveFunction = u16* (*)(u16*, u32, u32); + std::array m_primitive_table{}; }; diff --git a/Source/Core/VideoCommon/VertexLoaderManager.cpp b/Source/Core/VideoCommon/VertexLoaderManager.cpp index 81b537c297..bcbf64d3d4 100644 --- a/Source/Core/VideoCommon/VertexLoaderManager.cpp +++ b/Source/Core/VideoCommon/VertexLoaderManager.cpp @@ -283,8 +283,7 @@ int RunVertices(int vtx_attr_group, int primitive, int count, DataReader src, bo count = loader->RunVertices(src, dst, count); - IndexGenerator::AddIndices(primitive, count); - + g_vertex_manager->AddIndices(primitive, count); g_vertex_manager->FlushData(count, loader->m_native_vtx_decl.stride); ADDSTAT(g_stats.this_frame.num_prims, count); diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp index f1150dc340..48d547ec5e 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/VertexManagerBase.cpp @@ -88,6 +88,7 @@ VertexManagerBase::~VertexManagerBase() = default; bool VertexManagerBase::Initialize() { + m_index_generator.Init(); return true; } @@ -96,6 +97,11 @@ u32 VertexManagerBase::GetRemainingSize() const return static_cast(m_end_buffer_pointer - m_cur_buffer_pointer); } +void VertexManagerBase::AddIndices(int primitive, u32 num_vertices) +{ + m_index_generator.AddIndices(primitive, num_vertices); +} + DataReader VertexManagerBase::PrepareForAdditionalData(int primitive, u32 count, u32 stride, bool cullall) { @@ -120,12 +126,12 @@ DataReader VertexManagerBase::PrepareForAdditionalData(int primitive, u32 count, // Check for size in buffer, if the buffer gets full, call Flush() if (!m_is_flushed && - (count > IndexGenerator::GetRemainingIndices() || count > GetRemainingIndices(primitive) || + (count > m_index_generator.GetRemainingIndices() || count > GetRemainingIndices(primitive) || needed_vertex_bytes > GetRemainingSize())) { Flush(); - if (count > IndexGenerator::GetRemainingIndices()) + if (count > m_index_generator.GetRemainingIndices()) ERROR_LOG(VIDEO, "Too little remaining index values. Use 32-bit or reset them on flush."); if (count > GetRemainingIndices(primitive)) ERROR_LOG(VIDEO, "VertexManager: Buffer not large enough for all indices! " @@ -145,7 +151,7 @@ DataReader VertexManagerBase::PrepareForAdditionalData(int primitive, u32 count, // This buffer isn't getting sent to the GPU. Just allocate it on the cpu. m_cur_buffer_pointer = m_base_buffer_pointer = m_cpu_vertex_buffer.data(); m_end_buffer_pointer = m_base_buffer_pointer + m_cpu_vertex_buffer.size(); - IndexGenerator::Start(m_cpu_index_buffer.data()); + m_index_generator.Start(m_cpu_index_buffer.data()); } else { @@ -163,9 +169,9 @@ void VertexManagerBase::FlushData(u32 count, u32 stride) m_cur_buffer_pointer += count * stride; } -u32 VertexManagerBase::GetRemainingIndices(int primitive) +u32 VertexManagerBase::GetRemainingIndices(int primitive) const { - u32 index_len = MAXIBUFFERSIZE - IndexGenerator::GetIndexLen(); + const u32 index_len = MAXIBUFFERSIZE - m_index_generator.GetIndexLen(); if (g_Config.backend_info.bSupportsPrimitiveRestart) { @@ -234,7 +240,7 @@ void VertexManagerBase::ResetBuffer(u32 vertex_stride) m_base_buffer_pointer = m_cpu_vertex_buffer.data(); m_cur_buffer_pointer = m_cpu_vertex_buffer.data(); m_end_buffer_pointer = m_base_buffer_pointer + m_cpu_vertex_buffer.size(); - IndexGenerator::Start(m_cpu_index_buffer.data()); + m_index_generator.Start(m_cpu_index_buffer.data()); } void VertexManagerBase::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, @@ -288,7 +294,7 @@ void VertexManagerBase::UploadUtilityVertices(const void* vertices, u32 vertex_s m_cur_buffer_pointer += copy_size; } if (indices) - IndexGenerator::AddExternalIndices(indices, num_indices, num_vertices); + m_index_generator.AddExternalIndices(indices, num_indices, num_vertices); CommitBuffer(num_vertices, vertex_stride, num_indices, out_base_vertex, out_base_index); } @@ -413,9 +419,9 @@ void VertexManagerBase::Flush() { // Now the vertices can be flushed to the GPU. Everything following the CommitBuffer() call // must be careful to not upload any utility vertices, as the binding will be lost otherwise. - const u32 num_indices = IndexGenerator::GetIndexLen(); + const u32 num_indices = m_index_generator.GetIndexLen(); u32 base_vertex, base_index; - CommitBuffer(IndexGenerator::GetNumVerts(), + CommitBuffer(m_index_generator.GetNumVerts(), VertexLoaderManager::GetCurrentVertexFormat()->GetVertexStride(), num_indices, &base_vertex, &base_index); diff --git a/Source/Core/VideoCommon/VertexManagerBase.h b/Source/Core/VideoCommon/VertexManagerBase.h index ba1d98c236..3c73e344b1 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.h +++ b/Source/Core/VideoCommon/VertexManagerBase.h @@ -9,6 +9,7 @@ #include "Common/CommonTypes.h" #include "Common/MathUtil.h" +#include "VideoCommon/IndexGenerator.h" #include "VideoCommon/RenderState.h" #include "VideoCommon/ShaderCache.h" @@ -65,6 +66,7 @@ public: virtual bool Initialize(); PrimitiveType GetCurrentPrimitiveType() const { return m_current_primitive_type; } + void AddIndices(int primitive, u32 num_vertices); DataReader PrepareForAdditionalData(int primitive, u32 count, u32 stride, bool cullall); void FlushData(u32 count, u32 stride); @@ -134,7 +136,7 @@ protected: virtual void DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex); u32 GetRemainingSize() const; - static u32 GetRemainingIndices(int primitive); + u32 GetRemainingIndices(int primitive) const; void CalculateZSlope(NativeVertexFormat* format); void LoadTextures(); @@ -159,6 +161,8 @@ protected: bool m_blending_state_changed = true; bool m_cull_all = false; + IndexGenerator m_index_generator; + private: // Minimum number of draws per command buffer when attempting to preempt a readback operation. static constexpr u32 MINIMUM_DRAW_CALLS_PER_COMMAND_BUFFER_FOR_READBACK = 10; diff --git a/Source/Core/VideoCommon/VideoBackendBase.cpp b/Source/Core/VideoCommon/VideoBackendBase.cpp index 8ee7eb1202..e1ed233fa1 100644 --- a/Source/Core/VideoCommon/VideoBackendBase.cpp +++ b/Source/Core/VideoCommon/VideoBackendBase.cpp @@ -270,7 +270,6 @@ void VideoBackendBase::InitializeShared() PixelEngine::Init(); BPInit(); VertexLoaderManager::Init(); - IndexGenerator::Init(); VertexShaderManager::Init(); GeometryShaderManager::Init(); PixelShaderManager::Init();