From ca8554e7d1d7c77b3c2a9ed8a7fb12de7096c67b Mon Sep 17 00:00:00 2001 From: degasus Date: Fri, 29 Mar 2013 14:27:33 +0100 Subject: [PATCH 1/9] first try of primitive restart index generator Convert all quads+triangles into trangle_strip and uses primitive restart to split them. Speed up triangle_strip, but slows down all others primitive formats. Only implemented in ogl. --- .../Core/VideoCommon/Src/IndexGenerator.cpp | 44 +++++++++---- Source/Core/VideoCommon/Src/VertexLoader.cpp | 4 ++ .../VideoCommon/Src/VertexManagerBase.cpp | 64 +++++++++++++------ Source/Core/VideoCommon/Src/VideoConfig.h | 1 + Source/Plugins/Plugin_VideoDX11/Src/main.cpp | 1 + Source/Plugins/Plugin_VideoDX9/Src/main.cpp | 1 + Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 16 ++++- .../Plugin_VideoOGL/Src/VertexManager.cpp | 4 +- 8 files changed, 102 insertions(+), 33 deletions(-) diff --git a/Source/Core/VideoCommon/Src/IndexGenerator.cpp b/Source/Core/VideoCommon/Src/IndexGenerator.cpp index aa1a971687..05097b7c9a 100644 --- a/Source/Core/VideoCommon/Src/IndexGenerator.cpp +++ b/Source/Core/VideoCommon/Src/IndexGenerator.cpp @@ -18,6 +18,7 @@ #include #include "Common.h" +#include "VideoConfig.h" #include "IndexGenerator.h" /* @@ -90,7 +91,9 @@ __forceinline void IndexGenerator::WriteTriangle(u32 index1, u32 index2, u32 ind *Tptr++ = index1; *Tptr++ = index2; *Tptr++ = index3; - + if(g_Config.backend_info.bSupportsPrimitiveRestart) + *Tptr++ = 65535; + ++numT; } @@ -105,15 +108,25 @@ void IndexGenerator::AddList(u32 const numVerts) void IndexGenerator::AddStrip(u32 const numVerts) { - bool wind = false; - for (u32 i = 2; i < numVerts; ++i) - { - WriteTriangle( - index + i - 2, - index + i - !wind, - index + i - wind); + if(g_Config.backend_info.bSupportsPrimitiveRestart) { + for (u32 i = 0; i < numVerts; ++i) + { + *Tptr++ = index + i; + } + *Tptr++ = 65535; + numT += numVerts - 2; + + } else { + bool wind = false; + for (u32 i = 2; i < numVerts; ++i) + { + WriteTriangle( + index + i - 2, + index + i - !wind, + index + i - wind); - wind ^= true; + wind ^= true; + } } } @@ -130,8 +143,17 @@ void IndexGenerator::AddQuads(u32 numVerts) auto const numQuads = numVerts / 4; for (u32 i = 0; i != numQuads; ++i) { - WriteTriangle(index + i * 4, index + i * 4 + 1, index + i * 4 + 2); - WriteTriangle(index + i * 4, index + i * 4 + 2, index + i * 4 + 3); + if(g_Config.backend_info.bSupportsPrimitiveRestart) { + *Tptr++ = index + i * 4 + 0; + *Tptr++ = index + i * 4 + 1; + *Tptr++ = index + i * 4 + 3; + *Tptr++ = index + i * 4 + 2; + *Tptr++ = 65535; + numT += 2; + } else { + WriteTriangle(index + i * 4, index + i * 4 + 1, index + i * 4 + 2); + WriteTriangle(index + i * 4, index + i * 4 + 2, index + i * 4 + 3); + } } } diff --git a/Source/Core/VideoCommon/Src/VertexLoader.cpp b/Source/Core/VideoCommon/Src/VertexLoader.cpp index 5df495a44c..74c1bd9705 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader.cpp +++ b/Source/Core/VideoCommon/Src/VertexLoader.cpp @@ -659,6 +659,10 @@ void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2) 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 diff --git a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp index 87856b5aeb..076c45e4eb 100644 --- a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp @@ -74,28 +74,54 @@ bool VertexManager::IsFlushed() const u32 VertexManager::GetRemainingIndices(int primitive) { - switch (primitive) - { - case GX_DRAW_QUADS: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 6 * 4; - case GX_DRAW_TRIANGLES: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()); - case GX_DRAW_TRIANGLE_STRIP: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2; - case GX_DRAW_TRIANGLE_FAN: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2; + + if(g_Config.backend_info.bSupportsPrimitiveRestart) { + switch (primitive) + { + case GX_DRAW_QUADS: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 5 * 4; + case GX_DRAW_TRIANGLES: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 4 * 3; + case GX_DRAW_TRIANGLE_STRIP: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 1 - 1; + case GX_DRAW_TRIANGLE_FAN: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 4 + 2; - case GX_DRAW_LINES: - return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()); - case GX_DRAW_LINE_STRIP: - return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2 + 1; + case GX_DRAW_LINES: + return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()); + case GX_DRAW_LINE_STRIP: + return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2 + 1; - case GX_DRAW_POINTS: - return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen()); + case GX_DRAW_POINTS: + return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen()); - default: - return 0; - } + default: + return 0; + } + } else { + switch (primitive) + { + case GX_DRAW_QUADS: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 6 * 4; + case GX_DRAW_TRIANGLES: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()); + case GX_DRAW_TRIANGLE_STRIP: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2; + case GX_DRAW_TRIANGLE_FAN: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2; + + case GX_DRAW_LINES: + return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()); + case GX_DRAW_LINE_STRIP: + return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2 + 1; + + case GX_DRAW_POINTS: + return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen()); + + default: + return 0; + } + } } void VertexManager::AddVertices(int primitive, u32 numVertices) diff --git a/Source/Core/VideoCommon/Src/VideoConfig.h b/Source/Core/VideoCommon/Src/VideoConfig.h index 442e95f9bf..88326346f2 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.h +++ b/Source/Core/VideoCommon/Src/VideoConfig.h @@ -153,6 +153,7 @@ struct VideoConfig bool bSupportsDualSourceBlend; // only supported by D3D11 and OpenGL bool bSupportsFormatReinterpretation; bool bSupportsPixelLighting; + bool bSupportsPrimitiveRestart; bool bSupportsGLSLUBO; // needed by pixelShaderGen, so must stay in videoCommon } backend_info; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp index 17bbdcf33c..b7c27c895c 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp @@ -96,6 +96,7 @@ void InitBackendInfo() g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsFormatReinterpretation = true; g_Config.backend_info.bSupportsPixelLighting = true; + g_Config.backend_info.bSupportsPrimitiveRestart = false; // TODO: dx11 does support it, but it isn't implemented IDXGIFactory* factory; IDXGIAdapter* ad; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp index 10fab8ea5a..0db667cc66 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp @@ -101,6 +101,7 @@ void InitBackendInfo() g_Config.backend_info.bUseRGBATextures = false; g_Config.backend_info.bUseMinimalMipCount = true; g_Config.backend_info.bSupports3DVision = true; + g_Config.backend_info.bSupportsPrimitiveRestart = false; // TODO: figure out if it does OSVERSIONINFO info; ZeroMemory(&info, sizeof(OSVERSIONINFO)); info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index 7c950e9e85..c9bfe86190 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -293,6 +293,7 @@ Renderer::Renderer() g_Config.backend_info.bSupportsDualSourceBlend = GLEW_ARB_blend_func_extended; g_Config.backend_info.bSupportsGLSLUBO = GLEW_ARB_uniform_buffer_object; + g_Config.backend_info.bSupportsPrimitiveRestart = false; //GLEW_VERSION_3_1; g_ogl_config.bSupportsGLSLCache = GLEW_ARB_get_program_binary; g_ogl_config.bSupportsGLPinnedMemory = GLEW_AMD_pinned_memory; @@ -328,9 +329,10 @@ Renderer::Renderer() g_ogl_config.gl_renderer, g_ogl_config.gl_version).c_str(), 5000); - OSD::AddMessage(StringFromFormat("Missing Extensions: %s%s%s%s%s%s%s%s", + OSD::AddMessage(StringFromFormat("Missing Extensions: %s%s%s%s%s%s%s%s%s", g_ActiveConfig.backend_info.bSupportsDualSourceBlend ? "" : "DualSourceBlend ", g_ActiveConfig.backend_info.bSupportsGLSLUBO ? "" : "UniformBuffer ", + g_ActiveConfig.backend_info.bSupportsPrimitiveRestart ? "" : "PrimitiveRestart ", g_ogl_config.bSupportsGLPinnedMemory ? "" : "PinnedMemory ", g_ogl_config.bSupportsGLSLCache ? "" : "ShaderCache ", g_ogl_config.bSupportsGLBaseVertex ? "" : "BaseVertex ", @@ -1391,6 +1393,12 @@ void Renderer::ResetAPIState() glDisable(GL_BLEND); glDepthMask(GL_FALSE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + + if(g_ActiveConfig.backend_info.bSupportsPrimitiveRestart) + { + glDisable(GL_PRIMITIVE_RESTART); + } } void Renderer::RestoreAPIState() @@ -1411,6 +1419,12 @@ void Renderer::RestoreAPIState() vm->m_last_vao = 0; TextureCache::SetStage(); + + if(g_ActiveConfig.backend_info.bSupportsPrimitiveRestart) + { + glEnable(GL_PRIMITIVE_RESTART); + glPrimitiveRestartIndex(65535); + } } void Renderer::SetGenerationMode() diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index 228eeb757d..ee8e52a265 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -127,7 +127,7 @@ void VertexManager::Draw(u32 stride) if(g_ogl_config.bSupportsGLBaseVertex) { if (triangle_index_size > 0) { - glDrawElementsBaseVertex(GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0], s_baseVertex); + glDrawElementsBaseVertex(g_ActiveConfig.backend_info.bSupportsPrimitiveRestart?GL_TRIANGLE_STRIP:GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0], s_baseVertex); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } if (line_index_size > 0) @@ -143,7 +143,7 @@ void VertexManager::Draw(u32 stride) } else { if (triangle_index_size > 0) { - glDrawElements(GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0]); + glDrawElements(g_ActiveConfig.backend_info.bSupportsPrimitiveRestart?GL_TRIANGLE_STRIP:GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0]); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } if (line_index_size > 0) From cf98ef8cf3331709396e0d1e3a25ba59c4823e8c Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 8 Apr 2013 16:34:47 +0200 Subject: [PATCH 2/9] enable primitive restart on dx11 --- Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp | 2 +- Source/Plugins/Plugin_VideoDX11/Src/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp index da8c98e19e..e573751698 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp @@ -154,7 +154,7 @@ void VertexManager::Draw(UINT stride) if (IndexGenerator::GetNumTriangles() > 0) { - D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); D3D::context->DrawIndexed(IndexGenerator::GetTriangleindexLen(), m_triangle_draw_index, 0); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } diff --git a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp index de86f3ef5b..fcc5567016 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp @@ -96,7 +96,7 @@ void InitBackendInfo() g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsFormatReinterpretation = true; g_Config.backend_info.bSupportsPixelLighting = true; - g_Config.backend_info.bSupportsPrimitiveRestart = false; // TODO: dx11 does support it, but it isn't implemented + g_Config.backend_info.bSupportsPrimitiveRestart = true; IDXGIFactory* factory; IDXGIAdapter* ad; From 80b56ddd170b12db30e636c0d5014afe20ebb784 Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 8 Apr 2013 17:22:16 +0200 Subject: [PATCH 3/9] convert triangle_fan to triangle_strip --- .../Core/VideoCommon/Src/IndexGenerator.cpp | 71 +++++++++++++++---- 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/Source/Core/VideoCommon/Src/IndexGenerator.cpp b/Source/Core/VideoCommon/Src/IndexGenerator.cpp index 05097b7c9a..edc6e90309 100644 --- a/Source/Core/VideoCommon/Src/IndexGenerator.cpp +++ b/Source/Core/VideoCommon/Src/IndexGenerator.cpp @@ -21,15 +21,6 @@ #include "VideoConfig.h" #include "IndexGenerator.h" -/* -* -QUAD simulator - -0 1 4 5 -3 2 7 6 -012023 147172 ... -*/ - //Init u16 *IndexGenerator::Tptr; u16 *IndexGenerator::BASETptr; @@ -130,24 +121,80 @@ void IndexGenerator::AddStrip(u32 const numVerts) } } +/** + * 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 + */ + void IndexGenerator::AddFan(u32 numVerts) { - for (u32 i = 2; i < numVerts; ++i) + ERROR_LOG(VIDEO, "addfan: %d vertices", numVerts); + u32 i = 2; + + if(g_Config.backend_info.bSupportsPrimitiveRestart) { + for(; i<=numVerts-3; i+=3) { + *Tptr++ = index + i - 1; + *Tptr++ = index + i + 0; + *Tptr++ = index; + *Tptr++ = index + i + 1; + *Tptr++ = index + i + 2; + *Tptr++ = 65535; + numT += 3; + } + + for(; i<=numVerts-2; i+=2) { + *Tptr++ = index + i - 1; + *Tptr++ = index + i + 0; + *Tptr++ = index; + *Tptr++ = index + i + 1; + *Tptr++ = 65535; + numT += 2; + } + } + + for (; i < numVerts; ++i) { WriteTriangle(index, index + i - 1, index + i); } } +/* + * QUAD simulator + * + * 0---1 4---5 + * |\ | |\ | + * | \ | | \ | + * | \| | \| + * 3---2 7---6 + * + * 012,023, 456,467 ... + * or 120,302, 564,746 + * or as strip: 1203, 5647 + */ void IndexGenerator::AddQuads(u32 numVerts) { auto const numQuads = numVerts / 4; for (u32 i = 0; i != numQuads; ++i) { if(g_Config.backend_info.bSupportsPrimitiveRestart) { - *Tptr++ = index + i * 4 + 0; *Tptr++ = index + i * 4 + 1; - *Tptr++ = index + i * 4 + 3; *Tptr++ = index + i * 4 + 2; + *Tptr++ = index + i * 4 + 0; + *Tptr++ = index + i * 4 + 3; *Tptr++ = 65535; numT += 2; } else { From 4dca133745129295965b245d2a07e2c82da70066 Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 8 Apr 2013 17:58:23 +0200 Subject: [PATCH 4/9] small cleanups --- Source/Core/VideoCommon/Src/IndexGenerator.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Source/Core/VideoCommon/Src/IndexGenerator.cpp b/Source/Core/VideoCommon/Src/IndexGenerator.cpp index edc6e90309..0c5c2fb91e 100644 --- a/Source/Core/VideoCommon/Src/IndexGenerator.cpp +++ b/Source/Core/VideoCommon/Src/IndexGenerator.cpp @@ -33,6 +33,8 @@ u32 IndexGenerator::numL; u32 IndexGenerator::numP; u32 IndexGenerator::index; +static const u16 s_primitive_restart = -1; + void IndexGenerator::Start(u16* Triangleptr, u16* Lineptr, u16* Pointptr) { Tptr = Triangleptr; @@ -83,7 +85,7 @@ __forceinline void IndexGenerator::WriteTriangle(u32 index1, u32 index2, u32 ind *Tptr++ = index2; *Tptr++ = index3; if(g_Config.backend_info.bSupportsPrimitiveRestart) - *Tptr++ = 65535; + *Tptr++ = s_primitive_restart; ++numT; } @@ -104,7 +106,7 @@ void IndexGenerator::AddStrip(u32 const numVerts) { *Tptr++ = index + i; } - *Tptr++ = 65535; + *Tptr++ = s_primitive_restart; numT += numVerts - 2; } else { @@ -142,7 +144,6 @@ void IndexGenerator::AddStrip(u32 const numVerts) void IndexGenerator::AddFan(u32 numVerts) { - ERROR_LOG(VIDEO, "addfan: %d vertices", numVerts); u32 i = 2; if(g_Config.backend_info.bSupportsPrimitiveRestart) { @@ -152,7 +153,7 @@ void IndexGenerator::AddFan(u32 numVerts) *Tptr++ = index; *Tptr++ = index + i + 1; *Tptr++ = index + i + 2; - *Tptr++ = 65535; + *Tptr++ = s_primitive_restart; numT += 3; } @@ -161,7 +162,7 @@ void IndexGenerator::AddFan(u32 numVerts) *Tptr++ = index + i + 0; *Tptr++ = index; *Tptr++ = index + i + 1; - *Tptr++ = 65535; + *Tptr++ = s_primitive_restart; numT += 2; } } @@ -195,7 +196,7 @@ void IndexGenerator::AddQuads(u32 numVerts) *Tptr++ = index + i * 4 + 2; *Tptr++ = index + i * 4 + 0; *Tptr++ = index + i * 4 + 3; - *Tptr++ = 65535; + *Tptr++ = s_primitive_restart; numT += 2; } else { WriteTriangle(index + i * 4, index + i * 4 + 1, index + i * 4 + 2); @@ -216,6 +217,8 @@ void IndexGenerator::AddLineList(u32 numVerts) } } +// shouldn't be used as strips as LineLists are much more common +// so converting them to lists void IndexGenerator::AddLineStrip(u32 numVerts) { for (u32 i = 1; i < numVerts; ++i) @@ -239,6 +242,6 @@ void IndexGenerator::AddPoints(u32 numVerts) u32 IndexGenerator::GetRemainingIndices() { - u32 max_index = 65535; + u32 max_index = 65534; // -1 is reserved for primitive restart (ogl + dx11) return max_index - index; } From b0108631f6ef98719f9df3fb5924766b0798f236 Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 8 Apr 2013 19:39:43 +0200 Subject: [PATCH 5/9] use templates for primitive restart --- .../Core/VideoCommon/Src/IndexGenerator.cpp | 75 ++++++++++--------- Source/Core/VideoCommon/Src/IndexGenerator.h | 11 +-- Source/Plugins/Plugin_VideoDX11/Src/main.cpp | 2 + Source/Plugins/Plugin_VideoDX9/Src/main.cpp | 2 + Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 2 +- Source/Plugins/Plugin_VideoOGL/Src/main.cpp | 2 + 6 files changed, 51 insertions(+), 43 deletions(-) diff --git a/Source/Core/VideoCommon/Src/IndexGenerator.cpp b/Source/Core/VideoCommon/Src/IndexGenerator.cpp index 0c5c2fb91e..53a3e4a351 100644 --- a/Source/Core/VideoCommon/Src/IndexGenerator.cpp +++ b/Source/Core/VideoCommon/Src/IndexGenerator.cpp @@ -35,6 +35,30 @@ u32 IndexGenerator::index; static const u16 s_primitive_restart = -1; +static void (*primitive_table[8])(u32); + +void IndexGenerator::Init() +{ + if(g_Config.backend_info.bSupportsPrimitiveRestart) + { + primitive_table[0] = IndexGenerator::AddQuads; + primitive_table[2] = IndexGenerator::AddList; + primitive_table[3] = IndexGenerator::AddStrip; + primitive_table[4] = IndexGenerator::AddFan; + } + else + { + primitive_table[0] = IndexGenerator::AddQuads; + primitive_table[2] = IndexGenerator::AddList; + primitive_table[3] = IndexGenerator::AddStrip; + primitive_table[4] = IndexGenerator::AddFan; + } + primitive_table[1] = NULL; + primitive_table[5] = &IndexGenerator::AddLineList; + primitive_table[6] = &IndexGenerator::AddLineStrip; + primitive_table[7] = &IndexGenerator::AddPoints; +} + void IndexGenerator::Start(u16* Triangleptr, u16* Lineptr, u16* Pointptr) { Tptr = Triangleptr; @@ -51,57 +75,34 @@ void IndexGenerator::Start(u16* Triangleptr, u16* Lineptr, u16* Pointptr) void IndexGenerator::AddIndices(int primitive, u32 numVerts) { - //switch (primitive) - //{ - //case GX_DRAW_QUADS: IndexGenerator::AddQuads(numVerts); break; - //case GX_DRAW_TRIANGLES: IndexGenerator::AddList(numVerts); break; - //case GX_DRAW_TRIANGLE_STRIP: IndexGenerator::AddStrip(numVerts); break; - //case GX_DRAW_TRIANGLE_FAN: IndexGenerator::AddFan(numVerts); break; - //case GX_DRAW_LINES: IndexGenerator::AddLineList(numVerts); break; - //case GX_DRAW_LINE_STRIP: IndexGenerator::AddLineStrip(numVerts); break; - //case GX_DRAW_POINTS: IndexGenerator::AddPoints(numVerts); break; - //} - - static void (*const primitive_table[])(u32) = - { - IndexGenerator::AddQuads, - NULL, - IndexGenerator::AddList, - IndexGenerator::AddStrip, - IndexGenerator::AddFan, - IndexGenerator::AddLineList, - IndexGenerator::AddLineStrip, - IndexGenerator::AddPoints, - }; - primitive_table[primitive](numVerts); index += numVerts; } // Triangles -__forceinline void IndexGenerator::WriteTriangle(u32 index1, u32 index2, u32 index3) +template __forceinline void IndexGenerator::WriteTriangle(u32 index1, u32 index2, u32 index3) { *Tptr++ = index1; *Tptr++ = index2; *Tptr++ = index3; - if(g_Config.backend_info.bSupportsPrimitiveRestart) + if(pr) *Tptr++ = s_primitive_restart; ++numT; } -void IndexGenerator::AddList(u32 const numVerts) +template void IndexGenerator::AddList(u32 const numVerts) { auto const numTris = numVerts / 3; for (u32 i = 0; i != numTris; ++i) { - WriteTriangle(index + i * 3, index + i * 3 + 1, index + i * 3 + 2); + WriteTriangle(index + i * 3, index + i * 3 + 1, index + i * 3 + 2); } } -void IndexGenerator::AddStrip(u32 const numVerts) +template void IndexGenerator::AddStrip(u32 const numVerts) { - if(g_Config.backend_info.bSupportsPrimitiveRestart) { + if(pr) { for (u32 i = 0; i < numVerts; ++i) { *Tptr++ = index + i; @@ -113,7 +114,7 @@ void IndexGenerator::AddStrip(u32 const numVerts) bool wind = false; for (u32 i = 2; i < numVerts; ++i) { - WriteTriangle( + WriteTriangle( index + i - 2, index + i - !wind, index + i - wind); @@ -142,11 +143,11 @@ void IndexGenerator::AddStrip(u32 const numVerts) * so we use 6 indices for 3 triangles */ -void IndexGenerator::AddFan(u32 numVerts) +template void IndexGenerator::AddFan(u32 numVerts) { u32 i = 2; - if(g_Config.backend_info.bSupportsPrimitiveRestart) { + if(pr) { for(; i<=numVerts-3; i+=3) { *Tptr++ = index + i - 1; *Tptr++ = index + i + 0; @@ -169,7 +170,7 @@ void IndexGenerator::AddFan(u32 numVerts) for (; i < numVerts; ++i) { - WriteTriangle(index, index + i - 1, index + i); + WriteTriangle(index, index + i - 1, index + i); } } @@ -186,12 +187,12 @@ void IndexGenerator::AddFan(u32 numVerts) * or 120,302, 564,746 * or as strip: 1203, 5647 */ -void IndexGenerator::AddQuads(u32 numVerts) +template void IndexGenerator::AddQuads(u32 numVerts) { auto const numQuads = numVerts / 4; for (u32 i = 0; i != numQuads; ++i) { - if(g_Config.backend_info.bSupportsPrimitiveRestart) { + if(pr) { *Tptr++ = index + i * 4 + 1; *Tptr++ = index + i * 4 + 2; *Tptr++ = index + i * 4 + 0; @@ -199,8 +200,8 @@ void IndexGenerator::AddQuads(u32 numVerts) *Tptr++ = s_primitive_restart; numT += 2; } else { - WriteTriangle(index + i * 4, index + i * 4 + 1, index + i * 4 + 2); - WriteTriangle(index + i * 4, index + i * 4 + 2, index + i * 4 + 3); + WriteTriangle(index + i * 4, index + i * 4 + 1, index + i * 4 + 2); + WriteTriangle(index + i * 4, index + i * 4 + 2, index + i * 4 + 3); } } } diff --git a/Source/Core/VideoCommon/Src/IndexGenerator.h b/Source/Core/VideoCommon/Src/IndexGenerator.h index f14d3ae026..421c0aa4a8 100644 --- a/Source/Core/VideoCommon/Src/IndexGenerator.h +++ b/Source/Core/VideoCommon/Src/IndexGenerator.h @@ -26,6 +26,7 @@ class IndexGenerator { public: // Init + static void Init(); static void Start(u16 *Triangleptr,u16 *Lineptr,u16 *Pointptr); static void AddIndices(int primitive, u32 numVertices); @@ -54,10 +55,10 @@ public: */ private: // Triangles - static void AddList(u32 numVerts); - static void AddStrip(u32 numVerts); - static void AddFan(u32 numVerts); - static void AddQuads(u32 numVerts); + template static void AddList(u32 numVerts); + template static void AddStrip(u32 numVerts); + template static void AddFan(u32 numVerts); + template static void AddQuads(u32 numVerts); // Lines static void AddLineList(u32 numVerts); @@ -66,7 +67,7 @@ private: // Points static void AddPoints(u32 numVerts); - static void WriteTriangle(u32 index1, u32 index2, u32 index3); + template static void WriteTriangle(u32 index1, u32 index2, u32 index3); static u16 *Tptr; static u16 *BASETptr; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp index fcc5567016..0fe58e4277 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp @@ -35,6 +35,7 @@ #include "Debugger/DebuggerPanel.h" #include "DLCache.h" #include "EmuWindow.h" +#include "IndexGenerator.h" #include "FileUtil.h" #include "Globals.h" #include "IniFile.h" @@ -193,6 +194,7 @@ void VideoBackend::Video_Prepare() // VideoCommon BPInit(); Fifo_Init(); + IndexGenerator::Init(); VertexLoaderManager::Init(); OpcodeDecoder_Init(); VertexShaderManager::Init(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp index 71ce54c82b..4d21506b9c 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp @@ -51,6 +51,7 @@ #include "VideoState.h" #include "Render.h" #include "DLCache.h" +#include "IndexGenerator.h" #include "IniFile.h" #include "Core.h" #include "Host.h" @@ -184,6 +185,7 @@ void VideoBackend::Video_Prepare() // VideoCommon BPInit(); Fifo_Init(); + IndexGenerator::Init(); VertexLoaderManager::Init(); OpcodeDecoder_Init(); VertexShaderManager::Init(); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index 036444f8bd..ff5c3d1171 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -338,7 +338,7 @@ Renderer::Renderer() g_Config.backend_info.bSupportsDualSourceBlend = GLEW_ARB_blend_func_extended; g_Config.backend_info.bSupportsGLSLUBO = GLEW_ARB_uniform_buffer_object; - g_Config.backend_info.bSupportsPrimitiveRestart = false; //GLEW_VERSION_3_1; + g_Config.backend_info.bSupportsPrimitiveRestart = GLEW_VERSION_3_1; g_ogl_config.bSupportsGLSLCache = GLEW_ARB_get_program_binary; g_ogl_config.bSupportsGLPinnedMemory = GLEW_AMD_pinned_memory; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index e87238d4d4..9331956b67 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -96,6 +96,7 @@ Make AA apply instantly during gameplay if possible #include "PerfQuery.h" #include "VideoState.h" +#include "IndexGenerator.h" #include "VideoBackend.h" #include "ConfigManager.h" @@ -199,6 +200,7 @@ void VideoBackend::Video_Prepare() g_perf_query = new PerfQuery; Fifo_Init(); // must be done before OpcodeDecoder_Init() OpcodeDecoder_Init(); + IndexGenerator::Init(); VertexShaderManager::Init(); PixelShaderManager::Init(); ProgramShaderCache::Init(); From a6412f7bd4f09ce299638afbfd0a6b085e681902 Mon Sep 17 00:00:00 2001 From: degasus Date: Wed, 10 Apr 2013 12:36:59 +0200 Subject: [PATCH 6/9] render a triangle for a 3 vertice quad fix issue 6214 --- .../Core/VideoCommon/Src/IndexGenerator.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Source/Core/VideoCommon/Src/IndexGenerator.cpp b/Source/Core/VideoCommon/Src/IndexGenerator.cpp index 53a3e4a351..5f95f30884 100644 --- a/Source/Core/VideoCommon/Src/IndexGenerator.cpp +++ b/Source/Core/VideoCommon/Src/IndexGenerator.cpp @@ -98,6 +98,9 @@ template void IndexGenerator::AddList(u32 const numVerts) { WriteTriangle(index + i * 3, index + i * 3 + 1, index + i * 3 + 2); } + u32 remainingVerts = numVerts - numTris*3; + if(remainingVerts) + ERROR_LOG(VIDEO, "AddList: unknown count of vertices found"); } template void IndexGenerator::AddStrip(u32 const numVerts) @@ -186,6 +189,10 @@ template void IndexGenerator::AddFan(u32 numVerts) * 012,023, 456,467 ... * or 120,302, 564,746 * or as strip: 1203, 5647 + * + * Warning: + * A simple triangle have to be rendered for three vertices. + * SMS do this for sun rays */ template void IndexGenerator::AddQuads(u32 numVerts) { @@ -204,6 +211,14 @@ template void IndexGenerator::AddQuads(u32 numVerts) WriteTriangle(index + i * 4, index + i * 4 + 2, index + i * 4 + 3); } } + // three vertices remaining, so render a triangle + u32 remainingVerts = numVerts - numQuads*4; + if(remainingVerts == 3) + { + WriteTriangle(index+numVerts-3, index+numVerts-2, index+numVerts-1); + } + else if(remainingVerts) + ERROR_LOG(VIDEO, "AddQuads: unknown count of vertices found"); } // Lines @@ -216,6 +231,10 @@ void IndexGenerator::AddLineList(u32 numVerts) *Lptr++ = index + i * 2 + 1; ++numL; } + u32 remainingVerts = numVerts - numLines*2; + if(remainingVerts) + ERROR_LOG(VIDEO, "AddLineList: unknown count of vertices found"); + } // shouldn't be used as strips as LineLists are much more common From 1aa10b579a017257e74d4c26d2aab36944c55949 Mon Sep 17 00:00:00 2001 From: degasus Date: Wed, 10 Apr 2013 12:45:44 +0200 Subject: [PATCH 7/9] fix triangle_fan size calculation wasn't updated for the new primitive restart implementation --- Source/Core/VideoCommon/Src/IndexGenerator.cpp | 4 ++-- Source/Core/VideoCommon/Src/VertexManagerBase.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoCommon/Src/IndexGenerator.cpp b/Source/Core/VideoCommon/Src/IndexGenerator.cpp index 5f95f30884..28c62193c2 100644 --- a/Source/Core/VideoCommon/Src/IndexGenerator.cpp +++ b/Source/Core/VideoCommon/Src/IndexGenerator.cpp @@ -191,8 +191,8 @@ template void IndexGenerator::AddFan(u32 numVerts) * or as strip: 1203, 5647 * * Warning: - * A simple triangle have to be rendered for three vertices. - * SMS do this for sun rays + * A simple triangle has to be rendered for three vertices. + * ZWW do this for sun rays */ template void IndexGenerator::AddQuads(u32 numVerts) { diff --git a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp index d85548bf1f..567621964f 100644 --- a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp @@ -85,7 +85,7 @@ u32 VertexManager::GetRemainingIndices(int primitive) case GX_DRAW_TRIANGLE_STRIP: return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 1 - 1; case GX_DRAW_TRIANGLE_FAN: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 4 + 2; + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 6 * 4 + 1; case GX_DRAW_LINES: return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()); From b9ba82ec03e5d66a0121565402cfd4ead93f0173 Mon Sep 17 00:00:00 2001 From: degasus Date: Wed, 10 Apr 2013 12:58:52 +0200 Subject: [PATCH 8/9] proper ogl primitive restart code --- Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 29 ++++++++++--------- Source/Plugins/Plugin_VideoOGL/Src/Render.h | 1 + 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index ff5c3d1171..d6c161614e 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -338,7 +338,7 @@ Renderer::Renderer() g_Config.backend_info.bSupportsDualSourceBlend = GLEW_ARB_blend_func_extended; g_Config.backend_info.bSupportsGLSLUBO = GLEW_ARB_uniform_buffer_object; - g_Config.backend_info.bSupportsPrimitiveRestart = GLEW_VERSION_3_1; + g_Config.backend_info.bSupportsPrimitiveRestart = GLEW_VERSION_3_1 || GLEW_NV_primitive_restart; g_ogl_config.bSupportsGLSLCache = GLEW_ARB_get_program_binary; g_ogl_config.bSupportsGLPinnedMemory = GLEW_AMD_pinned_memory; @@ -346,6 +346,7 @@ Renderer::Renderer() g_ogl_config.bSupportsGLBaseVertex = GLEW_ARB_draw_elements_base_vertex; g_ogl_config.bSupportCoverageMSAA = GLEW_NV_framebuffer_multisample_coverage; g_ogl_config.bSupportSampleShading = GLEW_ARB_sample_shading; + g_ogl_config.bSupportOGL31 = GLEW_VERSION_3_1; g_ogl_config.gl_vendor = (const char*)glGetString(GL_VENDOR); g_ogl_config.gl_renderer = (const char*)glGetString(GL_RENDERER); @@ -477,6 +478,20 @@ Renderer::Renderer() glScissor(0, 0, GetTargetWidth(), GetTargetHeight()); glBlendColor(0, 0, 0, 0.5f); glClearDepth(1.0f); + + if(g_ActiveConfig.backend_info.bSupportsPrimitiveRestart) + { + if(g_ogl_config.bSupportOGL31) + { + glEnable(GL_PRIMITIVE_RESTART); + glPrimitiveRestartIndex(65535); + } + else + { + glEnableClientState(GL_PRIMITIVE_RESTART_NV); + glPrimitiveRestartIndexNV(65535); + } + } UpdateActiveConfig(); } @@ -1466,12 +1481,6 @@ void Renderer::ResetAPIState() glDisable(GL_BLEND); glDepthMask(GL_FALSE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - - if(g_ActiveConfig.backend_info.bSupportsPrimitiveRestart) - { - glDisable(GL_PRIMITIVE_RESTART); - } } void Renderer::RestoreAPIState() @@ -1492,12 +1501,6 @@ void Renderer::RestoreAPIState() vm->m_last_vao = 0; TextureCache::SetStage(); - - if(g_ActiveConfig.backend_info.bSupportsPrimitiveRestart) - { - glEnable(GL_PRIMITIVE_RESTART); - glPrimitiveRestartIndex(65535); - } } void Renderer::SetGenerationMode() diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.h b/Source/Plugins/Plugin_VideoOGL/Src/Render.h index 963c267b19..61e820dad4 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.h @@ -24,6 +24,7 @@ extern struct VideoConfig { bool bSupportCoverageMSAA; bool bSupportSampleShading; GLSL_VERSION eSupportedGLSLVersion; + bool bSupportOGL31; const char *gl_vendor; const char *gl_renderer; From 26b428539a81226042dd421dff4bf193fa77136c Mon Sep 17 00:00:00 2001 From: degasus Date: Wed, 10 Apr 2013 14:12:35 +0200 Subject: [PATCH 9/9] small cleanup suggested by neobrain --- Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index ea8ec305ce..333d0b5550 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -124,10 +124,12 @@ void VertexManager::Draw(u32 stride) u32 triangle_index_size = IndexGenerator::GetTriangleindexLen(); u32 line_index_size = IndexGenerator::GetLineindexLen(); u32 point_index_size = IndexGenerator::GetPointindexLen(); + GLenum triangle_mode = g_ActiveConfig.backend_info.bSupportsPrimitiveRestart?GL_TRIANGLE_STRIP:GL_TRIANGLES; + if(g_ogl_config.bSupportsGLBaseVertex) { if (triangle_index_size > 0) { - glDrawElementsBaseVertex(g_ActiveConfig.backend_info.bSupportsPrimitiveRestart?GL_TRIANGLE_STRIP:GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0], s_baseVertex); + glDrawElementsBaseVertex(triangle_mode, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0], s_baseVertex); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } if (line_index_size > 0) @@ -143,7 +145,7 @@ void VertexManager::Draw(u32 stride) } else { if (triangle_index_size > 0) { - glDrawElements(g_ActiveConfig.backend_info.bSupportsPrimitiveRestart?GL_TRIANGLE_STRIP:GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0]); + glDrawElements(triangle_mode, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0]); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } if (line_index_size > 0)