Commit 7c82bc46 by Geoff Lang

Handle client data for draw calls with RendererGL.

BUG=angleproject:880 Change-Id: I67839d4934767db77cff7b501002c5aafbcbaef2 Reviewed-on: https://chromium-review.googlesource.com/257672Tested-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 84e91d39
...@@ -59,7 +59,12 @@ gl::Error RendererGL::finish() ...@@ -59,7 +59,12 @@ gl::Error RendererGL::finish()
gl::Error RendererGL::drawArrays(const gl::Data &data, GLenum mode, gl::Error RendererGL::drawArrays(const gl::Data &data, GLenum mode,
GLint first, GLsizei count, GLsizei instances) GLint first, GLsizei count, GLsizei instances)
{ {
mStateManager->setDrawState(data); gl::Error error = mStateManager->setDrawArraysState(data, first, count);
if (error.isError())
{
return error;
}
mFunctions->drawArrays(mode, first, count); mFunctions->drawArrays(mode, first, count);
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
...@@ -74,8 +79,14 @@ gl::Error RendererGL::drawElements(const gl::Data &data, GLenum mode, GLsizei co ...@@ -74,8 +79,14 @@ gl::Error RendererGL::drawElements(const gl::Data &data, GLenum mode, GLsizei co
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
mStateManager->setDrawState(data); const GLvoid *drawIndexPointer = nullptr;
mFunctions->drawElements(mode, count, type, indices); gl::Error error = mStateManager->setDrawElementsState(data, count, type, indices, &drawIndexPointer);
if (error.isError())
{
return error;
}
mFunctions->drawElements(mode, count, type, drawIndexPointer);
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
......
...@@ -56,7 +56,7 @@ void StateManagerGL::bindVertexArray(GLuint vao) ...@@ -56,7 +56,7 @@ void StateManagerGL::bindVertexArray(GLuint vao)
void StateManagerGL::bindBuffer(GLenum type, GLuint buffer) void StateManagerGL::bindBuffer(GLenum type, GLuint buffer)
{ {
if (mBuffers[type] == 0) if (mBuffers[type] != buffer)
{ {
mBuffers[type] = buffer; mBuffers[type] = buffer;
mFunctions->bindBuffer(type, buffer); mFunctions->bindBuffer(type, buffer);
...@@ -96,16 +96,42 @@ void StateManagerGL::setPixelUnpackState(GLint alignment, GLint rowLength) ...@@ -96,16 +96,42 @@ void StateManagerGL::setPixelUnpackState(GLint alignment, GLint rowLength)
} }
} }
void StateManagerGL::setDrawState(const gl::Data &data) gl::Error StateManagerGL::setDrawArraysState(const gl::Data &data, GLint first, GLsizei count)
{ {
const gl::State &state = *data.state; const gl::State &state = *data.state;
const gl::Caps &caps = *data.caps;
const gl::VertexArray *vao = state.getVertexArray(); const gl::VertexArray *vao = state.getVertexArray();
const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao); const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
vaoGL->syncState(); vaoGL->syncDrawArraysState(first, count);
bindVertexArray(vaoGL->getVertexArrayID()); bindVertexArray(vaoGL->getVertexArrayID());
return setGenericDrawState(data);
}
gl::Error StateManagerGL::setDrawElementsState(const gl::Data &data, GLsizei count, GLenum type, const GLvoid *indices,
const GLvoid **outIndices)
{
const gl::State &state = *data.state;
const gl::VertexArray *vao = state.getVertexArray();
const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
gl::Error error = vaoGL->syncDrawElementsState(count, type, indices, outIndices);
if (error.isError())
{
return error;
}
bindVertexArray(vaoGL->getVertexArrayID());
return setGenericDrawState(data);
}
gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data)
{
const gl::State &state = *data.state;
const gl::Caps &caps = *data.caps;
const gl::Program *program = state.getProgram(); const gl::Program *program = state.getProgram();
const ProgramGL *programGL = GetImplAs<ProgramGL>(program); const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
useProgram(programGL->getProgramID()); useProgram(programGL->getProgramID());
...@@ -154,6 +180,8 @@ void StateManagerGL::setDrawState(const gl::Data &data) ...@@ -154,6 +180,8 @@ void StateManagerGL::setDrawState(const gl::Data &data)
} }
} }
} }
return gl::Error(GL_NO_ERROR);
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#define LIBANGLE_RENDERER_GL_STATEMANAGERGL_H_ #define LIBANGLE_RENDERER_GL_STATEMANAGERGL_H_
#include "common/debug.h" #include "common/debug.h"
#include "libANGLE/Error.h"
#include "libANGLE/renderer/gl/functionsgl_typedefs.h" #include "libANGLE/renderer/gl/functionsgl_typedefs.h"
#include <map> #include <map>
...@@ -37,11 +38,15 @@ class StateManagerGL ...@@ -37,11 +38,15 @@ class StateManagerGL
void bindTexture(GLenum type, GLuint texture); void bindTexture(GLenum type, GLuint texture);
void setPixelUnpackState(GLint alignment, GLint rowLength); void setPixelUnpackState(GLint alignment, GLint rowLength);
void setDrawState(const gl::Data &data); gl::Error setDrawArraysState(const gl::Data &data, GLint first, GLsizei count);
gl::Error setDrawElementsState(const gl::Data &data, GLsizei count, GLenum type, const GLvoid *indices,
const GLvoid **outIndices);
private: private:
DISALLOW_COPY_AND_ASSIGN(StateManagerGL); DISALLOW_COPY_AND_ASSIGN(StateManagerGL);
gl::Error setGenericDrawState(const gl::Data &data);
const FunctionsGL *mFunctions; const FunctionsGL *mFunctions;
GLuint mProgram; GLuint mProgram;
......
...@@ -9,8 +9,10 @@ ...@@ -9,8 +9,10 @@
#include "libANGLE/renderer/gl/VertexArrayGL.h" #include "libANGLE/renderer/gl/VertexArrayGL.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/mathutil.h"
#include "libANGLE/Buffer.h" #include "libANGLE/Buffer.h"
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/gl/BufferGL.h" #include "libANGLE/renderer/gl/BufferGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h" #include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h" #include "libANGLE/renderer/gl/StateManagerGL.h"
...@@ -26,7 +28,11 @@ VertexArrayGL::VertexArrayGL(const FunctionsGL *functions, StateManagerGL *state ...@@ -26,7 +28,11 @@ VertexArrayGL::VertexArrayGL(const FunctionsGL *functions, StateManagerGL *state
mElementArrayBuffer(), mElementArrayBuffer(),
mAttributes(), mAttributes(),
mAppliedElementArrayBuffer(0), mAppliedElementArrayBuffer(0),
mAppliedAttributes() mAppliedAttributes(),
mStreamingElementArrayBufferSize(0),
mStreamingElementArrayBuffer(0),
mStreamingArrayBufferSize(0),
mStreamingArrayBuffer(0)
{ {
ASSERT(mFunctions); ASSERT(mFunctions);
ASSERT(mStateManager); ASSERT(mStateManager);
...@@ -47,7 +53,26 @@ VertexArrayGL::~VertexArrayGL() ...@@ -47,7 +53,26 @@ VertexArrayGL::~VertexArrayGL()
mVertexArrayID = 0; mVertexArrayID = 0;
} }
if (mStreamingElementArrayBuffer != 0)
{
mFunctions->deleteBuffers(1, &mStreamingElementArrayBuffer);
mStreamingElementArrayBufferSize = 0;
mStreamingElementArrayBuffer = 0;
}
if (mStreamingArrayBuffer != 0)
{
mFunctions->deleteBuffers(1, &mStreamingArrayBuffer);
mStreamingArrayBufferSize = 0;
mStreamingArrayBuffer = 0;
}
mElementArrayBuffer.set(nullptr); mElementArrayBuffer.set(nullptr);
for (size_t idx = 0; idx < mAttributes.size(); idx++)
{
mAttributes[idx].buffer.set(NULL);
}
for (size_t idx = 0; idx < mAppliedAttributes.size(); idx++) for (size_t idx = 0; idx < mAppliedAttributes.size(); idx++)
{ {
mAppliedAttributes[idx].buffer.set(NULL); mAppliedAttributes[idx].buffer.set(NULL);
...@@ -74,26 +99,88 @@ void VertexArrayGL::enableAttribute(size_t idx, bool enabledState) ...@@ -74,26 +99,88 @@ void VertexArrayGL::enableAttribute(size_t idx, bool enabledState)
mAttributes[idx].enabled = enabledState; mAttributes[idx].enabled = enabledState;
} }
void VertexArrayGL::syncState() const gl::Error VertexArrayGL::syncDrawArraysState(GLint first, GLsizei count) const
{
return syncDrawState(first, count, GL_NONE, nullptr, nullptr);
}
gl::Error VertexArrayGL::syncDrawElementsState(GLsizei count, GLenum type, const GLvoid *indices, const GLvoid **outIndices) const
{
return syncDrawState(0, count, type, indices, outIndices);
}
gl::Error VertexArrayGL::syncDrawState(GLint first, GLsizei count, GLenum type, const GLvoid *indices, const GLvoid **outIndices) const
{ {
mStateManager->bindVertexArray(mVertexArrayID); mStateManager->bindVertexArray(mVertexArrayID);
GLuint elementArrayBufferID = 0; // Check if any attributes need to be streamed, determines if the index range needs to be computed
if (mElementArrayBuffer.get() != nullptr) bool attributesNeedStreaming = doAttributesNeedStreaming();
// Determine if an index buffer needs to be streamed and the range of vertices that need to be copied
RangeUI indexRange(0, 0);
if (type != GL_NONE)
{ {
const BufferGL *bufferGL = GetImplAs<BufferGL>(mElementArrayBuffer.get()); gl::Error error = syncIndexData(count, type, indices, attributesNeedStreaming, &indexRange, outIndices);
elementArrayBufferID = bufferGL->getBufferID(); if (error.isError())
{
return error;
}
}
else
{
// Not an indexed call, set the range to [first, first + count)
indexRange.start = first;
indexRange.end = first + count;
}
// Sync the vertex attribute state and track what data needs to be streamed
size_t streamingDataSize = 0;
size_t maxAttributeDataSize = 0;
gl::Error error = syncAttributeState(attributesNeedStreaming, indexRange, &streamingDataSize, &maxAttributeDataSize);
if (error.isError())
{
return error;
}
if (streamingDataSize > 0)
{
ASSERT(attributesNeedStreaming);
gl::Error error = streamAttributes(streamingDataSize, maxAttributeDataSize, indexRange);
if (error.isError())
{
return error;
}
} }
if (elementArrayBufferID != mAppliedElementArrayBuffer) return gl::Error(GL_NO_ERROR);
}
bool VertexArrayGL::doAttributesNeedStreaming() const
{
// TODO: if GLES, nothing needs to be streamed
for (size_t idx = 0; idx < mAttributes.size(); idx++)
{ {
mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBufferID); if (mAttributes[idx].enabled && mAttributes[idx].buffer.get() == nullptr)
mAppliedElementArrayBuffer = elementArrayBufferID; {
return true;
}
} }
return false;
}
gl::Error VertexArrayGL::syncAttributeState(bool attributesNeedStreaming, const RangeUI &indexRange,
size_t *outStreamingDataSize, size_t *outMaxAttributeDataSize) const
{
*outStreamingDataSize = 0;
*outMaxAttributeDataSize = 0;
for (size_t idx = 0; idx < mAttributes.size(); idx++) for (size_t idx = 0; idx < mAttributes.size(); idx++)
{ {
if (mAppliedAttributes[idx] != mAttributes[idx]) // Always sync the enabled and divisor state, they are required for both streaming and buffered
// attributes
if (mAppliedAttributes[idx].enabled != mAttributes[idx].enabled)
{ {
if (mAttributes[idx].enabled) if (mAttributes[idx].enabled)
{ {
...@@ -103,37 +190,230 @@ void VertexArrayGL::syncState() const ...@@ -103,37 +190,230 @@ void VertexArrayGL::syncState() const
{ {
mFunctions->disableVertexAttribArray(idx); mFunctions->disableVertexAttribArray(idx);
} }
mAppliedAttributes[idx].enabled = mAttributes[idx].enabled;
}
if (mAppliedAttributes[idx].divisor != mAttributes[idx].divisor)
{
mFunctions->vertexAttribDivisor(idx, mAttributes[idx].divisor);
mAppliedAttributes[idx].divisor = mAttributes[idx].divisor;
}
if (mAttributes[idx].enabled && mAttributes[idx].buffer.get() == nullptr)
{
ASSERT(attributesNeedStreaming);
const size_t streamedVertexCount = indexRange.end - indexRange.start + 1;
const gl::Buffer *arrayBuffer = mAttributes[idx].buffer.get(); // If streaming is going to be required, compute the size of the required buffer
if (arrayBuffer != nullptr) // 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(mAttributes[idx]);
*outStreamingDataSize += typeSize * streamedVertexCount;
*outMaxAttributeDataSize = std::max(*outMaxAttributeDataSize, typeSize);
}
else
{
// Sync the attribute with no translation
if (mAppliedAttributes[idx] != mAttributes[idx])
{ {
const gl::Buffer *arrayBuffer = mAttributes[idx].buffer.get();
const BufferGL *arrayBufferGL = GetImplAs<BufferGL>(arrayBuffer); const BufferGL *arrayBufferGL = GetImplAs<BufferGL>(arrayBuffer);
mStateManager->bindBuffer(GL_ARRAY_BUFFER, arrayBufferGL->getBufferID()); mStateManager->bindBuffer(GL_ARRAY_BUFFER, arrayBufferGL->getBufferID());
if (mAttributes[idx].pureInteger)
{
mFunctions->vertexAttribIPointer(idx, mAttributes[idx].size, mAttributes[idx].type,
mAttributes[idx].stride, mAttributes[idx].pointer);
}
else
{
mFunctions->vertexAttribPointer(idx, mAttributes[idx].size, mAttributes[idx].type,
mAttributes[idx].normalized, mAttributes[idx].stride,
mAttributes[idx].pointer);
}
mAppliedAttributes[idx] = mAttributes[idx];
} }
else }
{ }
// This will take some extra work, core OpenGL doesn't support binding raw data pointers
// to VAOs return gl::Error(GL_NO_ERROR);
UNIMPLEMENTED(); }
}
if (mAttributes[idx].pureInteger) gl::Error VertexArrayGL::syncIndexData(GLsizei count, GLenum type, const GLvoid *indices, bool attributesNeedStreaming,
RangeUI *outIndexRange, const GLvoid **outIndices) const
{
ASSERT(outIndices);
// Need to check the range of indices if attributes need to be streamed
if (mElementArrayBuffer.get() != nullptr)
{
const BufferGL *bufferGL = GetImplAs<BufferGL>(mElementArrayBuffer.get());
GLuint elementArrayBufferID = bufferGL->getBufferID();
if (elementArrayBufferID != mAppliedElementArrayBuffer)
{
mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBufferID);
mAppliedElementArrayBuffer = elementArrayBufferID;
}
// Only compute the index range if the attributes also need to be streamed
if (attributesNeedStreaming)
{
ptrdiff_t elementArrayBufferOffset = reinterpret_cast<ptrdiff_t>(indices);
// Find the index range in the buffer
const IndexRangeCache *rangeCache = mElementArrayBuffer.get()->getIndexRangeCache();
unsigned int streamOffset = 0;
if (!rangeCache->findRange(type, elementArrayBufferOffset, count, outIndexRange, &streamOffset))
{ {
mFunctions->vertexAttribIPointer(idx, mAttributes[idx].size, mAttributes[idx].type, // Need to compute the index range.
mAttributes[idx].stride, mAttributes[idx].pointer); mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBufferID);
uint8_t *elementArrayBufferPointer = reinterpret_cast<uint8_t*>(mFunctions->mapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY));
*outIndexRange = IndexRangeCache::ComputeRange(type, elementArrayBufferPointer + elementArrayBufferOffset, count);
// TODO: Store the range cache at the impl level since the gl::Buffer object is supposed to remain constant
const_cast<IndexRangeCache*>(rangeCache)->addRange(type, elementArrayBufferOffset, count, *outIndexRange, 0);
if (!mFunctions->unmapBuffer(GL_ELEMENT_ARRAY_BUFFER))
{
return gl::Error(GL_OUT_OF_MEMORY);
}
} }
else }
// Indices serves as an offset into the index buffer in this case, use the same value for the draw call
*outIndices = indices;
}
else
{
// Need to stream the index buffer
// TODO: if GLES, nothing needs to be streamed
// Only compute the index range if the attributes also need to be streamed
if (attributesNeedStreaming)
{
*outIndexRange = IndexRangeCache::ComputeRange(type, indices, count);
}
// Allocate the streaming element array buffer
if (mStreamingElementArrayBuffer == 0)
{
mFunctions->genBuffers(1, &mStreamingElementArrayBuffer);
mStreamingElementArrayBufferSize = 0;
}
mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mStreamingElementArrayBuffer);
mAppliedElementArrayBuffer = mStreamingElementArrayBuffer;
// Make sure the element array buffer is large enough
const gl::Type &indexTypeInfo = gl::GetTypeInfo(type);
size_t requiredStreamingBufferSize = indexTypeInfo.bytes * count;
if (requiredStreamingBufferSize > mStreamingElementArrayBufferSize)
{
// Copy the indices in while resizing the buffer
mFunctions->bufferData(GL_ELEMENT_ARRAY_BUFFER, requiredStreamingBufferSize, indices, GL_DYNAMIC_DRAW);
mStreamingElementArrayBufferSize = requiredStreamingBufferSize;
}
else
{
// Put the indices at the beginning of the buffer
mFunctions->bufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, requiredStreamingBufferSize, indices);
}
// Set the index offset for the draw call to zero since the supplied index pointer is to client data
*outIndices = nullptr;
}
return gl::Error(GL_NO_ERROR);
}
gl::Error VertexArrayGL::streamAttributes(size_t streamingDataSize, size_t maxAttributeDataSize, const RangeUI &indexRange) const
{
if (mStreamingArrayBuffer == 0)
{
mFunctions->genBuffers(1, &mStreamingArrayBuffer);
mStreamingArrayBufferSize = 0;
}
// If first is greater than zero, a slack space needs to be left at the beginning of the buffer so that
// the same 'first' argument can be passed into the draw call.
const size_t bufferEmptySpace = maxAttributeDataSize * indexRange.start;
const size_t requiredBufferSize = streamingDataSize + bufferEmptySpace;
mStateManager->bindBuffer(GL_ARRAY_BUFFER, mStreamingArrayBuffer);
if (requiredBufferSize > mStreamingArrayBufferSize)
{
mFunctions->bufferData(GL_ARRAY_BUFFER, requiredBufferSize, nullptr, GL_DYNAMIC_DRAW);
mStreamingArrayBufferSize = requiredBufferSize;
}
// Unmapping a buffer can return GL_FALSE to indicate that the system has corrupted the data
// somehow (such as by a screen change), retry writing the data a few times and return OUT_OF_MEMORY
// if that fails.
GLboolean unmapResult = GL_FALSE;
size_t unmapRetryAttempts = 5;
while (unmapResult != GL_TRUE && --unmapRetryAttempts > 0)
{
uint8_t *bufferPointer = reinterpret_cast<uint8_t*>(mFunctions->mapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
size_t curBufferOffset = bufferEmptySpace;
const size_t streamedVertexCount = indexRange.end - indexRange.start + 1;
for (size_t idx = 0; idx < mAttributes.size(); idx++)
{
if (mAttributes[idx].enabled && mAttributes[idx].buffer.get() == nullptr)
{ {
const size_t sourceStride = ComputeVertexAttributeStride(mAttributes[idx]);
const size_t destStride = ComputeVertexAttributeTypeSize(mAttributes[idx]);
const uint8_t *inputPointer = reinterpret_cast<const uint8_t*>(mAttributes[idx].pointer);
// Pack the data when copying it, user could have supplied a very large stride that would
// cause the buffer to be much larger than needed.
if (destStride == sourceStride)
{
// Can copy in one go, the data is packed
memcpy(bufferPointer + curBufferOffset,
inputPointer + (sourceStride * indexRange.start),
destStride * streamedVertexCount);
}
else
{
// Copy each vertex individually
for (size_t vertexIdx = indexRange.start; vertexIdx <= indexRange.end; vertexIdx++)
{
memcpy(bufferPointer + curBufferOffset + (destStride * vertexIdx),
inputPointer + (sourceStride * vertexIdx),
destStride);
}
}
// Compute where the 0-index vertex would be.
const size_t vertexStartOffset = curBufferOffset - (indexRange.start * destStride);
mFunctions->vertexAttribPointer(idx, mAttributes[idx].size, mAttributes[idx].type, mFunctions->vertexAttribPointer(idx, mAttributes[idx].size, mAttributes[idx].type,
mAttributes[idx].normalized, mAttributes[idx].stride, mAttributes[idx].normalized, destStride,
mAttributes[idx].pointer); reinterpret_cast<const GLvoid*>(vertexStartOffset));
}
mFunctions->vertexAttribDivisor(idx, mAttributes[idx].divisor); curBufferOffset += destStride * streamedVertexCount;
mAppliedAttributes[idx] = mAttributes[idx]; // Mark the applied attribute as dirty by setting an invalid size so that if it doesn't
// need to be streamed later, there is no chance that the caching will skip it.
mAppliedAttributes[idx].size = static_cast<GLuint>(-1);
}
} }
unmapResult = mFunctions->unmapBuffer(GL_ARRAY_BUFFER);
} }
if (unmapResult != GL_TRUE)
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to unmap the client data streaming buffer.");
}
return gl::Error(GL_NO_ERROR);
} }
GLuint VertexArrayGL::getVertexArrayID() const GLuint VertexArrayGL::getVertexArrayID() const
......
...@@ -28,13 +28,31 @@ class VertexArrayGL : public VertexArrayImpl ...@@ -28,13 +28,31 @@ class VertexArrayGL : public VertexArrayImpl
void setAttributeDivisor(size_t idx, GLuint divisor) override; void setAttributeDivisor(size_t idx, GLuint divisor) override;
void enableAttribute(size_t idx, bool enabledState) override; void enableAttribute(size_t idx, bool enabledState) override;
void syncState() const; gl::Error syncDrawArraysState(GLint first, GLsizei count) const;
gl::Error syncDrawElementsState(GLsizei count, GLenum type, const GLvoid *indices, const GLvoid **outIndices) const;
GLuint getVertexArrayID() const; GLuint getVertexArrayID() const;
private: private:
DISALLOW_COPY_AND_ASSIGN(VertexArrayGL); DISALLOW_COPY_AND_ASSIGN(VertexArrayGL);
gl::Error syncDrawState(GLint first, GLsizei count, GLenum type, const GLvoid *indices, const GLvoid **outIndices) const;
// Check if any vertex attributes need to be streamed
bool doAttributesNeedStreaming() const;
// Apply attribute state, returns the amount of space needed to stream all attributes that need streaming
// and the data size of the largest attribute
gl::Error syncAttributeState(bool attributesNeedStreaming, const RangeUI &indexRange, size_t *outStreamingDataSize,
size_t *outMaxAttributeDataSize) const;
// Apply index data, only sets outIndexRange if attributesNeedStreaming is true
gl::Error syncIndexData(GLsizei count, GLenum type, const GLvoid *indices, bool attributesNeedStreaming,
RangeUI *outIndexRange, const GLvoid **outIndices) const;
// Stream attributes that have client data
gl::Error streamAttributes(size_t streamingDataSize, size_t maxAttributeDataSize, const RangeUI &indexRange) const;
const FunctionsGL *mFunctions; const FunctionsGL *mFunctions;
StateManagerGL *mStateManager; StateManagerGL *mStateManager;
...@@ -45,6 +63,12 @@ class VertexArrayGL : public VertexArrayImpl ...@@ -45,6 +63,12 @@ class VertexArrayGL : public VertexArrayImpl
mutable GLuint mAppliedElementArrayBuffer; mutable GLuint mAppliedElementArrayBuffer;
mutable std::vector<gl::VertexAttribute> mAppliedAttributes; mutable std::vector<gl::VertexAttribute> mAppliedAttributes;
mutable size_t mStreamingElementArrayBufferSize;
mutable GLuint mStreamingElementArrayBuffer;
mutable size_t mStreamingArrayBufferSize;
mutable GLuint mStreamingArrayBuffer;
}; };
} }
......
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