Merge branch 'index_buffer_cleanup'

This commit is contained in:
degasus 2014-01-17 16:35:54 +01:00
commit 355df60abd
7 changed files with 160 additions and 218 deletions

View File

@ -36,9 +36,7 @@ void VertexManager::CreateDeviceObjects()
D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
m_vertex_draw_offset = 0; m_vertex_draw_offset = 0;
m_triangle_draw_index = 0; m_index_draw_offset = 0;
m_line_draw_index = 0;
m_point_draw_index = 0;
m_index_buffers = new PID3D11Buffer[MAX_VBUFFER_COUNT]; m_index_buffers = new PID3D11Buffer[MAX_VBUFFER_COUNT];
m_vertex_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++) 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_draw_offset = m_vertex_buffer_cursor;
m_vertex_buffer_cursor += vSize; m_vertex_buffer_cursor += vSize;
UINT iCount = IndexGenerator::GetTriangleindexLen() + UINT iCount = IndexGenerator::GetIndexLen();
IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen();
MapType = D3D11_MAP_WRITE_NO_OVERWRITE; MapType = D3D11_MAP_WRITE_NO_OVERWRITE;
if (m_index_buffer_cursor + iCount >= (IBUFFER_SIZE / sizeof(u16))) 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); D3D::context->Map(m_index_buffers[m_current_index_buffer], 0, MapType, 0, &map);
m_triangle_draw_index = m_index_buffer_cursor; memcpy((u16*)map.pData + m_index_buffer_cursor, GetIndexBuffer(), sizeof(u16) * IndexGenerator::GetIndexLen());
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());
D3D::context->Unmap(m_index_buffers[m_current_index_buffer], 0); D3D::context->Unmap(m_index_buffers[m_current_index_buffer], 0);
m_index_draw_offset = m_index_buffer_cursor;
m_index_buffer_cursor += iCount; m_index_buffer_cursor += iCount;
ADDSTAT(stats.thisFrame.bytesVertexStreamed, vSize); 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->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); 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->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); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
} }
// Disable culling for lines and points else if (current_primitive_type == PRIMITIVE_LINES)
if (IndexGenerator::GetNumLines() > 0 || IndexGenerator::GetNumPoints() > 0)
((DX11::Renderer*)g_renderer)->ApplyCullDisable();
if (IndexGenerator::GetNumLines() > 0)
{ {
float lineWidth = float(bpmem.lineptwidth.linesize) / 6.f; float lineWidth = float(bpmem.lineptwidth.linesize) / 6.f;
float texOffset = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.lineoff]; 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, if (m_lineShader.SetShader(g_nativeVertexFmt->m_components, lineWidth,
texOffset, vpWidth, vpHeight, texOffsetEnable)) texOffset, vpWidth, vpHeight, texOffsetEnable))
{ {
((DX11::Renderer*)g_renderer)->ApplyCullDisable(); // Disable culling for lines and points
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); 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); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
D3D::context->GSSetShader(NULL, NULL, 0); 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 pointSize = float(bpmem.lineptwidth.pointsize) / 6.f;
float texOffset = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.pointoff]; 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, if (m_pointShader.SetShader(g_nativeVertexFmt->m_components, pointSize,
texOffset, vpWidth, vpHeight, texOffsetEnable)) texOffset, vpWidth, vpHeight, texOffsetEnable))
{ {
((DX11::Renderer*)g_renderer)->ApplyCullDisable(); // Disable culling for lines and points
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); 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); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
D3D::context->GSSetShader(NULL, NULL, 0); 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() void VertexManager::vFlush()

View File

@ -32,11 +32,9 @@ private:
u32 m_vertex_buffer_cursor; u32 m_vertex_buffer_cursor;
u32 m_vertex_draw_offset; u32 m_vertex_draw_offset;
u32 m_index_buffer_cursor; u32 m_index_buffer_cursor;
u32 m_index_draw_offset;
u32 m_current_vertex_buffer; u32 m_current_vertex_buffer;
u32 m_current_index_buffer; u32 m_current_index_buffer;
u32 m_triangle_draw_index;
u32 m_line_draw_index;
u32 m_point_draw_index;
typedef ID3D11Buffer* PID3D11Buffer; typedef ID3D11Buffer* PID3D11Buffer;
PID3D11Buffer* m_index_buffers; PID3D11Buffer* m_index_buffers;
PID3D11Buffer* m_vertex_buffers; PID3D11Buffer* m_vertex_buffers;

View File

@ -44,7 +44,7 @@ const u32 MAX_VBUFFER_SIZE = 16*1024*1024;
static StreamBuffer *s_vertexBuffer; static StreamBuffer *s_vertexBuffer;
static StreamBuffer *s_indexBuffer; static StreamBuffer *s_indexBuffer;
static size_t s_baseVertex; static size_t s_baseVertex;
static size_t s_offset[3]; static size_t s_index_offset;
VertexManager::VertexManager() VertexManager::VertexManager()
{ {
@ -83,74 +83,44 @@ void VertexManager::DestroyDeviceObjects()
void VertexManager::PrepareDrawBuffers(u32 stride) void VertexManager::PrepareDrawBuffers(u32 stride)
{ {
u32 vertex_data_size = IndexGenerator::GetNumVerts() * stride; u32 vertex_data_size = IndexGenerator::GetNumVerts() * stride;
u32 triangle_index_size = IndexGenerator::GetTriangleindexLen(); u32 index_data_size = IndexGenerator::GetIndexLen() * sizeof(u16);
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);
s_vertexBuffer->Alloc(vertex_data_size, stride); s_vertexBuffer->Alloc(vertex_data_size, stride);
size_t offset = s_vertexBuffer->Upload(GetVertexBuffer(), vertex_data_size); size_t offset = s_vertexBuffer->Upload(GetVertexBuffer(), vertex_data_size);
s_baseVertex = offset / stride; s_baseVertex = offset / stride;
s_indexBuffer->Alloc(index_size); s_indexBuffer->Alloc(index_data_size);
if(triangle_index_size) s_index_offset = s_indexBuffer->Upload((u8*)GetIndexBuffer(), index_data_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));
}
ADDSTAT(stats.thisFrame.bytesVertexStreamed, vertex_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) void VertexManager::Draw(u32 stride)
{ {
u32 triangle_index_size = IndexGenerator::GetTriangleindexLen(); u32 index_size = IndexGenerator::GetIndexLen();
u32 line_index_size = IndexGenerator::GetLineindexLen();
u32 point_index_size = IndexGenerator::GetPointindexLen();
u32 max_index = IndexGenerator::GetNumVerts(); 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(g_ogl_config.bSupportsGLBaseVertex) {
if (triangle_index_size > 0) glDrawRangeElementsBaseVertex(primitive_mode, 0, max_index, index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_index_offset, (GLint)s_baseVertex);
{
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);
}
} else { } else {
if (triangle_index_size > 0) glDrawRangeElements(primitive_mode, 0, max_index, index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_index_offset);
{
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);
}
} }
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
} }
void VertexManager::vFlush() void VertexManager::vFlush()

View File

@ -9,20 +9,13 @@
#include "IndexGenerator.h" #include "IndexGenerator.h"
//Init //Init
u16 *IndexGenerator::Tptr; u16 *IndexGenerator::index_buffer_current;
u16 *IndexGenerator::BASETptr; u16 *IndexGenerator::BASEIptr;
u16 *IndexGenerator::Lptr; u32 IndexGenerator::base_index;
u16 *IndexGenerator::BASELptr;
u16 *IndexGenerator::Pptr;
u16 *IndexGenerator::BASEPptr;
u32 IndexGenerator::numT;
u32 IndexGenerator::numL;
u32 IndexGenerator::numP;
u32 IndexGenerator::index;
static const u16 s_primitive_restart = -1; static const u16 s_primitive_restart = -1;
static void (*primitive_table[8])(u32); static u16* (*primitive_table[8])(u16*, u32, u32);
void IndexGenerator::Init() void IndexGenerator::Init()
{ {
@ -46,56 +39,48 @@ void IndexGenerator::Init()
primitive_table[7] = &IndexGenerator::AddPoints; primitive_table[7] = &IndexGenerator::AddPoints;
} }
void IndexGenerator::Start(u16* Triangleptr, u16* Lineptr, u16* Pointptr) void IndexGenerator::Start(u16* Indexptr)
{ {
Tptr = Triangleptr; index_buffer_current = Indexptr;
Lptr = Lineptr; BASEIptr = Indexptr;
Pptr = Pointptr; base_index = 0;
BASETptr = Triangleptr;
BASELptr = Lineptr;
BASEPptr = Pointptr;
index = 0;
numT = 0;
numL = 0;
numP = 0;
} }
void IndexGenerator::AddIndices(int primitive, u32 numVerts) void IndexGenerator::AddIndices(int primitive, u32 numVerts)
{ {
primitive_table[primitive](numVerts); index_buffer_current = primitive_table[primitive](index_buffer_current, numVerts, base_index);
index += numVerts; base_index += numVerts;
} }
// Triangles // Triangles
template <bool pr> __forceinline void IndexGenerator::WriteTriangle(u32 index1, u32 index2, u32 index3) template <bool pr> __forceinline u16* IndexGenerator::WriteTriangle(u16 *Iptr, u32 index1, u32 index2, u32 index3)
{ {
*Tptr++ = index1; *Iptr++ = index1;
*Tptr++ = index2; *Iptr++ = index2;
*Tptr++ = index3; *Iptr++ = index3;
if(pr) if(pr)
*Tptr++ = s_primitive_restart; *Iptr++ = s_primitive_restart;
return Iptr;
++numT;
} }
template <bool pr> void IndexGenerator::AddList(u32 const numVerts) template <bool pr> u16* IndexGenerator::AddList(u16 *Iptr, u32 const numVerts, u32 index)
{ {
for (u32 i = 2; i < numVerts; i+=3) for (u32 i = 2; i < numVerts; i+=3)
{ {
WriteTriangle<pr>(index + i - 2, index + i - 1, index + i); Iptr = WriteTriangle<pr>(Iptr, index + i - 2, index + i - 1, index + i);
} }
return Iptr;
} }
template <bool pr> void IndexGenerator::AddStrip(u32 const numVerts) template <bool pr> u16* IndexGenerator::AddStrip(u16 *Iptr, u32 const numVerts, u32 index)
{ {
if(pr) if(pr)
{ {
for (u32 i = 0; i < numVerts; ++i) for (u32 i = 0; i < numVerts; ++i)
{ {
*Tptr++ = index + i; *Iptr++ = index + i;
} }
*Tptr++ = s_primitive_restart; *Iptr++ = s_primitive_restart;
numT += numVerts - 2;
} }
else else
@ -103,7 +88,7 @@ template <bool pr> void IndexGenerator::AddStrip(u32 const numVerts)
bool wind = false; bool wind = false;
for (u32 i = 2; i < numVerts; ++i) for (u32 i = 2; i < numVerts; ++i)
{ {
WriteTriangle<pr>( Iptr = WriteTriangle<pr>(Iptr,
index + i - 2, index + i - 2,
index + i - !wind, index + i - !wind,
index + i - wind); index + i - wind);
@ -111,6 +96,7 @@ template <bool pr> void IndexGenerator::AddStrip(u32 const numVerts)
wind ^= true; wind ^= true;
} }
} }
return Iptr;
} }
/** /**
@ -132,7 +118,7 @@ template <bool pr> void IndexGenerator::AddStrip(u32 const numVerts)
* so we use 6 indices for 3 triangles * so we use 6 indices for 3 triangles
*/ */
template <bool pr> void IndexGenerator::AddFan(u32 numVerts) template <bool pr> u16* IndexGenerator::AddFan(u16 *Iptr, u32 numVerts, u32 index)
{ {
u32 i = 2; u32 i = 2;
@ -140,30 +126,29 @@ template <bool pr> void IndexGenerator::AddFan(u32 numVerts)
{ {
for(; i+3<=numVerts; i+=3) for(; i+3<=numVerts; i+=3)
{ {
*Tptr++ = index + i - 1; *Iptr++ = index + i - 1;
*Tptr++ = index + i + 0; *Iptr++ = index + i + 0;
*Tptr++ = index; *Iptr++ = index;
*Tptr++ = index + i + 1; *Iptr++ = index + i + 1;
*Tptr++ = index + i + 2; *Iptr++ = index + i + 2;
*Tptr++ = s_primitive_restart; *Iptr++ = s_primitive_restart;
numT += 3;
} }
for(; i+2<=numVerts; i+=2) for(; i+2<=numVerts; i+=2)
{ {
*Tptr++ = index + i - 1; *Iptr++ = index + i - 1;
*Tptr++ = index + i + 0; *Iptr++ = index + i + 0;
*Tptr++ = index; *Iptr++ = index;
*Tptr++ = index + i + 1; *Iptr++ = index + i + 1;
*Tptr++ = s_primitive_restart; *Iptr++ = s_primitive_restart;
numT += 2;
} }
} }
for (; i < numVerts; ++i) for (; i < numVerts; ++i)
{ {
WriteTriangle<pr>(index, index + i - 1, index + i); Iptr = WriteTriangle<pr>(Iptr, index, index + i - 1, index + i);
} }
return Iptr;
} }
/* /*
@ -183,71 +168,71 @@ template <bool pr> void IndexGenerator::AddFan(u32 numVerts)
* A simple triangle has to be rendered for three vertices. * A simple triangle has to be rendered for three vertices.
* ZWW do this for sun rays * ZWW do this for sun rays
*/ */
template <bool pr> void IndexGenerator::AddQuads(u32 numVerts) template <bool pr> u16* IndexGenerator::AddQuads(u16 *Iptr, u32 numVerts, u32 index)
{ {
u32 i = 3; u32 i = 3;
for (; i < numVerts; i+=4) for (; i < numVerts; i+=4)
{ {
if(pr) if(pr)
{ {
*Tptr++ = index + i - 2; *Iptr++ = index + i - 2;
*Tptr++ = index + i - 1; *Iptr++ = index + i - 1;
*Tptr++ = index + i - 3; *Iptr++ = index + i - 3;
*Tptr++ = index + i - 0; *Iptr++ = index + i - 0;
*Tptr++ = s_primitive_restart; *Iptr++ = s_primitive_restart;
numT += 2;
} }
else else
{ {
WriteTriangle<pr>(index + i - 3, index + i - 2, index + i - 1); Iptr = WriteTriangle<pr>(Iptr, index + i - 3, index + i - 2, index + i - 1);
WriteTriangle<pr>(index + i - 3, index + i - 1, index + i - 0); Iptr = WriteTriangle<pr>(Iptr, index + i - 3, index + i - 1, index + i - 0);
} }
} }
// three vertices remaining, so render a triangle // three vertices remaining, so render a triangle
if(i == numVerts) if(i == numVerts)
{ {
WriteTriangle<pr>(index+numVerts-3, index+numVerts-2, index+numVerts-1); Iptr = WriteTriangle<pr>(Iptr, index+numVerts-3, index+numVerts-2, index+numVerts-1);
} }
return Iptr;
} }
// Lines // Lines
void IndexGenerator::AddLineList(u32 numVerts) u16* IndexGenerator::AddLineList(u16 *Iptr, u32 numVerts, u32 index)
{ {
for (u32 i = 1; i < numVerts; i+=2) for (u32 i = 1; i < numVerts; i+=2)
{ {
*Lptr++ = index + i - 1; *Iptr++ = index + i - 1;
*Lptr++ = index + i; *Iptr++ = index + i;
++numL;
} }
return Iptr;
} }
// shouldn't be used as strips as LineLists are much more common // shouldn't be used as strips as LineLists are much more common
// so converting them to lists // 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) for (u32 i = 1; i < numVerts; ++i)
{ {
*Lptr++ = index + i - 1; *Iptr++ = index + i - 1;
*Lptr++ = index + i; *Iptr++ = index + i;
++numL;
} }
return Iptr;
} }
// Points // Points
void IndexGenerator::AddPoints(u32 numVerts) u16* IndexGenerator::AddPoints(u16 *Iptr, u32 numVerts, u32 index)
{ {
for (u32 i = 0; i != numVerts; ++i) for (u32 i = 0; i != numVerts; ++i)
{ {
*Pptr++ = index + i; *Iptr++ = index + i;
++numP;
} }
return Iptr;
} }
u32 IndexGenerator::GetRemainingIndices() u32 IndexGenerator::GetRemainingIndices()
{ {
u32 max_index = 65534; // -1 is reserved for primitive restart (ogl + dx11) u32 max_index = 65534; // -1 is reserved for primitive restart (ogl + dx11)
return max_index - index; return max_index - base_index;
} }

View File

@ -14,59 +14,36 @@ class IndexGenerator
public: public:
// Init // Init
static void 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); static void AddIndices(int primitive, u32 numVertices);
// Interface
static u32 GetNumTriangles() {return numT;}
static u32 GetNumLines() {return numL;}
static u32 GetNumPoints() {return numP;}
// returns numprimitives // returns numprimitives
static u32 GetNumVerts() {return index;} static u32 GetNumVerts() {return base_index;}
static u32 GetTriangleindexLen() {return (u32)(Tptr - BASETptr);} static u32 GetIndexLen() {return (u32)(index_buffer_current - BASEIptr);}
static u32 GetLineindexLen() {return (u32)(Lptr - BASELptr);}
static u32 GetPointindexLen() {return (u32)(Pptr - BASEPptr);}
static u32 GetRemainingIndices(); static u32 GetRemainingIndices();
/*
enum IndexPrimitiveType
{
Prim_None = 0,
Prim_List,
Prim_Strip,
Prim_Fan
};
*/
private: private:
// Triangles // Triangles
template <bool pr> static void AddList(u32 numVerts); template <bool pr> static u16* AddList(u16 *Iptr, u32 numVerts, u32 index);
template <bool pr> static void AddStrip(u32 numVerts); template <bool pr> static u16* AddStrip(u16 *Iptr, u32 numVerts, u32 index);
template <bool pr> static void AddFan(u32 numVerts); template <bool pr> static u16* AddFan(u16 *Iptr, u32 numVerts, u32 index);
template <bool pr> static void AddQuads(u32 numVerts); template <bool pr> static u16* AddQuads(u16 *Iptr, u32 numVerts, u32 index);
// Lines // Lines
static void AddLineList(u32 numVerts); static u16* AddLineList(u16 *Iptr, u32 numVerts, u32 index);
static void AddLineStrip(u32 numVerts); static u16* AddLineStrip(u16 *Iptr, u32 numVerts, u32 index);
// Points // Points
static void AddPoints(u32 numVerts); static u16* AddPoints(u16 *Iptr, u32 numVerts, u32 index);
template <bool pr> static void WriteTriangle(u32 index1, u32 index2, u32 index3); template <bool pr> static u16* WriteTriangle(u16 *Iptr, u32 index1, u32 index2, u32 index3);
static u16 *Tptr; static u16 *index_buffer_current;
static u16 *BASETptr; static u16 *BASEIptr;
static u16 *Lptr; static u32 base_index;
static u16 *BASELptr;
static u16 *Pptr;
static u16 *BASEPptr;
// TODO: redundant variables
static u32 numT;
static u32 numL;
static u32 numP;
static u32 index;
}; };
#endif // _INDEXGENERATOR_H #endif // _INDEXGENERATOR_H

View File

@ -21,15 +21,26 @@ u8 *VertexManager::s_pCurBufferPointer;
u8 *VertexManager::s_pBaseBufferPointer; u8 *VertexManager::s_pBaseBufferPointer;
u8 *VertexManager::s_pEndBufferPointer; 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() VertexManager::VertexManager()
{ {
LocalVBuffer.resize(MAXVBUFFERSIZE); LocalVBuffer.resize(MAXVBUFFERSIZE);
s_pCurBufferPointer = s_pBaseBufferPointer = &LocalVBuffer[0]; s_pCurBufferPointer = s_pBaseBufferPointer = &LocalVBuffer[0];
s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size(); s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size();
TIBuffer.resize(MAXIBUFFERSIZE); LocalIBuffer.resize(MAXIBUFFERSIZE);
LIBuffer.resize(MAXIBUFFERSIZE);
PIBuffer.resize(MAXIBUFFERSIZE);
ResetBuffer(); ResetBuffer();
} }
@ -41,7 +52,7 @@ VertexManager::~VertexManager()
void VertexManager::ResetBuffer() void VertexManager::ResetBuffer()
{ {
s_pCurBufferPointer = s_pBaseBufferPointer; s_pCurBufferPointer = s_pBaseBufferPointer;
IndexGenerator::Start(GetTriangleIndexBuffer(), GetLineIndexBuffer(), GetPointIndexBuffer()); IndexGenerator::Start(GetIndexBuffer());
} }
u32 VertexManager::GetRemainingSize() u32 VertexManager::GetRemainingSize()
@ -53,6 +64,12 @@ void VertexManager::PrepareForAdditionalData(int primitive, u32 count, u32 strid
{ {
u32 const needed_vertex_bytes = count * stride; 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()) if (count > IndexGenerator::GetRemainingIndices() || count > GetRemainingIndices(primitive) || needed_vertex_bytes > GetRemainingSize())
{ {
Flush(); Flush();
@ -75,27 +92,28 @@ bool VertexManager::IsFlushed() const
u32 VertexManager::GetRemainingIndices(int primitive) u32 VertexManager::GetRemainingIndices(int primitive)
{ {
u32 index_len = MAXIBUFFERSIZE - IndexGenerator::GetIndexLen();
if(g_Config.backend_info.bSupportsPrimitiveRestart) if(g_Config.backend_info.bSupportsPrimitiveRestart)
{ {
switch (primitive) switch (primitive)
{ {
case GX_DRAW_QUADS: case GX_DRAW_QUADS:
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 5 * 4; return index_len / 5 * 4;
case GX_DRAW_TRIANGLES: case GX_DRAW_TRIANGLES:
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 4 * 3; return index_len / 4 * 3;
case GX_DRAW_TRIANGLE_STRIP: case GX_DRAW_TRIANGLE_STRIP:
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 1 - 1; return index_len / 1 - 1;
case GX_DRAW_TRIANGLE_FAN: case GX_DRAW_TRIANGLE_FAN:
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 6 * 4 + 1; return index_len / 6 * 4 + 1;
case GX_DRAW_LINES: case GX_DRAW_LINES:
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()); return index_len;
case GX_DRAW_LINE_STRIP: case GX_DRAW_LINE_STRIP:
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2 + 1; return index_len / 2 + 1;
case GX_DRAW_POINTS: case GX_DRAW_POINTS:
return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen()); return index_len;
default: default:
return 0; return 0;
@ -106,21 +124,21 @@ u32 VertexManager::GetRemainingIndices(int primitive)
switch (primitive) switch (primitive)
{ {
case GX_DRAW_QUADS: case GX_DRAW_QUADS:
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 6 * 4; return index_len / 6 * 4;
case GX_DRAW_TRIANGLES: case GX_DRAW_TRIANGLES:
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()); return index_len;
case GX_DRAW_TRIANGLE_STRIP: case GX_DRAW_TRIANGLE_STRIP:
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2; return index_len / 3 + 2;
case GX_DRAW_TRIANGLE_FAN: case GX_DRAW_TRIANGLE_FAN:
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2; return index_len / 3 + 2;
case GX_DRAW_LINES: case GX_DRAW_LINES:
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()); return index_len;
case GX_DRAW_LINE_STRIP: case GX_DRAW_LINE_STRIP:
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2 + 1; return index_len / 2 + 1;
case GX_DRAW_POINTS: case GX_DRAW_POINTS:
return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen()); return index_len;
default: default:
return 0; return 0;
@ -167,9 +185,7 @@ void VertexManager::DoStateShared(PointerWrap& p)
// and maybe other things are overlooked // and maybe other things are overlooked
p.Do(LocalVBuffer); p.Do(LocalVBuffer);
p.Do(TIBuffer); p.Do(LocalIBuffer);
p.Do(LIBuffer);
p.Do(PIBuffer);
s_pBaseBufferPointer = &LocalVBuffer[0]; s_pBaseBufferPointer = &LocalVBuffer[0];
s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size(); s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size();

View File

@ -8,6 +8,12 @@
class NativeVertexFormat; class NativeVertexFormat;
class PointerWrap; class PointerWrap;
enum PrimitiveType {
PRIMITIVE_POINTS,
PRIMITIVE_LINES,
PRIMITIVE_TRIANGLES,
};
class VertexManager class VertexManager
{ {
private: private:
@ -45,14 +51,14 @@ public:
virtual void DestroyDeviceObjects(){}; virtual void DestroyDeviceObjects(){};
protected: protected:
u16* GetTriangleIndexBuffer() { return &TIBuffer[0]; } u16* GetIndexBuffer() { return &LocalIBuffer[0]; }
u16* GetLineIndexBuffer() { return &LIBuffer[0]; }
u16* GetPointIndexBuffer() { return &PIBuffer[0]; }
u8* GetVertexBuffer() { return &s_pBaseBufferPointer[0]; } u8* GetVertexBuffer() { return &s_pBaseBufferPointer[0]; }
virtual void vDoState(PointerWrap& p) { DoStateShared(p); } virtual void vDoState(PointerWrap& p) { DoStateShared(p); }
void DoStateShared(PointerWrap& p); void DoStateShared(PointerWrap& p);
static PrimitiveType current_primitive_type;
private: private:
bool IsFlushed() const; bool IsFlushed() const;
@ -63,9 +69,7 @@ private:
virtual void vFlush() = 0; virtual void vFlush() = 0;
std::vector<u8> LocalVBuffer; std::vector<u8> LocalVBuffer;
std::vector<u16> TIBuffer; std::vector<u16> LocalIBuffer;
std::vector<u16> LIBuffer;
std::vector<u16> PIBuffer;
}; };
extern VertexManager *g_vertex_manager; extern VertexManager *g_vertex_manager;