Skip to content

Commit

Permalink
VideoCommon: merge triangle+list+point index buffers
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
degasus committed Jan 17, 2014
1 parent 770485a commit 6b01839
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 175 deletions.
36 changes: 14 additions & 22 deletions Source/Core/VideoBackends/D3D/VertexManager.cpp
Expand Up @@ -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++)
Expand Down Expand Up @@ -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)))
{
Expand All @@ -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);
Expand All @@ -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];
Expand All @@ -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];
Expand All @@ -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()
Expand Down
4 changes: 1 addition & 3 deletions Source/Core/VideoBackends/D3D/VertexManager.h
Expand Up @@ -32,11 +32,9 @@ class VertexManager : public ::VertexManager
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;
Expand Down
76 changes: 23 additions & 53 deletions Source/Core/VideoBackends/OGL/VertexManager.cpp
Expand Up @@ -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()
{
Expand Down Expand Up @@ -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()
Expand Down
96 changes: 42 additions & 54 deletions Source/Core/VideoCommon/IndexGenerator.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand All @@ -69,13 +57,13 @@ void IndexGenerator::AddIndices(int primitive, u32 numVerts)
// Triangles
template <bool pr> __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 <bool pr> void IndexGenerator::AddList(u32 const numVerts)
Expand All @@ -92,10 +80,10 @@ template <bool pr> 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
Expand Down Expand Up @@ -140,23 +128,23 @@ template <bool pr> 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;
}
}

Expand Down Expand Up @@ -190,12 +178,12 @@ template <bool pr> 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
{
Expand All @@ -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;
}

}
Expand All @@ -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;
}
}

Expand All @@ -240,8 +228,8 @@ void IndexGenerator::AddPoints(u32 numVerts)
{
for (u32 i = 0; i != numVerts; ++i)
{
*Pptr++ = index + i;
++numP;
*Iptr++ = index + i;
++numI;
}
}

Expand Down

0 comments on commit 6b01839

Please sign in to comment.