PDA

View Full Version : VBO - index data gets corrupted



arabesc
05-26-2009, 05:00 PM
The new index data gets corrupted after discarding previous index buffer through the glBufferData(GL_ELEMENT_ARRAY_BUFFER, size_, 0, GL_DYNAMIC_DRAW) call.
Some parts of the scene have missing triangles, other parts are looks like a chaotic triangles soup.

I have tested it on ATi HD3850, Catalyst 9.5, WinXP SP3.
I will test tomorrow on nVidia board, but I think there are should not be any problems.

This is a lock method of my dynamic index buffer class:

CDynamicIndexBuffer::write_lock CDynamicIndexBuffer::lock_for_fill(std::size_t stride,
std::size_t count,
std::size_t &start_offset)
{
const std::size_t lock_size = stride*count;
if (lock_size > size_)
throw std::runtime_error("dynamic index lock size is too large");

if (!size_)
return write_lock();

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_id_);
CHECK_GL_ERRORS();

const std::size_t offset = (stride - (offset_ % stride)) % stride;
offset_ += offset;

const bool discard = offset_ + lock_size > size_;

void *data = 0;

if (GLEW_ARB_map_buffer_range)
{
GLbitfield access = GL_MAP_WRITE_BIT;

if (discard)
{
offset_ = 0;
access |= GL_MAP_INVALIDATE_BUFFER_BIT;
}
else
access |= GL_MAP_INVALIDATE_RANGE_BIT;

data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, offset_, lock_size, access);
CHECK_GL_ERRORS();
}
else
{
if (discard)
{
offset_ = 0;
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size_, 0, GL_DYNAMIC_DRAW); // discard old buffer
CHECK_GL_ERRORS();
}

data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
CHECK_GL_ERRORS();
data = data ? advance_pointer<void>(data, offset_) : data;
}

if (!data)
return write_lock();

start_offset = offset_;
offset_ += lock_size;

return write_lock(*this, unlock_wrapper, data);
}
The GLEW_ARB_map_buffer_range branch is working as it should.
The problem is with else branch. It is not working normally. But it will work without any side effects if I remove glBufferData call.
Is it a driver bug or my incorrect usage of OGL?

bertgp
05-27-2009, 07:18 AM
I can't see anything wrong with your code right now. Try reading back the data from the VBO and doing a memcmp with what you expect to have in the buffer. Maybe this will give you a hint.

arabesc
05-27-2009, 08:00 AM
I has tested it on nVidia - all is ok.


Try reading back the data from the VBO and doing a memcmp with what you expect to have in the buffer.
Good idea!
I make it in this way:

bool CDynamicIndexBuffer::unlock() const
{
assert(locked_);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_id_);
CHECK_GL_ERRORS();

void *data;

data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
memcpy(data, &amp;temp_.front(), temp_.size());
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);

if (true) // point of interest
{
data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY);
assert(0 == memcmp(data, &amp;temp_.front(), temp_.size()));
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
}

locked_ = false;

return true;
}
And what you think? It's now working without any problems!
But if I disable check of the index buffer content the bug strikes back :(

tamlin
05-28-2009, 01:39 AM
Suggestions:
1. Check the return value from the glUnmapBuffer call.
2. Comment out the memcmp, effectively using the old code but with the additional (but should-be quite redundant) Map/Unmap READ_ONLY.

It could help getting closer to solve the mystery.

arabesc
05-28-2009, 03:16 AM
Check the return value from the glUnmapBuffer call.
I have checking the return value in the previous implementation. It is ok.


Comment out the memcmp, effectively using the old code but with the additional (but should-be quite redundant) Map/Unmap READ_ONLY.
Already did it. memcmp have no influence on effect.
So there is no mystery. The second readonly glMapBuffer actually make some synchronization.
I think it is a driver bug. As usual on ATi/AMD...

_NK47
05-28-2009, 10:05 AM
the first post doesnt show an glUnmapBuffer only a glMapBuffer. the third one shows glUnmapBuffer and you say its working. you might not unlock the buffer before rendering?

arabesc
05-28-2009, 01:56 PM
the first post doesnt show an glUnmapBuffer only a glMapBuffer.
becouse it's lock method of the dynamic index buffer class


the third one shows glUnmapBuffer and you say its working.
it's working only with double glMapBuffer/glUnmapBuffer calls
see the code carefully


you might not unlock the buffer before rendering?
this situation is not possible because locking is encapsulated in the smart object (like smartpointer)
unlock will be called automatically when the lock object goes out of scope
and of course I checked this

do you think that bugs in ATi OpenGL drivers are unusual thing?

_NK47
05-28-2009, 02:22 PM
you're right. didn't checked properly, my bad.

"do you think that bugs in ATi OpenGL drivers are unusual thing?"
find out by installing latest drivers or alternate ATI drivers like Omega drivers. But yeah ATI drivers are better Direct3D neglecting OpenGL here and there.