PDA

View Full Version : Having trouble with imageBuffers



jfslocum
07-26-2012, 07:38 AM
I'm in the middle of implementing linked-list transparency, and so I wrote a simple test program as a proof of concept for using texture buffers. Unfortunately, I'm having trouble getting it to work properly.

What the code is supposed to do is generate a 2D color gradient and display it on the screen. It does this with two separate shader invocations: in the first invocation, the fragment shader writes a color to the texture buffer that varies with gl_FragCoord.xy; the buffer location written to is gl_FragCoord.x + (gl_FragCoord.y * viewport_width). The second shader invocation merely reads from the same buffer and writes out to the framebuffer.

What I end up seeing instead is a small, horizontal line of pixels at the bottom-left of the screen - only a tiny section at the beginning of the buffer is being properly written (or read?). Through some finagling with the shader code, I found that the line is 64 pixels long. If I try to read the buffer into main memory to inspect it, I end up with a region of memory containing some data that appears more or less random.

I've been trying to figure out what's going wrong for quite a while now, so if anyone has encountered a similar problem before or has further suggestions for debugging, I'd be most grateful.

System specs:
Ubuntu Linux 11.04 64-bit
Radeon HD 5450
Catalyst v12.6



This is the shader I am using. The first invocation writes the pixel rank to a bufferTexture object (w_buffer). That object is then bound to r_buffer, and the second invocation reads from it and draws those pixels to the screen.


#version 420

#include <gtest/SmallImage.h>


layout(binding = SMALL_IMAGE_READ_UNIT, rgba8) readonly uniform image2D r_image;

layout(binding = SMALL_IMAGE_WRITE_UNIT, rgba8) writeonly uniform image2D w_image;


layout(binding = SMALL_BUFFER_READ_UNIT, rgba8) readonly uniform imageBuffer r_buffer;

layout(binding = SMALL_BUFFER_WRITE_UNIT, rgba8) writeonly uniform imageBuffer w_buffer;


subroutine void actual_main(void);
subroutine uniform actual_main exec;

subroutine vec4 imageReader(ivec2 coords);
subroutine uniform imageReader imRd;

subroutine void imageWriter(ivec2 coords, vec4 value);
subroutine uniform imageWriter imWt;

uniform uint viewport_height;
uniform uint viewport_width;


//NOTE: bottom-left pixel is at (0,0)
layout(pixel_center_integer) in vec4 gl_FragCoord;


smooth in vec2 texture_coords;
out vec4 out_color;

/*
* Subroutines that abstract image acess away from buffer/2d format
*/

//image2d
subroutine(imageReader) vec4 read2D(ivec2 coords)
{
return imageLoad(r_image, coords);
}

subroutine(imageWriter) void write2D(ivec2 coords, vec4 color)
{
imageStore(w_image, coords, color);
}


//buffers
int pixelToBufferCoords(ivec2 coords)
{
return coords.x + (coords.y * int(viewport_width));
}

subroutine(imageReader) vec4 readBuffer(ivec2 coords)
{
return imageLoad(r_buffer, pixelToBufferCoords(coords));
}

subroutine(imageWriter) void writeBuffer(ivec2 coords, vec4 color)
{
imageStore(w_buffer, pixelToBufferCoords(coords), color);
}



/*
* Subroutines set for test functionality
*/
subroutine(actual_main) void loadImageOrigin(void)
{
vec4 loaded = imRd(ivec2(int(gl_FragCoord.x),
int(gl_FragCoord.y)));
out_color = vec4(1.0,0.0,0.0,1.0);/*loaded.r,
loaded.g,
gl_FragCoord.y/1200.0,
1);*/
}


subroutine(actual_main) void pixelRank(void)
{
vec4 color = vec4(0.0f, 0.0f, 0.0f, 1.0f);
color.r = gl_FragCoord.x/viewport_width);
color.b = gl_FragCoord.y/viewport_height);
color.g = 1.0f;
imWt(ivec2(int(gl_FragCoord.x),
int(gl_FragCoord.y)),
color);
}

subroutine(actual_main) void readPixels(void)
{
vec4 loaded = imRd(ivec2(int(gl_FragCoord.x),
int(gl_FragCoord.y)));
out_color = vec4(loaded.r,
loaded.g,
loaded.b,
1.0);
}


void main(void)
{
exec();
}



This is my draw-loop. ReportGLErrors is just a macro that records any openGLerrors to disk.


WHILE_YNTEST(handler,nameWriter)
{
float64 time = (float64) timer.GetTime();

rend->InitFrame(time);

/*
* Refresh the texture if the viewport has changed size
*/
Height h = getViewportHeight();
Width w = getViewportWidth();
if(4*h.value*w.value != my_buff->getSize()) {
my_buff = GLBufferTexturePtr(vms_new GLBufferTexture(GL_RGBA8,
4*w.value*h.value));
lfReportGLerrors(&error);

my_buff->initialize();
lfReportGLerrors(&error);
}

/*
* To each pixel, write a color based on pixel rank
*/
my_buff->bindToImageUnit(SMALL_BUFFER_WRITE_UNIT, GL_WRITE_ONLY);
lfReportGLerrors(&error);

sits->setSub("pixelRank");
lfReportGLerrors(&error);
sits->renderWrapper(fullscreen_quad, ctx, time);
lfReportGLerrors(&error);

/*
* Now show the image
*/
my_buff->bindToImageUnit(SMALL_BUFFER_READ_UNIT, GL_READ_ONLY);

sits->setSub("readPixels");
lfReportGLerrors(&error);
sits->renderWrapper(fullscreen_quad, ctx, time);
lfReportGLerrors(&error);

rend->EndFrame(time);

//cap framerate at 100fps
boost::this_thread::sleep(boost::posix_time::milli seconds(10));
}

xahir
07-27-2012, 06:16 AM
just out of curiosity, do u set viewport_width uniform?

jfslocum
07-27-2012, 07:14 AM
just out of curiosity, do u set viewport_width uniform?

Yup. And I know that it's the correct value, because when I set the imageRead/Write subroutines to use an image2D instead of an imageBuffer, I get a smooth gradient along the X-axis that goes from no red to all red.