Index buffer no longer permit 8 bits index size

Modern graphics cards don't like 8 bits index size, so I introduced
"Large indices" option, it means 32 bits indices when used otherwise the
index size is 16 bits


Former-commit-id: 213902de6704ceef16c6ea311ba0c6c5d2f6e665
This commit is contained in:
Lynix 2012-12-02 17:01:02 +01:00
parent 437c7047c9
commit b06acfcffd
4 changed files with 68 additions and 137 deletions

View File

@ -15,19 +15,20 @@ class NAZARA_API NzIndexBuffer : public NzResource
{
public:
NzIndexBuffer(NzBuffer* buffer, unsigned int startIndex, unsigned int indexCount);
NzIndexBuffer(unsigned int length, nzUInt8 indexSize, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static);
NzIndexBuffer(unsigned int length, bool largeIndices = false, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static);
NzIndexBuffer(const NzIndexBuffer& indexBuffer);
~NzIndexBuffer();
bool Fill(const void* data, unsigned int offset, unsigned int length);
NzBuffer* GetBuffer() const;
nzUInt8 GetIndexSize() const;
unsigned int GetIndexCount() const;
void* GetPointer();
const void* GetPointer() const;
unsigned int GetStartIndex() const;
bool HasLargeIndices() const;
bool IsHardware() const;
bool IsSequential() const;

View File

@ -187,29 +187,20 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f
glDrawArrays(NzOpenGL::PrimitiveType[primitive], s_indexBuffer->GetStartIndex(), s_indexBuffer->GetIndexCount());
else
{
nzUInt8 indexSize = s_indexBuffer->GetIndexSize();
GLenum type;
switch (indexSize)
const nzUInt8* ptr = reinterpret_cast<const nzUInt8*>(s_indexBuffer->GetPointer());
if (s_indexBuffer->HasLargeIndices())
{
case 1:
type = GL_UNSIGNED_BYTE;
break;
case 2:
type = GL_UNSIGNED_SHORT;
break;
case 4:
type = GL_UNSIGNED_INT;
break;
default:
NazaraError("Invalid index size (" + NzString::Number(indexSize) + ')');
return;
ptr += firstIndex*sizeof(nzUInt32);
type = GL_UNSIGNED_INT;
}
else
{
ptr += firstIndex*sizeof(nzUInt16);
type = GL_UNSIGNED_SHORT;
}
glDrawElements(NzOpenGL::PrimitiveType[primitive], indexCount, type, reinterpret_cast<const nzUInt8*>(s_indexBuffer->GetPointer()) + firstIndex*indexSize);
glDrawElements(NzOpenGL::PrimitiveType[primitive], indexCount, type, ptr);
}
}

View File

@ -20,7 +20,7 @@ m_startIndex(startIndex)
{
#ifdef NAZARA_DEBUG
nzUInt8 indexSize = m_buffer->GetSize();
if (indexSize != 1 && indexSize != 2 && indexSize != 4)
if (indexSize != 2 && indexSize != 4)
{
NazaraError("Invalid index size (" + NzString::Number(indexSize) + ')');
m_buffer = nullptr;
@ -33,22 +33,12 @@ m_startIndex(startIndex)
}
}
NzIndexBuffer::NzIndexBuffer(unsigned int length, nzUInt8 indexSize, nzBufferStorage storage, nzBufferUsage usage) :
NzIndexBuffer::NzIndexBuffer(unsigned int length, bool largeIndices, nzBufferStorage storage, nzBufferUsage usage) :
m_ownsBuffer(true),
m_indexCount(length),
m_startIndex(0)
{
#ifdef NAZARA_DEBUG
if (indexSize != 1 && indexSize != 2 && indexSize != 4)
{
NazaraError("Invalid index size");
m_buffer = nullptr;
throw std::runtime_error("Constructor failed");
}
#endif
m_buffer = new NzBuffer(nzBufferType_Index, length, indexSize, storage, usage);
m_buffer = new NzBuffer(nzBufferType_Index, length, (largeIndices) ? 4 : 2, storage, usage);
m_buffer->AddResourceReference();
m_buffer->SetPersistent(false);
}
@ -109,19 +99,6 @@ NzBuffer* NzIndexBuffer::GetBuffer() const
return m_buffer;
}
nzUInt8 NzIndexBuffer::GetIndexSize() const
{
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Sequential buffers have no index size");
return 0;
}
#endif
return m_buffer->GetTypeSize();
}
void* NzIndexBuffer::GetPointer()
{
#if NAZARA_UTILITY_SAFE
@ -158,6 +135,19 @@ unsigned int NzIndexBuffer::GetStartIndex() const
return m_startIndex;
}
bool NzIndexBuffer::HasLargeIndices() const
{
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Sequential buffers have no index size");
return 0;
}
#endif
return (m_buffer->GetTypeSize() == 4);
}
bool NzIndexBuffer::IsHardware() const
{
#if NAZARA_UTILITY_SAFE

View File

@ -186,15 +186,9 @@ bool NzMD5MeshParser::Parse(NzMesh* mesh)
unsigned int weightCount = md5Mesh.weights.size();
// Index buffer
nzUInt8 indexSize;
if (vertexCount > std::numeric_limits<nzUInt16>::max())
indexSize = 4;
else if (vertexCount > std::numeric_limits<nzUInt8>::max())
indexSize = 2;
else
indexSize = 1;
bool largeIndices = (vertexCount > std::numeric_limits<nzUInt16>::max());
std::unique_ptr<NzIndexBuffer> indexBuffer(new NzIndexBuffer(indexCount, indexSize, m_parameters.storage));
std::unique_ptr<NzIndexBuffer> indexBuffer(new NzIndexBuffer(indexCount, largeIndices, m_parameters.storage));
if (!indexBuffer->GetBuffer()->IsValid())
{
NazaraError("Failed to create index buffer");
@ -208,48 +202,28 @@ bool NzMD5MeshParser::Parse(NzMesh* mesh)
continue;
}
switch (indexSize)
if (largeIndices)
{
case 1:
{
nzUInt8* index = reinterpret_cast<nzUInt8*>(ptr);
nzUInt32* index = reinterpret_cast<nzUInt32*>(ptr);
for (const Mesh::Triangle& triangle : md5Mesh.triangles)
{
// On les respécifie dans le bon ordre
*index++ = triangle.x;
*index++ = triangle.z;
*index++ = triangle.y;
}
break;
for (const Mesh::Triangle& triangle : md5Mesh.triangles)
{
// On les respécifie dans le bon ordre
*index++ = triangle.x;
*index++ = triangle.z;
*index++ = triangle.y;
}
}
else
{
nzUInt16* index = reinterpret_cast<nzUInt16*>(ptr);
case 2:
for (const Mesh::Triangle& triangle : md5Mesh.triangles)
{
nzUInt16* index = reinterpret_cast<nzUInt16*>(ptr);
for (const Mesh::Triangle& triangle : md5Mesh.triangles)
{
// On les respécifie dans le bon ordre
*index++ = triangle.x;
*index++ = triangle.z;
*index++ = triangle.y;
}
break;
}
case 4:
{
nzUInt32* index = reinterpret_cast<nzUInt32*>(ptr);
for (const Mesh::Triangle& triangle : md5Mesh.triangles)
{
// On les respécifie dans le bon ordre
*index++ = triangle.x;
*index++ = triangle.z;
*index++ = triangle.y;
}
break;
// On les respécifie dans le bon ordre
*index++ = triangle.x;
*index++ = triangle.z;
*index++ = triangle.y;
}
}
@ -342,15 +316,9 @@ bool NzMD5MeshParser::Parse(NzMesh* mesh)
unsigned int vertexCount = md5Mesh.vertices.size();
// Index buffer
nzUInt8 indexSize;
if (vertexCount > std::numeric_limits<nzUInt16>::max())
indexSize = 4;
else if (vertexCount > std::numeric_limits<nzUInt8>::max())
indexSize = 2;
else
indexSize = 1;
bool largeIndices = (vertexCount > std::numeric_limits<nzUInt16>::max());
std::unique_ptr<NzIndexBuffer> indexBuffer(new NzIndexBuffer(indexCount, indexSize, m_parameters.storage));
std::unique_ptr<NzIndexBuffer> indexBuffer(new NzIndexBuffer(indexCount, largeIndices, m_parameters.storage));
if (!indexBuffer->GetBuffer()->IsValid())
{
NazaraError("Failed to create index buffer");
@ -364,49 +332,30 @@ bool NzMD5MeshParser::Parse(NzMesh* mesh)
continue;
}
switch (indexSize)
if (largeIndices)
{
case 1:
nzUInt32* index = reinterpret_cast<nzUInt32*>(ptr);
for (const Mesh::Triangle& triangle : md5Mesh.triangles)
{
nzUInt8* index = reinterpret_cast<nzUInt8*>(ptr);
for (const Mesh::Triangle& triangle : md5Mesh.triangles)
{
// On les respécifie dans le bon ordre
*index++ = triangle.x;
*index++ = triangle.z;
*index++ = triangle.y;
}
break;
// On les respécifie dans le bon ordre
*index++ = triangle.x;
*index++ = triangle.z;
*index++ = triangle.y;
}
}
else
{
nzUInt16* index = reinterpret_cast<nzUInt16*>(ptr);
case 2:
for (const Mesh::Triangle& triangle : md5Mesh.triangles)
{
nzUInt16* index = reinterpret_cast<nzUInt16*>(ptr);
for (const Mesh::Triangle& triangle : md5Mesh.triangles)
{
// On les respécifie dans le bon ordre
*index++ = triangle.x;
*index++ = triangle.z;
*index++ = triangle.y;
}
break;
}
case 4:
{
nzUInt32* index = reinterpret_cast<nzUInt32*>(ptr);
for (const Mesh::Triangle& triangle : md5Mesh.triangles)
{
// On les respécifie dans le bon ordre
*index++ = triangle.x;
*index++ = triangle.z;
*index++ = triangle.y;
}
break;
// On les respécifie dans le bon ordre
*index++ = triangle.x;
*index++ = triangle.z;
*index++ = triangle.y;
}
break;
}
if (!indexBuffer->Unmap())