Jump to content

  • Log In with Google      Sign In   
  • Create Account


#Actualmhagain

Posted 15 September 2012 - 06:39 AM

Your main problem with this code is the way you're updating your VBO. Calling glBufferSubData in this manner is going to lead to pipeline stalls and flushes, and doing it potentially so many times per frame will make things worse. You need to implement proper buffer streaming to get this working well; have a read of this post for a description of the technique.

Sample code:
GLuint bufferid;
int buffersize = 0x400000;
int bufferoffset = 0;

void StreamBuffer (void *data, int batchsize)
{
	glBindBuffer (GL_ARRAY_BUFFER, bufferid);

	if (bufferoffset + batchsize >= buffersize)
	{
		glBufferData (GL_ARRAY_BUFFER, buffersize, NULL, GL_STREAM_DRAW);
		bufferoffset = 0;
	}

	GLbitfield access = (GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
	void *mappeddata = glMapBufferRange (GL_ARRAY_BUFFER, bufferoffset, bufferoffset + batchsize, access);

	if (mappeddata)
	{
		memcpy (mappeddata, data, batchsize);
		glUnmapBuffer (GL_ARRAY_BUFFER);
		glDrawArrays ( .... );
		bufferoffset += batchsize;
	}
}
Ideally you wouldn't memcpy here; you'd generate the batch data directly into the pointer returned from glMapBufferRange instead. That's not always possible though, and memcpy is fine for many (if not most) use cases - the key is in avoiding pipeline stalls and the CPU-side overhead from memcpy is going to be very low by comparison.

#3mhagain

Posted 15 September 2012 - 06:39 AM

Your main problem with this code is the way you're updating your VBO. Calling glBufferSubData in this manner is going to lead to pipeline stalls and flushes, and doing it potentially so many times per frame will make things worse. You need to implement proper buffer streaming to get this working well; have a read of this post for a description of the technique.

Sample code:
GLuint bufferid;
int buffersize = 0x400000;
int bufferoffset = 0;

void StreamBuffer (void *data, int batchsize)
{
    glBindBuffer (GL_ARRAY_BUFFER, bufferid);
    if (bufferoffset + batchsize >= buffersize)
    {
	    glBufferData (GL_ARRAY_BUFFER, buffersize, NULL, GL_STREAM_DRAW);
	    bufferoffset = 0;
    }
    GLbitfield access = (GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
    void *mappeddata = glMapBufferRange (GL_ARRAY_BUFFER, bufferoffset, bufferoffset + batchsize, access);
    if (mappeddata)
    {
	    memcpy (mappeddata, data, batchsize);
	    glUnmapBuffer (GL_ARRAY_BUFFER);
	    glDrawArrays ( .... );
	    bufferoffset += batchsize;
    }
}
Ideally you wouldn't memcpy here; you'd generate the batch data directly into the pointer returned from glMapBufferRange instead. That's not always possible though, and memcpy is fine for many (if not most) use cases - the key is in avoiding pipeline stalls and the CPU-side overhead from memcpy is going to be very low by comparison.

#2mhagain

Posted 15 September 2012 - 06:25 AM

Your main problem with this code is the way you're updating your VBO. Calling glBufferSubData in this manner is going to lead to pipeline stalls and flushes, and doing it potentially so many times per frame will make things worse. You need to implement proper buffer streaming to get this working well; have a read of this post for a description of the technique.

Sample code:
GLuint bufferid;
int buffersize = 0x400000;
int bufferoffset = 0;
void StreamBuffer (void *data, int batchsize)
{
glBindBuffer (GL_ARRAY_BUFFER, bufferid);
if (bufferoffset + batchsize >= buffersize)
{
  glBufferData (GL_ARRAY_BUFFER, buffersize, NULL, GL_STREAM_DRAW);
  bufferoffset = 0;
}
GLbitfield access = (GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
void *mappeddata = glMapBufferRange (GL_ARRAY_BUFFER, bufferoffset, batchsize, access);
if (mappeddata)
{
  memcpy (mappeddata, data, batchsize);
  glUnmapBuffer (GL_ARRAY_BUFFER);
  glDrawArrays ( .... );
  bufferoffset += batchsize;
}
}

#1mhagain

Posted 15 September 2012 - 06:20 AM

Your main problem with this code is the way you're updating your VBO. Calling glBufferSubData in this manner is going to lead to pipeline stalls and flushes, and doing it potentially so many times per frame will make things worse. You need to implement proper buffer streaming to get this working well; have a read of this post for a description of the technique.

Sample code:
GLuint bufferid;
int buffersize = 0x400000;
int bufferoffset = 0;
void StreamBuffer (void *data, int batchsize)
{
glBindBuffer (GL_ARRAY_BUFFER, bufferid);
if (bufferoffset + batchsize >= buffersize)
{
  glBufferData (GL_ARRAY_BUFFER, buffersize, NULL, GL_STREAM_DRAW);
  bufferoffset = 0;
}
GLbitfield access = (GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
void *mappeddata = glMapBufferRange (GL_ARRAY_BUFFER, bufferoffset, bufferoffset + batchsize, access);
if (mappeddata)
{
  memcpy (mappeddata, data, batchsize);
  glUnmapBuffer (GL_ARRAY_BUFFER);
  glDrawArrays ( .... );
  bufferoffset += batchsize;
}
}

PARTNERS