Commit 3edfe034 by Geoff Lang

Support primitive restart in RendererGL.

Store index ranges in a new struct that tracks how many real indices were seen. Update index caching to key on primitive restart being enabled and update index counting functions to skip primitive restart indicies when needed. Passes dEQP-GLES3.functional.primitive_restart.* Change-Id: Id1e25a5adcdcd4e998836e8ff6679c64be4c3066 Reviewed-on: https://chromium-review.googlesource.com/297770 Tryjob-Request: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 8f68be8b
......@@ -541,6 +541,26 @@ struct Range
typedef Range<int> RangeI;
typedef Range<unsigned int> RangeUI;
struct IndexRange
{
IndexRange() : IndexRange(0, 0, 0) {}
IndexRange(size_t start_, size_t end_, size_t vertexIndexCount_)
: start(start_), end(end_), vertexIndexCount(vertexIndexCount_)
{
ASSERT(start <= end);
}
// Number of vertices in the range.
size_t vertexCount() const { return (end - start) + 1; }
// Inclusive range of indices that are not primitive restart
size_t start;
size_t end;
// Number of non-primitive restart indices
size_t vertexIndexCount;
};
// First, both normalized floating-point values are converted into 16-bit integer values.
// Then, the results are packed into the returned 32-bit unsigned integer.
// The first float value will be written to the least significant bits of the output;
......
......@@ -19,6 +19,78 @@
# include <windows.graphics.display.h>
#endif
namespace
{
template <class IndexType>
gl::IndexRange ComputeTypedIndexRange(const IndexType *indices,
size_t count,
bool primitiveRestartEnabled,
GLuint primitiveRestartIndex)
{
ASSERT(count > 0);
IndexType minIndex = 0;
IndexType maxIndex = 0;
size_t nonPrimitiveRestartIndices = 0;
if (primitiveRestartEnabled)
{
// Find the first non-primitive restart index to initialize the min and max values
size_t i = 0;
for (; i < count; i++)
{
if (indices[i] != primitiveRestartIndex)
{
minIndex = indices[i];
maxIndex = indices[i];
nonPrimitiveRestartIndices++;
break;
}
}
// Loop over the rest of the indices
for (; i < count; i++)
{
if (indices[i] != primitiveRestartIndex)
{
if (minIndex > indices[i])
{
minIndex = indices[i];
}
if (maxIndex < indices[i])
{
maxIndex = indices[i];
}
nonPrimitiveRestartIndices++;
}
}
}
else
{
minIndex = indices[0];
maxIndex = indices[0];
nonPrimitiveRestartIndices = count;
for (size_t i = 1; i < count; i++)
{
if (minIndex > indices[i])
{
minIndex = indices[i];
}
if (maxIndex < indices[i])
{
maxIndex = indices[i];
}
}
}
return gl::IndexRange(static_cast<size_t>(minIndex), static_cast<size_t>(maxIndex),
nonPrimitiveRestartIndices);
}
} // anonymous namespace
namespace gl
{
......@@ -399,30 +471,44 @@ GLenum LayerIndexToCubeMapTextureTarget(size_t index)
return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
}
template <class IndexType>
static RangeUI ComputeTypedIndexRange(const IndexType *indices, GLsizei count)
IndexRange ComputeIndexRange(GLenum indexType,
const GLvoid *indices,
size_t count,
bool primitiveRestartEnabled)
{
ASSERT(count > 0);
IndexType minIndex = indices[0];
IndexType maxIndex = indices[0];
for (GLsizei i = 1; i < count; i++)
switch (indexType)
{
if (minIndex > indices[i]) minIndex = indices[i];
if (maxIndex < indices[i]) maxIndex = indices[i];
case GL_UNSIGNED_BYTE:
return ComputeTypedIndexRange(static_cast<const GLubyte *>(indices), count,
primitiveRestartEnabled,
GetPrimitiveRestartIndex(indexType));
case GL_UNSIGNED_SHORT:
return ComputeTypedIndexRange(static_cast<const GLushort *>(indices), count,
primitiveRestartEnabled,
GetPrimitiveRestartIndex(indexType));
case GL_UNSIGNED_INT:
return ComputeTypedIndexRange(static_cast<const GLuint *>(indices), count,
primitiveRestartEnabled,
GetPrimitiveRestartIndex(indexType));
default:
UNREACHABLE();
return IndexRange();
}
return RangeUI(static_cast<GLuint>(minIndex), static_cast<GLuint>(maxIndex));
}
RangeUI ComputeIndexRange(GLenum indexType, const GLvoid *indices, GLsizei count)
GLuint GetPrimitiveRestartIndex(GLenum indexType)
{
switch (indexType)
{
case GL_UNSIGNED_BYTE: return ComputeTypedIndexRange(static_cast<const GLubyte*>(indices), count);
case GL_UNSIGNED_SHORT: return ComputeTypedIndexRange(static_cast<const GLushort*>(indices), count);
case GL_UNSIGNED_INT: return ComputeTypedIndexRange(static_cast<const GLuint*>(indices), count);
default: UNREACHABLE(); return RangeUI(0, 0);
case GL_UNSIGNED_BYTE:
return 0xFF;
case GL_UNSIGNED_SHORT:
return 0xFFFF;
case GL_UNSIGNED_INT:
return 0xFFFFFFFF;
default:
UNREACHABLE();
return 0;
}
}
......
......@@ -50,7 +50,15 @@ GLenum LayerIndexToCubeMapTextureTarget(size_t index);
// set to GL_INVALID_INDEX if the provided name is not an array or the array index is invalid.
std::string ParseUniformName(const std::string &name, size_t *outSubscript);
RangeUI ComputeIndexRange(GLenum indexType, const GLvoid *indices, GLsizei count);
// Find the range of index values in the provided indices pointer. Primitive restart indices are
// only counted in the range if primitive restart is disabled.
IndexRange ComputeIndexRange(GLenum indexType,
const GLvoid *indices,
size_t count,
bool primitiveRestartEnabled);
// Get the primitive restart index value for the given index type.
GLuint GetPrimitiveRestartIndex(GLenum indexType);
bool IsTriangleMode(GLenum drawMode);
......
......@@ -160,22 +160,24 @@ void Buffer::onPixelUnpack()
mIndexRangeCache.clear();
}
Error Buffer::getIndexRange(GLenum type, size_t offset, size_t count, gl::RangeUI *outRange) const
Error Buffer::getIndexRange(GLenum type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
IndexRange *outRange) const
{
if (mIndexRangeCache.findRange(type, static_cast<unsigned int>(offset),
static_cast<GLsizei>(count), outRange))
if (mIndexRangeCache.findRange(type, offset, count, primitiveRestartEnabled, outRange))
{
return gl::Error(GL_NO_ERROR);
}
Error error = mBuffer->getIndexRange(type, offset, count, outRange);
Error error = mBuffer->getIndexRange(type, offset, count, primitiveRestartEnabled, outRange);
if (error.isError())
{
return error;
}
mIndexRangeCache.addRange(type, static_cast<unsigned int>(offset), static_cast<GLsizei>(count),
*outRange);
mIndexRangeCache.addRange(type, offset, count, primitiveRestartEnabled, *outRange);
return Error(GL_NO_ERROR);
}
......
......@@ -41,7 +41,11 @@ class Buffer : public RefCountObject
void onTransformFeedback();
void onPixelUnpack();
Error getIndexRange(GLenum type, size_t offset, size_t count, RangeUI *outRange) const;
Error getIndexRange(GLenum type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
IndexRange *outRange) const;
GLenum getUsage() const { return mUsage; }
GLbitfield getAccessFlags() const { return mAccessFlags; }
......
......@@ -1301,7 +1301,7 @@ Error Context::drawElements(GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
const RangeUI &indexRange)
const IndexRange &indexRange)
{
syncRendererState();
return mRenderer->drawElements(getData(), mode, count, type, indices, indexRange);
......@@ -1312,7 +1312,7 @@ Error Context::drawElementsInstanced(GLenum mode,
GLenum type,
const GLvoid *indices,
GLsizei instances,
const RangeUI &indexRange)
const IndexRange &indexRange)
{
syncRendererState();
return mRenderer->drawElementsInstanced(getData(), mode, count, type, indices, instances,
......@@ -1325,7 +1325,7 @@ Error Context::drawRangeElements(GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
const RangeUI &indexRange)
const IndexRange &indexRange)
{
syncRendererState();
return mRenderer->drawRangeElements(getData(), mode, start, end, count, type, indices,
......
......@@ -171,20 +171,20 @@ class Context final : angle::NonCopyable
GLsizei count,
GLenum type,
const GLvoid *indices,
const RangeUI &indexRange);
const IndexRange &indexRange);
Error drawElementsInstanced(GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
GLsizei instances,
const RangeUI &indexRange);
const IndexRange &indexRange);
Error drawRangeElements(GLenum mode,
GLuint start,
GLuint end,
GLsizei count,
GLenum type,
const GLvoid *indices,
const RangeUI &indexRange);
const IndexRange &indexRange);
Error flush();
Error finish();
......
......@@ -15,37 +15,22 @@
namespace gl
{
void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range)
void IndexRangeCache::addRange(GLenum type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
const IndexRange &range)
{
mIndexRangeCache[IndexRange(type, offset, count)] = range;
mIndexRangeCache[IndexRangeKey(type, offset, count, primitiveRestartEnabled)] = range;
}
void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size)
bool IndexRangeCache::findRange(GLenum type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
IndexRange *outRange) const
{
unsigned int invalidateStart = offset;
unsigned int invalidateEnd = offset + size;
IndexRangeMap::iterator i = mIndexRangeCache.begin();
while (i != mIndexRangeCache.end())
{
unsigned int rangeStart = i->first.offset;
unsigned int rangeEnd = i->first.offset + (GetTypeInfo(i->first.type).bytes * i->first.count);
if (invalidateEnd < rangeStart || invalidateStart > rangeEnd)
{
++i;
}
else
{
mIndexRangeCache.erase(i++);
}
}
}
bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count,
RangeUI *outRange) const
{
IndexRangeMap::const_iterator i = mIndexRangeCache.find(IndexRange(type, offset, count));
auto i = mIndexRangeCache.find(IndexRangeKey(type, offset, count, primitiveRestartEnabled));
if (i != mIndexRangeCache.end())
{
if (outRange)
......@@ -58,34 +43,71 @@ bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count,
{
if (outRange)
{
*outRange = RangeUI(0, 0);
*outRange = IndexRange();
}
return false;
}
}
void IndexRangeCache::invalidateRange(size_t offset, size_t size)
{
size_t invalidateStart = offset;
size_t invalidateEnd = offset + size;
auto i = mIndexRangeCache.begin();
while (i != mIndexRangeCache.end())
{
size_t rangeStart = i->first.offset;
size_t rangeEnd = i->first.offset + (GetTypeInfo(i->first.type).bytes * i->first.count);
if (invalidateEnd < rangeStart || invalidateStart > rangeEnd)
{
++i;
}
else
{
mIndexRangeCache.erase(i++);
}
}
}
void IndexRangeCache::clear()
{
mIndexRangeCache.clear();
}
IndexRangeCache::IndexRange::IndexRange()
: IndexRangeCache::IndexRange(GL_NONE, 0, 0)
IndexRangeCache::IndexRangeKey::IndexRangeKey()
: IndexRangeCache::IndexRangeKey(GL_NONE, 0, 0, false)
{
}
IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c)
: type(typ),
offset(static_cast<unsigned int>(off)),
count(c)
IndexRangeCache::IndexRangeKey::IndexRangeKey(GLenum type_,
size_t offset_,
size_t count_,
bool primitiveRestartEnabled_)
: type(type_), offset(offset_), count(count_), primitiveRestartEnabled(primitiveRestartEnabled_)
{
}
bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const
bool IndexRangeCache::IndexRangeKey::operator<(const IndexRangeKey &rhs) const
{
if (type != rhs.type) return type < rhs.type;
if (offset != rhs.offset) return offset < rhs.offset;
return count < rhs.count;
if (type != rhs.type)
{
return type < rhs.type;
}
if (offset != rhs.offset)
{
return offset < rhs.offset;
}
if (count != rhs.count)
{
return count < rhs.count;
}
if (primitiveRestartEnabled != rhs.primitiveRestartEnabled)
{
return primitiveRestartEnabled;
}
return false;
}
}
......@@ -23,26 +23,35 @@ namespace gl
class IndexRangeCache
{
public:
void addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range);
bool findRange(GLenum type, unsigned int offset, GLsizei count, RangeUI *rangeOut) const;
void invalidateRange(unsigned int offset, unsigned int size);
void addRange(GLenum type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
const IndexRange &range);
bool findRange(GLenum type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
IndexRange *outRange) const;
void invalidateRange(size_t offset, size_t size);
void clear();
private:
struct IndexRange
struct IndexRangeKey
{
GLenum type;
unsigned int offset;
GLsizei count;
IndexRangeKey();
IndexRangeKey(GLenum type, size_t offset, size_t count, bool primitiveRestart);
IndexRange();
IndexRange(GLenum type, intptr_t offset, GLsizei count);
bool operator<(const IndexRangeKey &rhs) const;
bool operator<(const IndexRange& rhs) const;
GLenum type;
size_t offset;
size_t count;
bool primitiveRestartEnabled;
};
typedef std::map<IndexRange, RangeUI> IndexRangeMap;
typedef std::map<IndexRangeKey, IndexRange> IndexRangeMap;
IndexRangeMap mIndexRangeCache;
};
......
......@@ -30,7 +30,11 @@ class BufferImpl : angle::NonCopyable
virtual gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) = 0;
virtual gl::Error unmap(GLboolean *result) = 0;
virtual gl::Error getIndexRange(GLenum type, size_t offset, size_t count, gl::RangeUI *outRange) = 0;
virtual gl::Error getIndexRange(GLenum type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
gl::IndexRange *outRange) = 0;
};
}
......
......@@ -28,7 +28,7 @@ class MockBufferImpl : public BufferImpl
MOCK_METHOD4(mapRange, gl::Error(size_t, size_t, GLbitfield, GLvoid **));
MOCK_METHOD1(unmap, gl::Error(GLboolean *result));
MOCK_METHOD4(getIndexRange, gl::Error(GLenum, size_t, size_t, gl::RangeUI *));
MOCK_METHOD5(getIndexRange, gl::Error(GLenum, size_t, size_t, bool, gl::IndexRange *));
MOCK_METHOD0(destructor, void());
};
......
......@@ -58,14 +58,14 @@ class Renderer : public ImplFactory
GLsizei count,
GLenum type,
const GLvoid *indices,
const gl::RangeUI &indexRange) = 0;
const gl::IndexRange &indexRange) = 0;
virtual gl::Error drawElementsInstanced(const gl::Data &data,
GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
GLsizei instances,
const gl::RangeUI &indexRange) = 0;
const gl::IndexRange &indexRange) = 0;
virtual gl::Error drawRangeElements(const gl::Data &data,
GLenum mode,
GLuint start,
......@@ -73,7 +73,7 @@ class Renderer : public ImplFactory
GLsizei count,
GLenum type,
const GLvoid *indices,
const gl::RangeUI &indexRange) = 0;
const gl::IndexRange &indexRange) = 0;
// lost device
//TODO(jmadill): investigate if this stuff is necessary in GL
......
......@@ -107,7 +107,11 @@ void BufferD3D::promoteStaticUsage(int dataSize)
}
}
gl::Error BufferD3D::getIndexRange(GLenum type, size_t offset, size_t count, gl::RangeUI *outRange)
gl::Error BufferD3D::getIndexRange(GLenum type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
gl::IndexRange *outRange)
{
const uint8_t *data = nullptr;
gl::Error error = getData(&data);
......@@ -116,7 +120,7 @@ gl::Error BufferD3D::getIndexRange(GLenum type, size_t offset, size_t count, gl:
return error;
}
*outRange = gl::ComputeIndexRange(type, data + offset, static_cast<GLsizei>(count));
*outRange = gl::ComputeIndexRange(type, data + offset, count, primitiveRestartEnabled);
return gl::Error(GL_NO_ERROR);
}
......
......@@ -46,7 +46,11 @@ class BufferD3D : public BufferImpl
void invalidateStaticData();
void promoteStaticUsage(int dataSize);
gl::Error getIndexRange(GLenum type, size_t offset, size_t count, gl::RangeUI *outRange) override;
gl::Error getIndexRange(GLenum type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
gl::IndexRange *outRange) override;
protected:
void updateSerial();
......
......@@ -9,6 +9,7 @@
#include "libANGLE/renderer/d3d/IndexDataManager.h"
#include "common/utilities.h"
#include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/IndexBuffer.h"
#include "libANGLE/Buffer.h"
......@@ -123,9 +124,11 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl::
{
// Avoid D3D11's primitive restart index value
// see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx
bool hasPrimitiveRestartIndex =
translated->indexRange.vertexIndexCount < static_cast<size_t>(count) ||
translated->indexRange.end == gl::GetPrimitiveRestartIndex(srcType);
bool primitiveRestartWorkaround = mRendererClass == RENDERER_D3D11 &&
translated->indexRange.end == 0xFFFF &&
srcType == GL_UNSIGNED_SHORT;
hasPrimitiveRestartIndex && srcType == GL_UNSIGNED_SHORT;
const GLenum dstType = (srcType == GL_UNSIGNED_INT || primitiveRestartWorkaround) ?
GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
......
......@@ -38,7 +38,7 @@ class RendererD3D;
struct TranslatedIndexData
{
gl::RangeUI indexRange;
gl::IndexRange indexRange;
unsigned int startIndex;
unsigned int startOffset; // In bytes
......
......@@ -86,7 +86,7 @@ gl::Error RendererD3D::drawElements(const gl::Data &data,
GLsizei count,
GLenum type,
const GLvoid *indices,
const gl::RangeUI &indexRange)
const gl::IndexRange &indexRange)
{
return genericDrawElements(data, mode, count, type, indices, 0, indexRange);
}
......@@ -97,7 +97,7 @@ gl::Error RendererD3D::drawElementsInstanced(const gl::Data &data,
GLenum type,
const GLvoid *indices,
GLsizei instances,
const gl::RangeUI &indexRange)
const gl::IndexRange &indexRange)
{
return genericDrawElements(data, mode, count, type, indices, instances, indexRange);
}
......@@ -109,7 +109,7 @@ gl::Error RendererD3D::drawRangeElements(const gl::Data &data,
GLsizei count,
GLenum type,
const GLvoid *indices,
const gl::RangeUI &indexRange)
const gl::IndexRange &indexRange)
{
return genericDrawElements(data, mode, count, type, indices, 0, indexRange);
}
......@@ -120,7 +120,7 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data,
GLenum type,
const GLvoid *indices,
GLsizei instances,
const gl::RangeUI &indexRange)
const gl::IndexRange &indexRange)
{
if (data.state->isPrimitiveRestartEnabled())
{
......@@ -175,8 +175,9 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data,
// layer.
ASSERT(!data.state->isTransformFeedbackActiveUnpaused());
GLsizei vertexCount = indexInfo.indexRange.length() + 1;
error = applyVertexBuffer(*data.state, mode, indexInfo.indexRange.start, vertexCount, instances, &sourceIndexInfo);
size_t vertexCount = indexInfo.indexRange.vertexCount();
error = applyVertexBuffer(*data.state, mode, static_cast<GLsizei>(indexInfo.indexRange.start),
static_cast<GLsizei>(vertexCount), instances, &sourceIndexInfo);
if (error.isError())
{
return error;
......
......@@ -109,14 +109,14 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
GLsizei count,
GLenum type,
const GLvoid *indices,
const gl::RangeUI &indexRange) override;
const gl::IndexRange &indexRange) override;
gl::Error drawElementsInstanced(const gl::Data &data,
GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
GLsizei instances,
const gl::RangeUI &indexRange) override;
const gl::IndexRange &indexRange) override;
gl::Error drawRangeElements(const gl::Data &data,
GLenum mode,
GLuint start,
......@@ -124,7 +124,7 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
GLsizei count,
GLenum type,
const GLvoid *indices,
const gl::RangeUI &indexRange) override;
const gl::IndexRange &indexRange) override;
bool isDeviceLost() const override;
std::string getVendorString() const override;
......@@ -270,7 +270,7 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
GLenum type,
const GLvoid *indices,
GLsizei instances,
const gl::RangeUI &indexRange);
const gl::IndexRange &indexRange);
virtual gl::Error drawArraysImpl(const gl::Data &data,
GLenum mode,
......
......@@ -1549,10 +1549,12 @@ gl::Error Renderer9::drawElementsImpl(GLenum mode,
}
else
{
size_t vertexCount = indexInfo.indexRange.vertexCount();
for (int i = 0; i < mRepeatDraw; i++)
{
GLsizei vertexCount = static_cast<int>(indexInfo.indexRange.length()) + 1;
mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount);
mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex,
static_cast<UINT>(vertexCount), indexInfo.startIndex,
mPrimitiveCount);
}
return gl::Error(GL_NO_ERROR);
}
......
......@@ -101,13 +101,17 @@ gl::Error BufferGL::unmap(GLboolean *result)
return gl::Error(GL_NO_ERROR);
}
gl::Error BufferGL::getIndexRange(GLenum type, size_t offset, size_t count, gl::RangeUI *outRange)
gl::Error BufferGL::getIndexRange(GLenum type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
gl::IndexRange *outRange)
{
ASSERT(!mIsMapped);
mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
const uint8_t *bufferData = reinterpret_cast<uint8_t*>(mFunctions->mapBuffer(DestBufferOperationTarget, GL_READ_ONLY));
*outRange = gl::ComputeIndexRange(type, bufferData + offset, static_cast<GLsizei>(count));
*outRange = gl::ComputeIndexRange(type, bufferData + offset, count, primitiveRestartEnabled);
mFunctions->unmapBuffer(DestBufferOperationTarget);
return gl::Error(GL_NO_ERROR);
......
......@@ -30,7 +30,11 @@ class BufferGL : public BufferImpl
gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) override;
gl::Error unmap(GLboolean *result) override;
gl::Error getIndexRange(GLenum type, size_t offset, size_t count, gl::RangeUI *outRange) override;
gl::Error getIndexRange(GLenum type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
gl::IndexRange *outRange) override;
GLuint getBufferID() const;
......
......@@ -170,7 +170,7 @@ gl::Error RendererGL::drawElements(const gl::Data &data,
GLsizei count,
GLenum type,
const GLvoid *indices,
const gl::RangeUI &indexRange)
const gl::IndexRange &indexRange)
{
const GLvoid *drawIndexPointer = nullptr;
gl::Error error =
......@@ -194,7 +194,7 @@ gl::Error RendererGL::drawElementsInstanced(const gl::Data &data,
GLenum type,
const GLvoid *indices,
GLsizei instances,
const gl::RangeUI &indexRange)
const gl::IndexRange &indexRange)
{
const GLvoid *drawIndexPointer = nullptr;
gl::Error error = mStateManager->setDrawElementsState(data, count, type, indices, instances,
......@@ -219,7 +219,7 @@ gl::Error RendererGL::drawRangeElements(const gl::Data &data,
GLsizei count,
GLenum type,
const GLvoid *indices,
const gl::RangeUI &indexRange)
const gl::IndexRange &indexRange)
{
const GLvoid *drawIndexPointer = nullptr;
gl::Error error =
......
......@@ -40,14 +40,14 @@ class RendererGL : public Renderer
GLsizei count,
GLenum type,
const GLvoid *indices,
const gl::RangeUI &indexRange) override;
const gl::IndexRange &indexRange) override;
gl::Error drawElementsInstanced(const gl::Data &data,
GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
GLsizei instances,
const gl::RangeUI &indexRange) override;
const gl::IndexRange &indexRange) override;
gl::Error drawRangeElements(const gl::Data &data,
GLenum mode,
GLuint start,
......@@ -55,7 +55,7 @@ class RendererGL : public Renderer
GLsizei count,
GLenum type,
const GLvoid *indices,
const gl::RangeUI &indexRange) override;
const gl::IndexRange &indexRange) override;
// Shader creation
CompilerImpl *createCompiler(const gl::Data &data) override;
......
......@@ -448,8 +448,9 @@ gl::Error StateManagerGL::setDrawElementsState(const gl::Data &data,
const gl::VertexArray *vao = state.getVertexArray();
const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
gl::Error error = vaoGL->syncDrawElementsState(program->getActiveAttribLocationsMask(), count,
type, indices, instanceCount, outIndices);
gl::Error error =
vaoGL->syncDrawElementsState(program->getActiveAttribLocationsMask(), count, type, indices,
instanceCount, state.isPrimitiveRestartEnabled(), outIndices);
if (error.isError())
{
return error;
......
......@@ -80,7 +80,7 @@ gl::Error VertexArrayGL::syncDrawArraysState(const gl::AttributesMask &activeAtt
GLsizei count,
GLsizei instanceCount) const
{
return syncDrawState(activeAttributesMask, first, count, GL_NONE, nullptr, instanceCount,
return syncDrawState(activeAttributesMask, first, count, GL_NONE, nullptr, instanceCount, false,
nullptr);
}
......@@ -89,9 +89,11 @@ gl::Error VertexArrayGL::syncDrawElementsState(const gl::AttributesMask &activeA
GLenum type,
const GLvoid *indices,
GLsizei instanceCount,
bool primitiveRestartEnabled,
const GLvoid **outIndices) const
{
return syncDrawState(activeAttributesMask, 0, count, type, indices, instanceCount, outIndices);
return syncDrawState(activeAttributesMask, 0, count, type, indices, instanceCount,
primitiveRestartEnabled, outIndices);
}
gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttributesMask,
......@@ -100,6 +102,7 @@ gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttribute
GLenum type,
const GLvoid *indices,
GLsizei instanceCount,
bool primitiveRestartEnabled,
const GLvoid **outIndices) const
{
mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
......@@ -108,11 +111,11 @@ gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttribute
bool attributesNeedStreaming = mAttributesNeedStreaming.any();
// Determine if an index buffer needs to be streamed and the range of vertices that need to be copied
RangeUI indexRange(0, 0);
IndexRange indexRange;
if (type != GL_NONE)
{
Error error =
syncIndexData(count, type, indices, attributesNeedStreaming, &indexRange, outIndices);
Error error = syncIndexData(count, type, indices, primitiveRestartEnabled,
attributesNeedStreaming, &indexRange, outIndices);
if (error.isError())
{
return error;
......@@ -140,8 +143,9 @@ gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttribute
Error VertexArrayGL::syncIndexData(GLsizei count,
GLenum type,
const GLvoid *indices,
bool primitiveRestartEnabled,
bool attributesNeedStreaming,
RangeUI *outIndexRange,
IndexRange *outIndexRange,
const GLvoid **outIndices) const
{
ASSERT(outIndices);
......@@ -163,7 +167,7 @@ Error VertexArrayGL::syncIndexData(GLsizei count,
{
ptrdiff_t elementArrayBufferOffset = reinterpret_cast<ptrdiff_t>(indices);
Error error = mData.getElementArrayBuffer()->getIndexRange(
type, static_cast<size_t>(elementArrayBufferOffset), count, outIndexRange);
type, elementArrayBufferOffset, count, primitiveRestartEnabled, outIndexRange);
if (error.isError())
{
return error;
......@@ -181,7 +185,7 @@ Error VertexArrayGL::syncIndexData(GLsizei count,
// Only compute the index range if the attributes also need to be streamed
if (attributesNeedStreaming)
{
*outIndexRange = ComputeIndexRange(type, indices, count);
*outIndexRange = ComputeIndexRange(type, indices, count, primitiveRestartEnabled);
}
// Allocate the streaming element array buffer
......@@ -218,7 +222,7 @@ Error VertexArrayGL::syncIndexData(GLsizei count,
void VertexArrayGL::computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask,
GLsizei instanceCount,
const gl::RangeUI &indexRange,
const gl::IndexRange &indexRange,
size_t *outStreamingDataSize,
size_t *outMaxAttributeDataSize) const
{
......@@ -233,21 +237,19 @@ void VertexArrayGL::computeStreamingAttributeSizes(const gl::AttributesMask &act
const auto &attrib = attribs[idx];
ASSERT(AttributeNeedsStreaming(attrib));
const size_t vertexCount = indexRange.end - indexRange.start + 1;
// If streaming is going to be required, compute the size of the required buffer
// and how much slack space at the beginning of the buffer will be required by determining
// the attribute with the largest data size.
size_t typeSize = ComputeVertexAttributeTypeSize(attrib);
*outStreamingDataSize +=
typeSize * ComputeVertexAttributeElementCount(attrib, vertexCount, instanceCount);
*outStreamingDataSize += typeSize * ComputeVertexAttributeElementCount(
attrib, indexRange.vertexCount(), instanceCount);
*outMaxAttributeDataSize = std::max(*outMaxAttributeDataSize, typeSize);
}
}
gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttributesMask,
GLsizei instanceCount,
const gl::RangeUI &indexRange) const
const gl::IndexRange &indexRange) const
{
// Sync the vertex attribute state and track what data needs to be streamed
size_t streamingDataSize = 0;
......@@ -289,8 +291,6 @@ gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttrib
uint8_t *bufferPointer = reinterpret_cast<uint8_t*>(mFunctions->mapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
size_t curBufferOffset = bufferEmptySpace;
const size_t vertexCount = indexRange.end - indexRange.start + 1;
const auto &attribs = mData.getVertexAttributes();
for (unsigned int idx :
angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask))
......@@ -299,7 +299,7 @@ gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttrib
ASSERT(AttributeNeedsStreaming(attrib));
const size_t streamedVertexCount =
ComputeVertexAttributeElementCount(attrib, vertexCount, instanceCount);
ComputeVertexAttributeElementCount(attrib, indexRange.vertexCount(), instanceCount);
const size_t sourceStride = ComputeVertexAttributeStride(attrib);
const size_t destStride = ComputeVertexAttributeTypeSize(attrib);
......
......@@ -32,6 +32,7 @@ class VertexArrayGL : public VertexArrayImpl
GLenum type,
const GLvoid *indices,
GLsizei instanceCount,
bool primitiveRestartEnabled,
const GLvoid **outIndices) const;
GLuint getVertexArrayID() const;
......@@ -46,24 +47,30 @@ class VertexArrayGL : public VertexArrayImpl
GLenum type,
const GLvoid *indices,
GLsizei instanceCount,
bool primitiveRestartEnabled,
const GLvoid **outIndices) const;
// Apply index data, only sets outIndexRange if attributesNeedStreaming is true
gl::Error syncIndexData(GLsizei count, GLenum type, const GLvoid *indices, bool attributesNeedStreaming,
gl::RangeUI *outIndexRange, const GLvoid **outIndices) const;
gl::Error syncIndexData(GLsizei count,
GLenum type,
const GLvoid *indices,
bool primitiveRestartEnabled,
bool attributesNeedStreaming,
gl::IndexRange *outIndexRange,
const GLvoid **outIndices) const;
// Returns the amount of space needed to stream all attributes that need streaming
// and the data size of the largest attribute
void computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask,
GLsizei instanceCount,
const gl::RangeUI &indexRange,
const gl::IndexRange &indexRange,
size_t *outStreamingDataSize,
size_t *outMaxAttributeDataSize) const;
// Stream attributes that have client data
gl::Error streamAttributes(const gl::AttributesMask &activeAttributesMask,
GLsizei instanceCount,
const gl::RangeUI &indexRange) const;
const gl::IndexRange &indexRange) const;
void updateNeedsStreaming(size_t attribIndex);
void updateAttribEnabled(size_t attribIndex);
......
......@@ -1642,8 +1642,13 @@ bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first
return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
}
bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices, GLsizei primcount, RangeUI *indexRangeOut)
bool ValidateDrawElements(Context *context,
GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
GLsizei primcount,
IndexRange *indexRangeOut)
{
switch (type)
{
......@@ -1728,7 +1733,9 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t
if (elementArrayBuffer)
{
uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Error error = elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count, indexRangeOut);
Error error =
elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
state.isPrimitiveRestartEnabled(), indexRangeOut);
if (error.isError())
{
context->recordError(error);
......@@ -1737,7 +1744,7 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t
}
else
{
*indexRangeOut = ComputeIndexRange(type, indices, count);
*indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
}
if (!ValidateDrawAttribs(context, primcount, static_cast<GLsizei>(indexRangeOut->end)))
......@@ -1745,13 +1752,17 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t
return false;
}
return true;
// No op if there are no real indices in the index data (all are primitive restart).
return (indexRangeOut->vertexIndexCount > 0);
}
bool ValidateDrawElementsInstanced(Context *context,
GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices, GLsizei primcount,
RangeUI *indexRangeOut)
GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
GLsizei primcount,
IndexRange *indexRangeOut)
{
if (primcount < 0)
{
......@@ -1768,8 +1779,13 @@ bool ValidateDrawElementsInstanced(Context *context,
return (primcount > 0);
}
bool ValidateDrawElementsInstancedANGLE(Context *context, GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices, GLsizei primcount, RangeUI *indexRangeOut)
bool ValidateDrawElementsInstancedANGLE(Context *context,
GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
GLsizei primcount,
IndexRange *indexRangeOut)
{
if (!ValidateDrawInstancedANGLE(context))
{
......
......@@ -87,13 +87,28 @@ bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei coun
bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount);
bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount);
bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices, GLsizei primcount, RangeUI *indexRangeOut);
bool ValidateDrawElementsInstanced(Context *context, GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices, GLsizei primcount, RangeUI *indexRangeOut);
bool ValidateDrawElementsInstancedANGLE(Context *context, GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices, GLsizei primcount, RangeUI *indexRangeOut);
bool ValidateDrawElements(Context *context,
GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
GLsizei primcount,
IndexRange *indexRangeOut);
bool ValidateDrawElementsInstanced(Context *context,
GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
GLsizei primcount,
IndexRange *indexRangeOut);
bool ValidateDrawElementsInstancedANGLE(Context *context,
GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
GLsizei primcount,
IndexRange *indexRangeOut);
bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
GLuint texture, GLint level);
......
......@@ -1184,7 +1184,7 @@ void GL_APIENTRY DrawElements(GLenum mode, GLsizei count, GLenum type, const GLv
Context *context = GetValidGlobalContext();
if (context)
{
RangeUI indexRange;
IndexRange indexRange;
if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange))
{
return;
......
......@@ -117,7 +117,7 @@ void GL_APIENTRY DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t
Context *context = GetValidGlobalContext();
if (context)
{
RangeUI indexRange;
IndexRange indexRange;
if (!ValidateDrawElementsInstancedANGLE(context, mode, count, type, indices, primcount, &indexRange))
{
return;
......
......@@ -59,7 +59,7 @@ void GL_APIENTRY DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsize
return;
}
RangeUI indexRange;
IndexRange indexRange;
if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange))
{
return;
......@@ -2264,7 +2264,7 @@ void GL_APIENTRY DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
return;
}
RangeUI indexRange;
IndexRange indexRange;
if (!ValidateDrawElementsInstanced(context, mode, count, type, indices, instanceCount, &indexRange))
{
return;
......
......@@ -157,7 +157,8 @@ void IndexDataManagerPerfTest::step(float dt, double totalTime)
rx::SourceIndexData sourceIndexData;
for (unsigned int iteration = 0; iteration < 100; ++iteration)
{
mIndexBuffer.getIndexRange(GL_UNSIGNED_SHORT, 0, mIndexCount, &translatedIndexData.indexRange);
mIndexBuffer.getIndexRange(GL_UNSIGNED_SHORT, 0, mIndexCount, false,
&translatedIndexData.indexRange);
mIndexDataManager.prepareIndexData(GL_UNSIGNED_SHORT, mIndexCount, &mIndexBuffer, nullptr, &translatedIndexData, &sourceIndexData);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment