@@ -2,113 +2,64 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include " VideoCommon/IndexGenerator.h"
#include < array>
#include < cstddef>
#include < cstring>
#include " Common/CommonTypes.h"
#include " Common/Compiler.h"
#include " Common/Logging/Log.h"
#include " VideoCommon/IndexGenerator.h"
#include " VideoCommon/OpcodeDecoding.h"
#include " VideoCommon/VideoConfig.h"
// Init
u16* IndexGenerator::index_buffer_current;
u16* IndexGenerator::BASEIptr;
u32 IndexGenerator::base_index;
static const u16 s_primitive_restart = UINT16_MAX;
static u16* (*primitive_table[8 ])(u16*, u32, u32);
void IndexGenerator::Init ()
namespace
{
if (g_Config.backend_info .bSupportsPrimitiveRestart )
{
primitive_table[OpcodeDecoder::GX_DRAW_QUADS] = AddQuads<true >;
primitive_table[OpcodeDecoder::GX_DRAW_QUADS_2] = AddQuads_nonstandard<true >;
primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLES] = AddList<true >;
primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip<true >;
primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan<true >;
}
else
{
primitive_table[OpcodeDecoder::GX_DRAW_QUADS] = AddQuads<false >;
primitive_table[OpcodeDecoder::GX_DRAW_QUADS_2] = AddQuads_nonstandard<false >;
primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLES] = AddList<false >;
primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip<false >;
primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan<false >;
}
primitive_table[OpcodeDecoder::GX_DRAW_LINES] = &AddLineList;
primitive_table[OpcodeDecoder::GX_DRAW_LINE_STRIP] = &AddLineStrip;
primitive_table[OpcodeDecoder::GX_DRAW_POINTS] = &AddPoints;
}
void IndexGenerator::Start (u16* Indexptr)
{
index_buffer_current = Indexptr;
BASEIptr = Indexptr;
base_index = 0 ;
}
constexpr u16 s_primitive_restart = UINT16_MAX;
void IndexGenerator::AddIndices (int primitive, u32 numVerts)
{
index_buffer_current = primitive_table[primitive](index_buffer_current, numVerts, base_index);
base_index += numVerts;
}
void IndexGenerator::AddExternalIndices (const u16* indices, u32 num_indices, u32 num_vertices)
{
std::memcpy (index_buffer_current, indices, sizeof (u16) * num_indices);
index_buffer_current += num_indices;
base_index += num_vertices;
}
// Triangles
template <bool pr>
DOLPHIN_FORCE_INLINE u16* IndexGenerator::WriteTriangle (u16* Iptr, u32 index1, u32 index2,
u32 index3)
u16* WriteTriangle (u16* index_ptr, u32 index1, u32 index2, u32 index3)
{
*Iptr ++ = index1;
*Iptr ++ = index2;
*Iptr ++ = index3;
if (pr)
*Iptr ++ = s_primitive_restart;
return Iptr ;
*index_ptr ++ = index1;
*index_ptr ++ = index2;
*index_ptr ++ = index3;
if constexpr (pr)
*index_ptr ++ = s_primitive_restart;
return index_ptr ;
}
template <bool pr>
u16* IndexGenerator:: AddList (u16* Iptr , u32 const numVerts , u32 index)
u16* AddList (u16* index_ptr , u32 num_verts , u32 index)
{
for (u32 i = 2 ; i < numVerts ; i += 3 )
for (u32 i = 2 ; i < num_verts ; i += 3 )
{
Iptr = WriteTriangle<pr>(Iptr , index + i - 2 , index + i - 1 , index + i);
index_ptr = WriteTriangle<pr>(index_ptr , index + i - 2 , index + i - 1 , index + i);
}
return Iptr ;
return index_ptr ;
}
template <bool pr>
u16* IndexGenerator:: AddStrip (u16* Iptr , u32 const numVerts , u32 index)
u16* AddStrip (u16* index_ptr , u32 num_verts , u32 index)
{
if (pr)
if constexpr (pr)
{
for (u32 i = 0 ; i < numVerts ; ++i)
for (u32 i = 0 ; i < num_verts ; ++i)
{
*Iptr ++ = index + i;
*index_ptr ++ = index + i;
}
*Iptr ++ = s_primitive_restart;
*index_ptr ++ = s_primitive_restart;
}
else
{
bool wind = false ;
for (u32 i = 2 ; i < numVerts ; ++i)
for (u32 i = 2 ; i < num_verts ; ++i)
{
Iptr = WriteTriangle<pr>(Iptr , index + i - 2 , index + i - !wind, index + i - wind);
index_ptr = WriteTriangle<pr>(index_ptr , index + i - 2 , index + i - !wind, index + i - wind);
wind ^= true ;
}
}
return Iptr ;
return index_ptr ;
}
/* *
@@ -131,37 +82,37 @@ u16* IndexGenerator::AddStrip(u16* Iptr, u32 const numVerts, u32 index)
*/
template <bool pr>
u16* IndexGenerator:: AddFan (u16* Iptr , u32 numVerts , u32 index)
u16* AddFan (u16* index_ptr , u32 num_verts , u32 index)
{
u32 i = 2 ;
if (pr)
if constexpr (pr)
{
for (; i + 3 <= numVerts ; i += 3 )
for (; i + 3 <= num_verts ; i += 3 )
{
*Iptr ++ = index + i - 1 ;
*Iptr ++ = index + i + 0 ;
*Iptr ++ = index ;
*Iptr ++ = index + i + 1 ;
*Iptr ++ = index + i + 2 ;
*Iptr ++ = s_primitive_restart;
*index_ptr ++ = index + i - 1 ;
*index_ptr ++ = index + i + 0 ;
*index_ptr ++ = index ;
*index_ptr ++ = index + i + 1 ;
*index_ptr ++ = index + i + 2 ;
*index_ptr ++ = s_primitive_restart;
}
for (; i + 2 <= numVerts ; i += 2 )
for (; i + 2 <= num_verts ; i += 2 )
{
*Iptr ++ = index + i - 1 ;
*Iptr ++ = index + i + 0 ;
*Iptr ++ = index ;
*Iptr ++ = index + i + 1 ;
*Iptr ++ = s_primitive_restart;
*index_ptr ++ = index + i - 1 ;
*index_ptr ++ = index + i + 0 ;
*index_ptr ++ = index ;
*index_ptr ++ = index + i + 1 ;
*index_ptr ++ = s_primitive_restart;
}
}
for (; i < numVerts ; ++i)
for (; i < num_verts ; ++i)
{
Iptr = WriteTriangle<pr>(Iptr , index , index + i - 1 , index + i);
index_ptr = WriteTriangle<pr>(index_ptr , index , index + i - 1 , index + i);
}
return Iptr ;
return index_ptr ;
}
/*
@@ -182,77 +133,122 @@ u16* IndexGenerator::AddFan(u16* Iptr, u32 numVerts, u32 index)
* ZWW do this for sun rays
*/
template <bool pr>
u16* IndexGenerator:: AddQuads (u16* Iptr , u32 numVerts , u32 index)
u16* AddQuads (u16* index_ptr , u32 num_verts , u32 index)
{
u32 i = 3 ;
for (; i < numVerts ; i += 4 )
for (; i < num_verts ; i += 4 )
{
if (pr)
if constexpr (pr)
{
*Iptr ++ = index + i - 2 ;
*Iptr ++ = index + i - 1 ;
*Iptr ++ = index + i - 3 ;
*Iptr ++ = index + i - 0 ;
*Iptr ++ = s_primitive_restart;
*index_ptr ++ = index + i - 2 ;
*index_ptr ++ = index + i - 1 ;
*index_ptr ++ = index + i - 3 ;
*index_ptr ++ = index + i - 0 ;
*index_ptr ++ = s_primitive_restart;
}
else
{
Iptr = WriteTriangle<pr>(Iptr , index + i - 3 , index + i - 2 , index + i - 1 );
Iptr = WriteTriangle<pr>(Iptr , index + i - 3 , index + i - 1 , index + i - 0 );
index_ptr = WriteTriangle<pr>(index_ptr , index + i - 3 , index + i - 2 , index + i - 1 );
index_ptr = WriteTriangle<pr>(index_ptr , index + i - 3 , index + i - 1 , index + i - 0 );
}
}
// three vertices remaining, so render a triangle
if (i == numVerts )
if (i == num_verts )
{
Iptr =
WriteTriangle<pr>(Iptr, index + numVerts - 3 , index + numVerts - 2 , index + numVerts - 1 );
index_ptr = WriteTriangle<pr>(index_ptr, index + num_verts - 3 , index + num_verts - 2 ,
index + num_verts - 1 );
}
return Iptr ;
return index_ptr ;
}
template <bool pr>
u16* IndexGenerator:: AddQuads_nonstandard (u16* Iptr , u32 numVerts , u32 index)
u16* AddQuads_nonstandard (u16* index_ptr , u32 num_verts , u32 index)
{
WARN_LOG (VIDEO, " Non-standard primitive drawing command GL_DRAW_QUADS_2" );
return AddQuads<pr>(Iptr, numVerts , index );
return AddQuads<pr>(index_ptr, num_verts , index );
}
// Lines
u16* IndexGenerator::AddLineList (u16* Iptr, u32 numVerts, u32 index)
u16* AddLineList (u16* index_ptr, u32 num_verts, u32 index)
{
for (u32 i = 1 ; i < numVerts ; i += 2 )
for (u32 i = 1 ; i < num_verts ; i += 2 )
{
*Iptr ++ = index + i - 1 ;
*Iptr ++ = index + i;
*index_ptr ++ = index + i - 1 ;
*index_ptr ++ = index + i;
}
return Iptr ;
return index_ptr ;
}
// 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
u16* IndexGenerator:: AddLineStrip (u16* Iptr , u32 numVerts , u32 index)
u16* AddLineStrip (u16* index_ptr , u32 num_verts , u32 index)
{
for (u32 i = 1 ; i < numVerts ; ++i)
for (u32 i = 1 ; i < num_verts ; ++i)
{
*Iptr ++ = index + i - 1 ;
*Iptr ++ = index + i;
*index_ptr ++ = index + i - 1 ;
*index_ptr ++ = index + i;
}
return Iptr ;
return index_ptr ;
}
// Points
u16* IndexGenerator::AddPoints (u16* Iptr, u32 numVerts, u32 index)
u16* AddPoints (u16* index_ptr, u32 num_verts, u32 index)
{
for (u32 i = 0 ; i != numVerts; ++i)
for (u32 i = 0 ; i != num_verts; ++i)
{
*index_ptr++ = index + i;
}
return index_ptr;
}
} // Anonymous namespace
void IndexGenerator::Init ()
{
if (g_Config.backend_info .bSupportsPrimitiveRestart )
{
m_primitive_table[OpcodeDecoder::GX_DRAW_QUADS] = AddQuads<true >;
m_primitive_table[OpcodeDecoder::GX_DRAW_QUADS_2] = AddQuads_nonstandard<true >;
m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLES] = AddList<true >;
m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip<true >;
m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan<true >;
}
else
{
*Iptr++ = index + i;
m_primitive_table[OpcodeDecoder::GX_DRAW_QUADS] = AddQuads<false >;
m_primitive_table[OpcodeDecoder::GX_DRAW_QUADS_2] = AddQuads_nonstandard<false >;
m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLES] = AddList<false >;
m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip<false >;
m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan<false >;
}
return Iptr;
m_primitive_table[OpcodeDecoder::GX_DRAW_LINES] = AddLineList;
m_primitive_table[OpcodeDecoder::GX_DRAW_LINE_STRIP] = AddLineStrip;
m_primitive_table[OpcodeDecoder::GX_DRAW_POINTS] = AddPoints;
}
u32 IndexGenerator::GetRemainingIndices ( )
void IndexGenerator::Start (u16* index_ptr )
{
u32 max_index = 65534 ; // -1 is reserved for primitive restart (ogl + dx11)
return max_index - base_index;
m_index_buffer_current = index_ptr;
m_base_index_ptr = index_ptr;
m_base_index = 0 ;
}
void IndexGenerator::AddIndices (int primitive, u32 num_vertices)
{
m_index_buffer_current =
m_primitive_table[primitive](m_index_buffer_current, num_vertices, m_base_index);
m_base_index += num_vertices;
}
void IndexGenerator::AddExternalIndices (const u16* indices, u32 num_indices, u32 num_vertices)
{
std::memcpy (m_index_buffer_current, indices, sizeof (u16) * num_indices);
m_index_buffer_current += num_indices;
m_base_index += num_vertices;
}
u32 IndexGenerator::GetRemainingIndices () const
{
// -1 is reserved for primitive restart (OGL + DX11)
constexpr u32 max_index = 65534 ;
return max_index - m_base_index;
}