From 6b0183952564a11cd4eee42715e61ea2962caff3 Mon Sep 17 00:00:00 2001 From: degasus Date: Wed, 15 Jan 2014 21:44:46 +0100 Subject: [PATCH 1/3] VideoCommon: merge triangle+list+point index buffers We are used to render them out of order as long as everything else matches, but rendering order does matter, so we have to flush on primitive switch. This commit implements this flush. Also as we flush on primitive switch, we don't have to create three different index buffers. All indices are now stored in one buffer. This will slow down games which switch often primitive types (eg ztp), but it should be more accurate. --- .../Core/VideoBackends/D3D/VertexManager.cpp | 36 +++---- Source/Core/VideoBackends/D3D/VertexManager.h | 4 +- .../Core/VideoBackends/OGL/VertexManager.cpp | 76 +++++---------- Source/Core/VideoCommon/IndexGenerator.cpp | 96 ++++++++----------- Source/Core/VideoCommon/IndexGenerator.h | 22 ++--- Source/Core/VideoCommon/VertexManagerBase.cpp | 58 +++++++---- Source/Core/VideoCommon/VertexManagerBase.h | 16 ++-- 7 files changed, 133 insertions(+), 175 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/VertexManager.cpp b/Source/Core/VideoBackends/D3D/VertexManager.cpp index 45638dfbf1..6553a56084 100644 --- a/Source/Core/VideoBackends/D3D/VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/VertexManager.cpp @@ -36,9 +36,7 @@ void VertexManager::CreateDeviceObjects() D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); m_vertex_draw_offset = 0; - m_triangle_draw_index = 0; - m_line_draw_index = 0; - m_point_draw_index = 0; + m_index_draw_offset = 0; m_index_buffers = new PID3D11Buffer[MAX_VBUFFER_COUNT]; m_vertex_buffers = new PID3D11Buffer[MAX_VBUFFER_COUNT]; for (m_current_index_buffer = 0; m_current_index_buffer < MAX_VBUFFER_COUNT; m_current_index_buffer++) @@ -108,8 +106,7 @@ void VertexManager::PrepareDrawBuffers() m_vertex_draw_offset = m_vertex_buffer_cursor; m_vertex_buffer_cursor += vSize; - UINT iCount = IndexGenerator::GetTriangleindexLen() + - IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen(); + UINT iCount = IndexGenerator::GetIndexLen(); MapType = D3D11_MAP_WRITE_NO_OVERWRITE; if (m_index_buffer_cursor + iCount >= (IBUFFER_SIZE / sizeof(u16))) { @@ -120,13 +117,9 @@ void VertexManager::PrepareDrawBuffers() } D3D::context->Map(m_index_buffers[m_current_index_buffer], 0, MapType, 0, &map); - m_triangle_draw_index = m_index_buffer_cursor; - m_line_draw_index = m_triangle_draw_index + IndexGenerator::GetTriangleindexLen(); - m_point_draw_index = m_line_draw_index + IndexGenerator::GetLineindexLen(); - memcpy((u16*)map.pData + m_triangle_draw_index, GetTriangleIndexBuffer(), sizeof(u16) * IndexGenerator::GetTriangleindexLen()); - memcpy((u16*)map.pData + m_line_draw_index, GetLineIndexBuffer(), sizeof(u16) * IndexGenerator::GetLineindexLen()); - memcpy((u16*)map.pData + m_point_draw_index, GetPointIndexBuffer(), sizeof(u16) * IndexGenerator::GetPointindexLen()); + memcpy((u16*)map.pData + m_index_buffer_cursor, GetIndexBuffer(), sizeof(u16) * IndexGenerator::GetIndexLen()); D3D::context->Unmap(m_index_buffers[m_current_index_buffer], 0); + m_index_draw_offset = m_index_buffer_cursor; m_index_buffer_cursor += iCount; ADDSTAT(stats.thisFrame.bytesVertexStreamed, vSize); @@ -142,16 +135,13 @@ void VertexManager::Draw(UINT stride) D3D::context->IASetVertexBuffers(0, 1, &m_vertex_buffers[m_current_vertex_buffer], &stride, &m_vertex_draw_offset); D3D::context->IASetIndexBuffer(m_index_buffers[m_current_index_buffer], DXGI_FORMAT_R16_UINT, 0); - if (IndexGenerator::GetNumTriangles() > 0) + if (current_primitive_type == PRIMITIVE_TRIANGLES) { D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - D3D::context->DrawIndexed(IndexGenerator::GetTriangleindexLen(), m_triangle_draw_index, 0); + D3D::context->DrawIndexed(IndexGenerator::GetIndexLen(), m_index_draw_offset, 0); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } - // Disable culling for lines and points - if (IndexGenerator::GetNumLines() > 0 || IndexGenerator::GetNumPoints() > 0) - ((DX11::Renderer*)g_renderer)->ApplyCullDisable(); - if (IndexGenerator::GetNumLines() > 0) + else if (current_primitive_type == PRIMITIVE_LINES) { float lineWidth = float(bpmem.lineptwidth.linesize) / 6.f; float texOffset = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.lineoff]; @@ -166,14 +156,16 @@ void VertexManager::Draw(UINT stride) if (m_lineShader.SetShader(g_nativeVertexFmt->m_components, lineWidth, texOffset, vpWidth, vpHeight, texOffsetEnable)) { + ((DX11::Renderer*)g_renderer)->ApplyCullDisable(); // Disable culling for lines and points D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); - D3D::context->DrawIndexed(IndexGenerator::GetLineindexLen(), m_line_draw_index, 0); + D3D::context->DrawIndexed(IndexGenerator::GetIndexLen(), m_index_draw_offset, 0); INCSTAT(stats.thisFrame.numIndexedDrawCalls); D3D::context->GSSetShader(NULL, NULL, 0); + ((DX11::Renderer*)g_renderer)->RestoreCull(); } } - if (IndexGenerator::GetNumPoints() > 0) + else //if (current_primitive_type == PRIMITIVE_POINTS) { float pointSize = float(bpmem.lineptwidth.pointsize) / 6.f; float texOffset = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.pointoff]; @@ -188,15 +180,15 @@ void VertexManager::Draw(UINT stride) if (m_pointShader.SetShader(g_nativeVertexFmt->m_components, pointSize, texOffset, vpWidth, vpHeight, texOffsetEnable)) { + ((DX11::Renderer*)g_renderer)->ApplyCullDisable(); // Disable culling for lines and points D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); - D3D::context->DrawIndexed(IndexGenerator::GetPointindexLen(), m_point_draw_index, 0); + D3D::context->DrawIndexed(IndexGenerator::GetIndexLen(), m_index_draw_offset, 0); INCSTAT(stats.thisFrame.numIndexedDrawCalls); D3D::context->GSSetShader(NULL, NULL, 0); + ((DX11::Renderer*)g_renderer)->RestoreCull(); } } - if (IndexGenerator::GetNumLines() > 0 || IndexGenerator::GetNumPoints() > 0) - ((DX11::Renderer*)g_renderer)->RestoreCull(); } void VertexManager::vFlush() diff --git a/Source/Core/VideoBackends/D3D/VertexManager.h b/Source/Core/VideoBackends/D3D/VertexManager.h index b4b7aa0ef4..9440c737b2 100644 --- a/Source/Core/VideoBackends/D3D/VertexManager.h +++ b/Source/Core/VideoBackends/D3D/VertexManager.h @@ -32,11 +32,9 @@ private: u32 m_vertex_buffer_cursor; u32 m_vertex_draw_offset; u32 m_index_buffer_cursor; + u32 m_index_draw_offset; u32 m_current_vertex_buffer; u32 m_current_index_buffer; - u32 m_triangle_draw_index; - u32 m_line_draw_index; - u32 m_point_draw_index; typedef ID3D11Buffer* PID3D11Buffer; PID3D11Buffer* m_index_buffers; PID3D11Buffer* m_vertex_buffers; diff --git a/Source/Core/VideoBackends/OGL/VertexManager.cpp b/Source/Core/VideoBackends/OGL/VertexManager.cpp index f10618e7f3..fdd1fbee34 100644 --- a/Source/Core/VideoBackends/OGL/VertexManager.cpp +++ b/Source/Core/VideoBackends/OGL/VertexManager.cpp @@ -44,7 +44,7 @@ const u32 MAX_VBUFFER_SIZE = 16*1024*1024; static StreamBuffer *s_vertexBuffer; static StreamBuffer *s_indexBuffer; static size_t s_baseVertex; -static size_t s_offset[3]; +static size_t s_index_offset; VertexManager::VertexManager() { @@ -83,74 +83,44 @@ void VertexManager::DestroyDeviceObjects() void VertexManager::PrepareDrawBuffers(u32 stride) { u32 vertex_data_size = IndexGenerator::GetNumVerts() * stride; - u32 triangle_index_size = IndexGenerator::GetTriangleindexLen(); - u32 line_index_size = IndexGenerator::GetLineindexLen(); - u32 point_index_size = IndexGenerator::GetPointindexLen(); - u32 index_size = (triangle_index_size+line_index_size+point_index_size) * sizeof(u16); + u32 index_data_size = IndexGenerator::GetIndexLen() * sizeof(u16); s_vertexBuffer->Alloc(vertex_data_size, stride); size_t offset = s_vertexBuffer->Upload(GetVertexBuffer(), vertex_data_size); s_baseVertex = offset / stride; - s_indexBuffer->Alloc(index_size); - if(triangle_index_size) - { - s_offset[0] = s_indexBuffer->Upload((u8*)GetTriangleIndexBuffer(), triangle_index_size * sizeof(u16)); - } - if(line_index_size) - { - s_offset[1] = s_indexBuffer->Upload((u8*)GetLineIndexBuffer(), line_index_size * sizeof(u16)); - } - if(point_index_size) - { - s_offset[2] = s_indexBuffer->Upload((u8*)GetPointIndexBuffer(), point_index_size * sizeof(u16)); - } + s_indexBuffer->Alloc(index_data_size); + s_index_offset = s_indexBuffer->Upload((u8*)GetIndexBuffer(), index_data_size); ADDSTAT(stats.thisFrame.bytesVertexStreamed, vertex_data_size); - ADDSTAT(stats.thisFrame.bytesIndexStreamed, index_size); + ADDSTAT(stats.thisFrame.bytesIndexStreamed, index_data_size); } void VertexManager::Draw(u32 stride) { - u32 triangle_index_size = IndexGenerator::GetTriangleindexLen(); - u32 line_index_size = IndexGenerator::GetLineindexLen(); - u32 point_index_size = IndexGenerator::GetPointindexLen(); + u32 index_size = IndexGenerator::GetIndexLen(); u32 max_index = IndexGenerator::GetNumVerts(); - GLenum triangle_mode = g_ActiveConfig.backend_info.bSupportsPrimitiveRestart?GL_TRIANGLE_STRIP:GL_TRIANGLES; + GLenum primitive_mode = 0; + + switch(current_primitive_type) + { + case PRIMITIVE_POINTS: + primitive_mode = GL_POINTS; + break; + case PRIMITIVE_LINES: + primitive_mode = GL_LINES; + break; + case PRIMITIVE_TRIANGLES: + primitive_mode = g_ActiveConfig.backend_info.bSupportsPrimitiveRestart ? GL_TRIANGLE_STRIP : GL_TRIANGLES; + break; + } if(g_ogl_config.bSupportsGLBaseVertex) { - if (triangle_index_size > 0) - { - glDrawRangeElementsBaseVertex(triangle_mode, 0, max_index, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0], (GLint)s_baseVertex); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } - if (line_index_size > 0) - { - glDrawRangeElementsBaseVertex(GL_LINES, 0, max_index, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[1], (GLint)s_baseVertex); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } - if (point_index_size > 0) - { - glDrawRangeElementsBaseVertex(GL_POINTS, 0, max_index, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[2], (GLint)s_baseVertex); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } + glDrawRangeElementsBaseVertex(primitive_mode, 0, max_index, index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_index_offset, (GLint)s_baseVertex); } else { - if (triangle_index_size > 0) - { - glDrawRangeElements(triangle_mode, 0, max_index, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0]); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } - if (line_index_size > 0) - { - glDrawRangeElements(GL_LINES, 0, max_index, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[1]); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } - if (point_index_size > 0) - { - glDrawRangeElements(GL_POINTS, 0, max_index, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[2]); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } + glDrawRangeElements(primitive_mode, 0, max_index, index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_index_offset); } + INCSTAT(stats.thisFrame.numIndexedDrawCalls); } void VertexManager::vFlush() diff --git a/Source/Core/VideoCommon/IndexGenerator.cpp b/Source/Core/VideoCommon/IndexGenerator.cpp index 4b49a4db5e..f77af16a97 100644 --- a/Source/Core/VideoCommon/IndexGenerator.cpp +++ b/Source/Core/VideoCommon/IndexGenerator.cpp @@ -9,15 +9,9 @@ #include "IndexGenerator.h" //Init -u16 *IndexGenerator::Tptr; -u16 *IndexGenerator::BASETptr; -u16 *IndexGenerator::Lptr; -u16 *IndexGenerator::BASELptr; -u16 *IndexGenerator::Pptr; -u16 *IndexGenerator::BASEPptr; -u32 IndexGenerator::numT; -u32 IndexGenerator::numL; -u32 IndexGenerator::numP; +u16 *IndexGenerator::Iptr; +u16 *IndexGenerator::BASEIptr; +u32 IndexGenerator::numI; u32 IndexGenerator::index; static const u16 s_primitive_restart = -1; @@ -46,18 +40,12 @@ void IndexGenerator::Init() primitive_table[7] = &IndexGenerator::AddPoints; } -void IndexGenerator::Start(u16* Triangleptr, u16* Lineptr, u16* Pointptr) +void IndexGenerator::Start(u16* Indexptr) { - Tptr = Triangleptr; - Lptr = Lineptr; - Pptr = Pointptr; - BASETptr = Triangleptr; - BASELptr = Lineptr; - BASEPptr = Pointptr; + Iptr = Indexptr; + BASEIptr = Indexptr; index = 0; - numT = 0; - numL = 0; - numP = 0; + numI = 0; } void IndexGenerator::AddIndices(int primitive, u32 numVerts) @@ -69,13 +57,13 @@ void IndexGenerator::AddIndices(int primitive, u32 numVerts) // Triangles template __forceinline void IndexGenerator::WriteTriangle(u32 index1, u32 index2, u32 index3) { - *Tptr++ = index1; - *Tptr++ = index2; - *Tptr++ = index3; + *Iptr++ = index1; + *Iptr++ = index2; + *Iptr++ = index3; if(pr) - *Tptr++ = s_primitive_restart; + *Iptr++ = s_primitive_restart; - ++numT; + ++numI; } template void IndexGenerator::AddList(u32 const numVerts) @@ -92,10 +80,10 @@ template void IndexGenerator::AddStrip(u32 const numVerts) { for (u32 i = 0; i < numVerts; ++i) { - *Tptr++ = index + i; + *Iptr++ = index + i; } - *Tptr++ = s_primitive_restart; - numT += numVerts - 2; + *Iptr++ = s_primitive_restart; + numI += numVerts - 2; } else @@ -140,23 +128,23 @@ template void IndexGenerator::AddFan(u32 numVerts) { for(; i+3<=numVerts; i+=3) { - *Tptr++ = index + i - 1; - *Tptr++ = index + i + 0; - *Tptr++ = index; - *Tptr++ = index + i + 1; - *Tptr++ = index + i + 2; - *Tptr++ = s_primitive_restart; - numT += 3; + *Iptr++ = index + i - 1; + *Iptr++ = index + i + 0; + *Iptr++ = index; + *Iptr++ = index + i + 1; + *Iptr++ = index + i + 2; + *Iptr++ = s_primitive_restart; + numI += 3; } for(; i+2<=numVerts; i+=2) { - *Tptr++ = index + i - 1; - *Tptr++ = index + i + 0; - *Tptr++ = index; - *Tptr++ = index + i + 1; - *Tptr++ = s_primitive_restart; - numT += 2; + *Iptr++ = index + i - 1; + *Iptr++ = index + i + 0; + *Iptr++ = index; + *Iptr++ = index + i + 1; + *Iptr++ = s_primitive_restart; + numI += 2; } } @@ -190,12 +178,12 @@ template void IndexGenerator::AddQuads(u32 numVerts) { if(pr) { - *Tptr++ = index + i - 2; - *Tptr++ = index + i - 1; - *Tptr++ = index + i - 3; - *Tptr++ = index + i - 0; - *Tptr++ = s_primitive_restart; - numT += 2; + *Iptr++ = index + i - 2; + *Iptr++ = index + i - 1; + *Iptr++ = index + i - 3; + *Iptr++ = index + i - 0; + *Iptr++ = s_primitive_restart; + numI += 2; } else { @@ -216,9 +204,9 @@ void IndexGenerator::AddLineList(u32 numVerts) { for (u32 i = 1; i < numVerts; i+=2) { - *Lptr++ = index + i - 1; - *Lptr++ = index + i; - ++numL; + *Iptr++ = index + i - 1; + *Iptr++ = index + i; + ++numI; } } @@ -229,9 +217,9 @@ void IndexGenerator::AddLineStrip(u32 numVerts) { for (u32 i = 1; i < numVerts; ++i) { - *Lptr++ = index + i - 1; - *Lptr++ = index + i; - ++numL; + *Iptr++ = index + i - 1; + *Iptr++ = index + i; + ++numI; } } @@ -240,8 +228,8 @@ void IndexGenerator::AddPoints(u32 numVerts) { for (u32 i = 0; i != numVerts; ++i) { - *Pptr++ = index + i; - ++numP; + *Iptr++ = index + i; + ++numI; } } diff --git a/Source/Core/VideoCommon/IndexGenerator.h b/Source/Core/VideoCommon/IndexGenerator.h index 1f72e6e74f..c36d5f41f3 100644 --- a/Source/Core/VideoCommon/IndexGenerator.h +++ b/Source/Core/VideoCommon/IndexGenerator.h @@ -14,21 +14,17 @@ class IndexGenerator public: // Init static void Init(); - static void Start(u16 *Triangleptr,u16 *Lineptr,u16 *Pointptr); + static void Start(u16 *Indexptr); static void AddIndices(int primitive, u32 numVertices); // Interface - static u32 GetNumTriangles() {return numT;} - static u32 GetNumLines() {return numL;} - static u32 GetNumPoints() {return numP;} + static u32 GetNumIndices() {return numI;} // returns numprimitives static u32 GetNumVerts() {return index;} - static u32 GetTriangleindexLen() {return (u32)(Tptr - BASETptr);} - static u32 GetLineindexLen() {return (u32)(Lptr - BASELptr);} - static u32 GetPointindexLen() {return (u32)(Pptr - BASEPptr);} + static u32 GetIndexLen() {return (u32)(Iptr - BASEIptr);} static u32 GetRemainingIndices(); /* @@ -56,16 +52,10 @@ private: template static void WriteTriangle(u32 index1, u32 index2, u32 index3); - static u16 *Tptr; - static u16 *BASETptr; - static u16 *Lptr; - static u16 *BASELptr; - static u16 *Pptr; - static u16 *BASEPptr; + static u16 *Iptr; + static u16 *BASEIptr; // TODO: redundant variables - static u32 numT; - static u32 numL; - static u32 numP; + static u32 numI; static u32 index; }; diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp index b5285dd0e2..bce4af457e 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/VertexManagerBase.cpp @@ -21,15 +21,26 @@ u8 *VertexManager::s_pCurBufferPointer; u8 *VertexManager::s_pBaseBufferPointer; u8 *VertexManager::s_pEndBufferPointer; +PrimitiveType VertexManager::current_primitive_type; + +static const PrimitiveType primitive_from_gx[8] = { + PRIMITIVE_TRIANGLES, // GX_DRAW_QUADS + PRIMITIVE_TRIANGLES, // GX_DRAW_NONE + PRIMITIVE_TRIANGLES, // GX_DRAW_TRIANGLES + PRIMITIVE_TRIANGLES, // GX_DRAW_TRIANGLE_STRIP + PRIMITIVE_TRIANGLES, // GX_DRAW_TRIANGLE_FAN + PRIMITIVE_LINES, // GX_DRAW_LINES + PRIMITIVE_LINES, // GX_DRAW_LINE_STRIP + PRIMITIVE_POINTS, // GX_DRAW_POINTS +}; + VertexManager::VertexManager() { LocalVBuffer.resize(MAXVBUFFERSIZE); s_pCurBufferPointer = s_pBaseBufferPointer = &LocalVBuffer[0]; s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size(); - TIBuffer.resize(MAXIBUFFERSIZE); - LIBuffer.resize(MAXIBUFFERSIZE); - PIBuffer.resize(MAXIBUFFERSIZE); + LocalIBuffer.resize(MAXIBUFFERSIZE); ResetBuffer(); } @@ -41,7 +52,7 @@ VertexManager::~VertexManager() void VertexManager::ResetBuffer() { s_pCurBufferPointer = s_pBaseBufferPointer; - IndexGenerator::Start(GetTriangleIndexBuffer(), GetLineIndexBuffer(), GetPointIndexBuffer()); + IndexGenerator::Start(GetIndexBuffer()); } u32 VertexManager::GetRemainingSize() @@ -53,6 +64,12 @@ void VertexManager::PrepareForAdditionalData(int primitive, u32 count, u32 strid { u32 const needed_vertex_bytes = count * stride; + // We can't merge different kinds of primitives, so we have to flush here + if (current_primitive_type != primitive_from_gx[primitive]) + Flush(); + current_primitive_type = primitive_from_gx[primitive]; + + // Check for size in buffer, if the buffer gets full, call Flush() if (count > IndexGenerator::GetRemainingIndices() || count > GetRemainingIndices(primitive) || needed_vertex_bytes > GetRemainingSize()) { Flush(); @@ -75,27 +92,28 @@ bool VertexManager::IsFlushed() const u32 VertexManager::GetRemainingIndices(int primitive) { + u32 index_len = MAXIBUFFERSIZE - IndexGenerator::GetIndexLen(); if(g_Config.backend_info.bSupportsPrimitiveRestart) { switch (primitive) { case GX_DRAW_QUADS: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 5 * 4; + return index_len / 5 * 4; case GX_DRAW_TRIANGLES: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 4 * 3; + return index_len / 4 * 3; case GX_DRAW_TRIANGLE_STRIP: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 1 - 1; + return index_len / 1 - 1; case GX_DRAW_TRIANGLE_FAN: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 6 * 4 + 1; + return index_len / 6 * 4 + 1; case GX_DRAW_LINES: - return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()); + return index_len; case GX_DRAW_LINE_STRIP: - return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2 + 1; + return index_len / 2 + 1; case GX_DRAW_POINTS: - return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen()); + return index_len; default: return 0; @@ -106,21 +124,21 @@ u32 VertexManager::GetRemainingIndices(int primitive) switch (primitive) { case GX_DRAW_QUADS: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 6 * 4; + return index_len / 6 * 4; case GX_DRAW_TRIANGLES: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()); + return index_len; case GX_DRAW_TRIANGLE_STRIP: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2; + return index_len / 3 + 2; case GX_DRAW_TRIANGLE_FAN: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2; + return index_len / 3 + 2; case GX_DRAW_LINES: - return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()); + return index_len; case GX_DRAW_LINE_STRIP: - return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2 + 1; + return index_len / 2 + 1; case GX_DRAW_POINTS: - return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen()); + return index_len; default: return 0; @@ -167,9 +185,7 @@ void VertexManager::DoStateShared(PointerWrap& p) // and maybe other things are overlooked p.Do(LocalVBuffer); - p.Do(TIBuffer); - p.Do(LIBuffer); - p.Do(PIBuffer); + p.Do(LocalIBuffer); s_pBaseBufferPointer = &LocalVBuffer[0]; s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size(); diff --git a/Source/Core/VideoCommon/VertexManagerBase.h b/Source/Core/VideoCommon/VertexManagerBase.h index b5b13c8933..f0f8c131ee 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.h +++ b/Source/Core/VideoCommon/VertexManagerBase.h @@ -8,6 +8,12 @@ class NativeVertexFormat; class PointerWrap; +enum PrimitiveType { + PRIMITIVE_POINTS, + PRIMITIVE_LINES, + PRIMITIVE_TRIANGLES, +}; + class VertexManager { private: @@ -45,14 +51,14 @@ public: virtual void DestroyDeviceObjects(){}; protected: - u16* GetTriangleIndexBuffer() { return &TIBuffer[0]; } - u16* GetLineIndexBuffer() { return &LIBuffer[0]; } - u16* GetPointIndexBuffer() { return &PIBuffer[0]; } + u16* GetIndexBuffer() { return &LocalIBuffer[0]; } u8* GetVertexBuffer() { return &s_pBaseBufferPointer[0]; } virtual void vDoState(PointerWrap& p) { DoStateShared(p); } void DoStateShared(PointerWrap& p); + static PrimitiveType current_primitive_type; + private: bool IsFlushed() const; @@ -63,9 +69,7 @@ private: virtual void vFlush() = 0; std::vector LocalVBuffer; - std::vector TIBuffer; - std::vector LIBuffer; - std::vector PIBuffer; + std::vector LocalIBuffer; }; extern VertexManager *g_vertex_manager; From 1d6425bd5e580c396cc8f25f14207a4e97e92572 Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 16 Jan 2014 13:56:20 +0100 Subject: [PATCH 2/3] IndexGenerator: drop unused variable --- Source/Core/VideoCommon/IndexGenerator.cpp | 11 ----------- Source/Core/VideoCommon/IndexGenerator.h | 15 +-------------- 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/Source/Core/VideoCommon/IndexGenerator.cpp b/Source/Core/VideoCommon/IndexGenerator.cpp index f77af16a97..884db29aee 100644 --- a/Source/Core/VideoCommon/IndexGenerator.cpp +++ b/Source/Core/VideoCommon/IndexGenerator.cpp @@ -11,7 +11,6 @@ //Init u16 *IndexGenerator::Iptr; u16 *IndexGenerator::BASEIptr; -u32 IndexGenerator::numI; u32 IndexGenerator::index; static const u16 s_primitive_restart = -1; @@ -45,7 +44,6 @@ void IndexGenerator::Start(u16* Indexptr) Iptr = Indexptr; BASEIptr = Indexptr; index = 0; - numI = 0; } void IndexGenerator::AddIndices(int primitive, u32 numVerts) @@ -62,8 +60,6 @@ template __forceinline void IndexGenerator::WriteTriangle(u32 index1, *Iptr++ = index3; if(pr) *Iptr++ = s_primitive_restart; - - ++numI; } template void IndexGenerator::AddList(u32 const numVerts) @@ -83,7 +79,6 @@ template void IndexGenerator::AddStrip(u32 const numVerts) *Iptr++ = index + i; } *Iptr++ = s_primitive_restart; - numI += numVerts - 2; } else @@ -134,7 +129,6 @@ template void IndexGenerator::AddFan(u32 numVerts) *Iptr++ = index + i + 1; *Iptr++ = index + i + 2; *Iptr++ = s_primitive_restart; - numI += 3; } for(; i+2<=numVerts; i+=2) @@ -144,7 +138,6 @@ template void IndexGenerator::AddFan(u32 numVerts) *Iptr++ = index; *Iptr++ = index + i + 1; *Iptr++ = s_primitive_restart; - numI += 2; } } @@ -183,7 +176,6 @@ template void IndexGenerator::AddQuads(u32 numVerts) *Iptr++ = index + i - 3; *Iptr++ = index + i - 0; *Iptr++ = s_primitive_restart; - numI += 2; } else { @@ -206,7 +198,6 @@ void IndexGenerator::AddLineList(u32 numVerts) { *Iptr++ = index + i - 1; *Iptr++ = index + i; - ++numI; } } @@ -219,7 +210,6 @@ void IndexGenerator::AddLineStrip(u32 numVerts) { *Iptr++ = index + i - 1; *Iptr++ = index + i; - ++numI; } } @@ -229,7 +219,6 @@ void IndexGenerator::AddPoints(u32 numVerts) for (u32 i = 0; i != numVerts; ++i) { *Iptr++ = index + i; - ++numI; } } diff --git a/Source/Core/VideoCommon/IndexGenerator.h b/Source/Core/VideoCommon/IndexGenerator.h index c36d5f41f3..e6d1a0ba97 100644 --- a/Source/Core/VideoCommon/IndexGenerator.h +++ b/Source/Core/VideoCommon/IndexGenerator.h @@ -18,24 +18,13 @@ public: static void AddIndices(int primitive, u32 numVertices); - // Interface - static u32 GetNumIndices() {return numI;} - // returns numprimitives static u32 GetNumVerts() {return index;} static u32 GetIndexLen() {return (u32)(Iptr - BASEIptr);} static u32 GetRemainingIndices(); -/* - enum IndexPrimitiveType - { - Prim_None = 0, - Prim_List, - Prim_Strip, - Prim_Fan - }; -*/ + private: // Triangles template static void AddList(u32 numVerts); @@ -54,8 +43,6 @@ private: static u16 *Iptr; static u16 *BASEIptr; - // TODO: redundant variables - static u32 numI; static u32 index; }; From 304adc6e0ddef6411739d0fb577a63108a362c6a Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 16 Jan 2014 14:30:17 +0100 Subject: [PATCH 3/3] IndexGenerator: inline all variables As we do lots of writes to *Iptr, the compiler isn't allowed to cache any shared variable (neither index nor Iptr itself). This commit inlines Iptr + index into the index generator functions, so the compiler know that they are const. --- Source/Core/VideoCommon/IndexGenerator.cpp | 52 +++++++++++++--------- Source/Core/VideoCommon/IndexGenerator.h | 24 +++++----- 2 files changed, 42 insertions(+), 34 deletions(-) diff --git a/Source/Core/VideoCommon/IndexGenerator.cpp b/Source/Core/VideoCommon/IndexGenerator.cpp index 884db29aee..0789ec1e1a 100644 --- a/Source/Core/VideoCommon/IndexGenerator.cpp +++ b/Source/Core/VideoCommon/IndexGenerator.cpp @@ -9,13 +9,13 @@ #include "IndexGenerator.h" //Init -u16 *IndexGenerator::Iptr; +u16 *IndexGenerator::index_buffer_current; u16 *IndexGenerator::BASEIptr; -u32 IndexGenerator::index; +u32 IndexGenerator::base_index; static const u16 s_primitive_restart = -1; -static void (*primitive_table[8])(u32); +static u16* (*primitive_table[8])(u16*, u32, u32); void IndexGenerator::Init() { @@ -41,36 +41,38 @@ void IndexGenerator::Init() void IndexGenerator::Start(u16* Indexptr) { - Iptr = Indexptr; + index_buffer_current = Indexptr; BASEIptr = Indexptr; - index = 0; + base_index = 0; } void IndexGenerator::AddIndices(int primitive, u32 numVerts) { - primitive_table[primitive](numVerts); - index += numVerts; + index_buffer_current = primitive_table[primitive](index_buffer_current, numVerts, base_index); + base_index += numVerts; } // Triangles -template __forceinline void IndexGenerator::WriteTriangle(u32 index1, u32 index2, u32 index3) +template __forceinline 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 void IndexGenerator::AddList(u32 const numVerts) +template u16* IndexGenerator::AddList(u16 *Iptr, u32 const numVerts, u32 index) { for (u32 i = 2; i < numVerts; i+=3) { - WriteTriangle(index + i - 2, index + i - 1, index + i); + Iptr = WriteTriangle(Iptr, index + i - 2, index + i - 1, index + i); } + return Iptr; } -template void IndexGenerator::AddStrip(u32 const numVerts) +template u16* IndexGenerator::AddStrip(u16 *Iptr, u32 const numVerts, u32 index) { if(pr) { @@ -86,7 +88,7 @@ template void IndexGenerator::AddStrip(u32 const numVerts) bool wind = false; for (u32 i = 2; i < numVerts; ++i) { - WriteTriangle( + Iptr = WriteTriangle(Iptr, index + i - 2, index + i - !wind, index + i - wind); @@ -94,6 +96,7 @@ template void IndexGenerator::AddStrip(u32 const numVerts) wind ^= true; } } + return Iptr; } /** @@ -115,7 +118,7 @@ template void IndexGenerator::AddStrip(u32 const numVerts) * so we use 6 indices for 3 triangles */ -template void IndexGenerator::AddFan(u32 numVerts) +template u16* IndexGenerator::AddFan(u16 *Iptr, u32 numVerts, u32 index) { u32 i = 2; @@ -143,8 +146,9 @@ template void IndexGenerator::AddFan(u32 numVerts) for (; i < numVerts; ++i) { - WriteTriangle(index, index + i - 1, index + i); + Iptr = WriteTriangle(Iptr, index, index + i - 1, index + i); } + return Iptr; } /* @@ -164,7 +168,7 @@ template void IndexGenerator::AddFan(u32 numVerts) * A simple triangle has to be rendered for three vertices. * ZWW do this for sun rays */ -template void IndexGenerator::AddQuads(u32 numVerts) +template u16* IndexGenerator::AddQuads(u16 *Iptr, u32 numVerts, u32 index) { u32 i = 3; for (; i < numVerts; i+=4) @@ -179,52 +183,56 @@ template void IndexGenerator::AddQuads(u32 numVerts) } else { - WriteTriangle(index + i - 3, index + i - 2, index + i - 1); - WriteTriangle(index + i - 3, index + i - 1, index + i - 0); + 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) { - WriteTriangle(index+numVerts-3, index+numVerts-2, index+numVerts-1); + Iptr = WriteTriangle(Iptr, index+numVerts-3, index+numVerts-2, index+numVerts-1); } + return Iptr; } // Lines -void IndexGenerator::AddLineList(u32 numVerts) +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 -void IndexGenerator::AddLineStrip(u32 numVerts) +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 -void IndexGenerator::AddPoints(u32 numVerts) +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) - return max_index - index; + return max_index - base_index; } diff --git a/Source/Core/VideoCommon/IndexGenerator.h b/Source/Core/VideoCommon/IndexGenerator.h index e6d1a0ba97..4b9a0fee3c 100644 --- a/Source/Core/VideoCommon/IndexGenerator.h +++ b/Source/Core/VideoCommon/IndexGenerator.h @@ -19,31 +19,31 @@ public: static void AddIndices(int primitive, u32 numVertices); // returns numprimitives - static u32 GetNumVerts() {return index;} + static u32 GetNumVerts() {return base_index;} - static u32 GetIndexLen() {return (u32)(Iptr - BASEIptr);} + static u32 GetIndexLen() {return (u32)(index_buffer_current - BASEIptr);} static u32 GetRemainingIndices(); private: // Triangles - template static void AddList(u32 numVerts); - template static void AddStrip(u32 numVerts); - template static void AddFan(u32 numVerts); - template static void AddQuads(u32 numVerts); + 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); // Lines - static void AddLineList(u32 numVerts); - static void AddLineStrip(u32 numVerts); + static u16* AddLineList(u16 *Iptr, u32 numVerts, u32 index); + static u16* AddLineStrip(u16 *Iptr, u32 numVerts, u32 index); // Points - static void AddPoints(u32 numVerts); + static u16* AddPoints(u16 *Iptr, u32 numVerts, u32 index); - template static void WriteTriangle(u32 index1, u32 index2, u32 index3); + template static u16* WriteTriangle(u16 *Iptr, u32 index1, u32 index2, u32 index3); - static u16 *Iptr; + static u16 *index_buffer_current; static u16 *BASEIptr; - static u32 index; + static u32 base_index; }; #endif // _INDEXGENERATOR_H