Commit ae07e01f authored by Eric Bruneton's avatar Eric Bruneton
Browse files

fixed bug with GPUBuffer optimization 'cpuData' (buffers can be modified by GL...

fixed bug with GPUBuffer optimization 'cpuData' (buffers can be modified by GL via readPixels, TransformFeedback, etc)

git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/ork/trunk@15 28599a00-4e59-401b-b2d8-d34d4661a6c9
parent 88893df9
......@@ -220,6 +220,13 @@ private:
*/
virtual void unbind(int target) const = 0;
/**
* Notifies this buffer that it received new data on the GL side
* (via readPixels, transformFeedback, etc). This is only possible
* for a GPU buffer.
*/
virtual void dirty() const = 0;
friend class MeshBuffers;
friend class FrameBuffer;
......@@ -243,6 +250,8 @@ private:
friend class TextureCubeArray;
friend class TextureRectangle;
friend class TransformFeedback;
};
}
......
......@@ -54,4 +54,8 @@ void CPUBuffer::unbind(int target) const
{
}
void CPUBuffer::dirty() const
{
}
}
......@@ -55,6 +55,8 @@ protected:
virtual void unbind(int target) const;
virtual void dirty() const;
private:
/**
* The buffer data. May be NULL.
......
......@@ -1419,6 +1419,7 @@ void FrameBuffer::readPixels(int x, int y, int w, int h, TextureFormat f, PixelT
glReadPixels(x, y, w, h, getTextureFormat(f), getPixelType(t), dstBuf.data(0));
s.unset();
dstBuf.unbind(GL_PIXEL_PACK_BUFFER);
dstBuf.dirty();
assert(getError() == 0);
}
......
......@@ -199,7 +199,7 @@ GLuint UniformBufferManager::maxUnits = 0;
static UniformBufferManager* UNIFORM_BUFFER_MANAGER = NULL;
GPUBuffer::GPUBuffer() : size(0), mappedData(NULL), cpuData(NULL), currentUniformUnit(-1)
GPUBuffer::GPUBuffer() : size(0), mappedData(NULL), cpuData(NULL), isDirty(false), currentUniformUnit(-1)
{
if (UNIFORM_BUFFER_MANAGER == NULL) {
UNIFORM_BUFFER_MANAGER = new UniformBufferManager();
......@@ -250,6 +250,7 @@ void GPUBuffer::setData(int size, const void *data, BufferUsage u)
if (data != NULL) {
memcpy(cpuData, (unsigned char*) data, size);
}
isDirty = false;
}
#endif
}
......@@ -281,6 +282,12 @@ volatile void *GPUBuffer::map(BufferAccess a)
assert(mappedData == NULL);
if (cpuData != NULL) {
if (isDirty) {
glBindBuffer(GL_COPY_READ_BUFFER, bufferId);
glGetBufferSubData(GL_COPY_READ_BUFFER, 0, size, cpuData);
glBindBuffer(GL_COPY_READ_BUFFER, 0);
isDirty = false;
}
mappedData = cpuData;
} else {
glBindBuffer(GL_COPY_READ_BUFFER, bufferId);
......@@ -333,6 +340,11 @@ void GPUBuffer::unbind(int target) const
assert(FrameBuffer::getError() == GL_NO_ERROR);
}
void GPUBuffer::dirty() const
{
isDirty = true;
}
void GPUBuffer::addUser(GLuint programId) const
{
assert(find(programIds.begin(), programIds.end(), programId) == programIds.end());
......
......@@ -116,6 +116,8 @@ protected:
virtual void unbind(int target) const;
virtual void dirty() const;
private:
/**
* The OpenGL buffer identifier of this buffer (as returned by glGenBuffers).
......@@ -137,6 +139,12 @@ private:
*/
unsigned char *cpuData;
/**
* True if cpuData is dirty because the buffer data has changed on GPU
* (via readPixels, transformFeedback, etc).
*/
mutable bool isDirty;
/**
* The uniform block binding unit to which this buffer is currently bound,
* or -1 if it is not bound to any uniform block binding unit.
......
......@@ -81,12 +81,14 @@ void TransformFeedback::setVertexBuffer(int index, ptr<GPUBuffer> b)
{
bind(id);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, index, b->getId());
b.cast<Buffer>()->dirty();
}
void TransformFeedback::setVertexBuffer(int index, ptr<GPUBuffer> b, GLuint offset, GLuint size)
{
bind(id);
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index, b->getId(), GLintptr(offset), GLsizeiptr(size));
b.cast<Buffer>()->dirty();
}
void TransformFeedback::begin(ptr<FrameBuffer> fb, ptr<Program> transform, MeshMode m, ptr<TransformFeedback> tfb, bool rasterize)
......
Supports Markdown
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