PDA

View Full Version : More GPGPU Woes



Kip Warner
02-07-2010, 10:41 PM
I have a VBO containing an array of contiguous pairs, each of type GLuint, representing a location on a flat grid. I am trying to send this list of pairs to my shader, but I get a crash on the glDrawElements() call. Note that I'm not trying to "render" anything in a graphical sense. I just want this list to be fed to the shader and received as...



in uvec2 GridLocation;


Initializing the VBO...


// Initialize grid location pairs...

// Calculate required storage space for all location pairs...
GLuint const Storage = m_Width * m_Height * sizeof(GLuint) * 2;

// Allocate...
GLuint *pGridLocations = (GLuint *) malloc(Storage);

// Initialize vertex ordinals across the grid...
for(GLuint CurrentY = 0; CurrentY < m_Height; ++CurrentY)
for(GLuint CurrentX = 0; CurrentX < m_Width; ++CurrentX)
{
// Calculate current location...
GLuint *pCurrentLocation =
pGridLocations + (2 * ((CurrentY * m_Width) + CurrentX));

// Store grid index...
pCurrentLocation[0] = CurrentX;
pCurrentLocation[1] = CurrentY;
}

// Initialize vertex buffer object with vertex pairs...

// Allocate...
glGenBuffers(1, &amp;m_VBO_GridLocations);

// Select...
glBindBuffer(GL_ARRAY_BUFFER, m_VBO_GridLocations);

// Commit grid indices to card...
glBufferData(GL_ARRAY_BUFFER, Storage, pGridLocations, GL_STATIC_DRAW);

// Associate data with generic vertex attribute...
glVertexAttribPointer(m_GVA_GridLocations, 2, GL_UNSIGNED_INT, GL_FALSE, 0, BufferOffset(0));


Routine to pass data to shader to do some fancy calculations and store in FBO's attached texture.


// Re-evaluate the waves, but must be called at constant interval...
void Fluid::EvaluateWaves()
{
// Variables...
GLint Viewport[4] = { 0, 0, 0, 0 };

// Setup viewport for one to one pixel = texel = geometry mapping...

// Projection should not transform...
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, m_Width, 0.0, m_Height);

// There should be no modelview transformations either...
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// Lastly, backup viewport size, and resize to the size of grid maps...
glGetIntegerv(GL_VIEWPORT, Viewport);
glViewport(0, 0, m_Width, m_Height);

// Redirect rendering through our framebuffer object...
glBindFramebuffer(GL_FRAMEBUFFER, m_FrameBufferObject);

// Check for OpenGL errors...
PrintOpenGLErrors();

// Make sure data written to texture replaces and doesn't just modulate...
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

// Send grid location data to program...

// Install program...
glUseProgram(m_PO_EvaluateWaves);

// Select the Z map texture...
glBindTexture(GL_TEXTURE_2D, m_ZMaps_TextureID[0]);

// Enable required vertex arrays...
glEnableVertexAttribArray(m_GVA_GridLocations);

// Select the grid indices...
glBindBuffer(GL_ARRAY_BUFFER, m_VBO_GridLocations);

/****** Crashes on next line ******/
// Commit data to shader...
glDrawElements(GL_POINTS, m_Width * m_Height, GL_UNSIGNED_INT, BufferOffset(0));

// Disable required vertex arrays...
glDisableVertexAttribArray(m_GVA_GridLocations);

// Check for OpenGL errors...
PrintOpenGLErrors();

// Restore state...

// Default framebuffer...
glBindFramebuffer(GL_FRAMEBUFFER, 0);

// Viewport back to original dimensions...
glViewport(Viewport[0], Viewport[1], Viewport[2], Viewport[3]);

// Check for OpenGL errors...
PrintOpenGLErrors();
}


I've been trying to get this to work for two days now and of no luck. =(

Kip

Alfonse Reinheart
02-08-2010, 01:00 AM
There are several things wrong with this. But I can tell you why this crashes:


glDrawElements(GL_POINTS, m_Width * m_Height, GL_UNSIGNED_INT, BufferOffset(0));

glDrawElements does indexed rendering. This means you need an array of indices, which is what the last argument should refer to.

Since there is no buffer object bound to GL_ELEMENT_ARRAY_BUFFER, the last argument is a pointer. You passed in NULL. So the first thing this will doe is reference NULL.

So you either forgot to bind something to GL_ELEMENT_ARRAY_BUFFER, or you should be using glDrawArrays instead of glDrawElements.

Kip Warner
02-08-2010, 11:54 AM
Thanks Alfonse. I passed in NULL because I thought it would dereference from the currently bound VBO, but since I never bound one of the GL_ELEMENT_ARRAY_BUFFER, it makes sense that it would crash.

I used glDrawElements instead of glDrawArrays because the latter is apparently deprecated?

Can you think of a more sensible solution I should have pursued to just pass that list of pairs of GLuint into my shader?

I appreciate your spotting that error.

Alfonse Reinheart
02-08-2010, 12:09 PM
I used glDrawElements instead of glDrawArrays because the latter is apparently deprecated?

Says who?

Kip Warner
02-08-2010, 12:29 PM
Sorry, my bad, got it confused with glArrayElement. So you recommend glDrawArrays() API instead? I imagine I would allocate an element array buffer which is just the list of numbers from 0 to n-1 pairs. Correct?

Alfonse Reinheart
02-08-2010, 12:49 PM
OK, seriously, read this wiki page. (http://www.opengl.org/wiki/Vertex_Specification)

Kip Warner
02-08-2010, 03:50 PM
Thanks Alfonse. I've read it and it wasn't helpful.

I've changed the call to initialize the array with



glVertexAttribIPointer(m_GVA_GridLocations, 2, GL_UNSIGNED_INT, 0, BufferOffset(0));


Instead of the glVertexAttribPointer call.

I'm trying to send the list to the shader via


glDrawArrays(GL_POINTS, 0, m_Width * m_Height);


When I use glReadPixels to examine the output, it's the same junk as if I had never called glDrawArrays. My shader, as a test, should just be writing 0.0f for each pair sent.

I don't know what I've done wrong. I appreciate the links, but I've gone through over a thousand pages of material in the red book and the orange book, and sometimes we aren't perfect and miss something and someone more experienced pointing out a solution can be very helpful.