PDA

View Full Version : Failing to use EXT_shader_image_load_store :/



Groovounet
03-10-2011, 11:29 AM
Hi,

I try to use EXT_shader_image_load_store but without success. I tried already month ago with the same luck.

My problem: The texel I fetch appear all black on nVidia without OpenGL error and on AMD it crash on glTextureImageEXT call.

So far the only think I am trying to do is to read texel to texture a quad.

Here is the code:


#include <glf/glf.hpp>

namespace
{
std::string const SAMPLE_NAME = "OpenGL Image texture";
std::string const VERTEX_SHADER_SOURCE(glf::DATA_DIRECTORY + "410/image-texture.vert");
std::string const FRAGMENT_SHADER_SOURCE(glf::DATA_DIRECTORY + "410/image-texture.frag");
std::string const TEXTURE_DIFFUSE(glf::DATA_DIRECTORY + "kueken256-rgba8.dds");
int const SAMPLE_SIZE_WIDTH = 640;
int const SAMPLE_SIZE_HEIGHT = 480;
int const SAMPLE_MAJOR_VERSION = 4;
int const SAMPLE_MINOR_VERSION = 1;

struct vertex
{
vertex
(
glm::vec2 const & Position,
glm::vec2 const & Texcoord
) :
Position(Position),
Texcoord(Texcoord)
{}

glm::vec2 Position;
glm::vec2 Texcoord;
};

GLsizei const VertexCount = 4;
GLsizeiptr const VertexSize = VertexCount * sizeof(glf::vertex_v2fv2f);
glf::vertex_v2fv2f const VertexData[VertexCount] =
{
glf::vertex_v2fv2f(glm::vec2(-1.0f,-1.0f), glm::vec2(0.0f, 1.0f)),
glf::vertex_v2fv2f(glm::vec2( 1.0f,-1.0f), glm::vec2(1.0f, 1.0f)),
glf::vertex_v2fv2f(glm::vec2( 1.0f, 1.0f), glm::vec2(1.0f, 0.0f)),
glf::vertex_v2fv2f(glm::vec2(-1.0f, 1.0f), glm::vec2(0.0f, 0.0f))
};

GLsizei const ElementCount = 6;
GLsizeiptr const ElementSize = ElementCount * sizeof(GLushort);
GLushort const ElementData[ElementCount] =
{
0, 1, 2,
2, 3, 0
};

glf::window Window(glm::ivec2(SAMPLE_SIZE_WIDTH, SAMPLE_SIZE_HEIGHT));
glm::uvec2 ImageSize(0);

namespace buffer
{
enum type
{
VERTEX,
ELEMENT,
MAX
};
}//namespace buffer

GLuint VertexArrayName(0);
GLuint PipelineName(0);
GLuint ProgramName(0);

GLuint BufferName[buffer::MAX] = {0, 0};
GLuint Image2DName(0);
GLuint SamplerName(0);

GLuint UniformMVP(0);
GLuint UniformImageData(0);
GLuint UniformImageSize(0);
}//namespace

bool initProgram()
{
bool Validated = true;

if(Validated)
{
GLuint VertexShaderName = glf::createShader(GL_VERTEX_SHADER, VERTEX_SHADER_SOURCE);
GLuint FragmentShaderName = glf::createShader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER_SOURCE);

ProgramName = glCreateProgram();
glAttachShader(ProgramName, VertexShaderName);
glAttachShader(ProgramName, FragmentShaderName);
glDeleteShader(VertexShaderName);
glDeleteShader(FragmentShaderName);
glLinkProgram(ProgramName);
Validated = glf::checkProgram(ProgramName);
}

if(Validated)
{
UniformMVP = glGetUniformLocation(ProgramName, "MVP");
UniformImageData = glGetUniformLocation(ProgramName, "ImageData");
UniformImageSize = glGetUniformLocation(ProgramName, "ImageSize");
}

return Validated &amp;&amp; glf::checkError("initProgram");
}

bool initArrayBuffer()
{
glGenBuffers(buffer::MAX, BufferName);
glNamedBufferDataEXT(BufferName[buffer::VERTEX], VertexSize, VertexData, GL_STATIC_DRAW);
glNamedBufferDataEXT(BufferName[buffer::ELEMENT], ElementSize, ElementData, GL_STATIC_DRAW);

return glf::checkError("initArrayBuffer");
}

bool initTexture2D()
{
glGenTextures(1, &amp;Image2DName);

glTextureParameteriEXT(Image2DName, GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTextureParameteriEXT(Image2DName, GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1000);
glTextureParameteriEXT(Image2DName, GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
glTextureParameteriEXT(Image2DName, GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
glTextureParameteriEXT(Image2DName, GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
glTextureParameteriEXT(Image2DName, GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
glTextureParameteriEXT(Image2DName, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTextureParameteriEXT(Image2DName, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

gli::texture2D Image = gli::load(TEXTURE_DIFFUSE);
//for(std::size_t Level = 0; Level < Image.levels(); ++Level)
{
glTexImage2D(
GL_TEXTURE_2D,
GLint(0),
GL_RGBA32F,
GLsizei(Image[0].dimensions().x),
GLsizei(Image[0].dimensions().y),
0,
GL_BGR,
GL_UNSIGNED_BYTE,
Image[0].data());
}
ImageSize = glm::uvec2(Image[0].dimensions());

return glf::checkError("initTexture2D");
}

bool initVertexArray()
{
glGenVertexArrays(1, &amp;VertexArrayName);

glVertexArrayVertexAttribOffsetEXT(VertexArrayName , BufferName[buffer::VERTEX], glf::semantic::attr::POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
glVertexArrayVertexAttribOffsetEXT(VertexArrayName , BufferName[buffer::VERTEX], glf::semantic::attr::TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), sizeof(glm::vec2));

glEnableVertexArrayAttribEXT(VertexArrayName, glf::semantic::attr::POSITION);
glEnableVertexArrayAttribEXT(VertexArrayName, glf::semantic::attr::TEXCOORD);

return glf::checkError("initVertexArray");
}

bool begin()
{
bool Validated = true;
Validated = Validated &amp;&amp; glf::checkGLVersion(SAMPLE_MAJOR_VERSION, SAMPLE_MINOR_VERSION);
Validated = Validated &amp;&amp; glf::checkExtension("GL_EXT_direct_state_access");
Validated = Validated &amp;&amp; glf::checkExtension("GL_EXT_shader_image_load_store");

if(Validated)
Validated = initProgram();
if(Validated)
Validated = initArrayBuffer();
if(Validated)
Validated = initTexture2D();
if(Validated)
Validated = initVertexArray();

return Validated &amp;&amp; glf::checkError("begin");
}

bool end()
{
glDeleteBuffers(buffer::MAX, BufferName);
glDeleteProgram(ProgramName);
glDeleteTextures(1, &amp;Image2DName);
glDeleteSamplers(1, &amp;SamplerName);
glDeleteVertexArrays(1, &amp;VertexArrayName);
glDeleteProgramPipelines(1, &amp;PipelineName);

return glf::checkError("end");
}

void display()
{
// Compute the MVP (Model View Projection matrix)
glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 1000.0f);
glm::mat4 ViewTranslate = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -Window.TranlationCurrent.y));
glm::mat4 ViewRotateX = glm::rotate(ViewTranslate, Window.RotationCurrent.y, glm::vec3(1.f, 0.f, 0.f));
glm::mat4 View = glm::rotate(ViewRotateX, Window.RotationCurrent.x, glm::vec3(0.f, 1.f, 0.f));
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 MVP = Projection * View * Model;

glProgramUniformMatrix4fv(ProgramName, UniformMVP, 1, GL_FALSE, &amp;MVP[0][0]);
glProgramUniform1i(ProgramName, UniformImageData, 0);
glProgramUniform2uiv(ProgramName, UniformImageSize, 1, &amp;ImageSize[0]);

glViewport(0, 0, Window.Size.x, Window.Size.y);
glClearBufferfv(GL_COLOR, 0, &amp;glm::vec4(1.0f, 0.5f, 0.0f, 1.0f)[0]);

glUseProgram(ProgramName);

glViewport(0, 0, Window.Size.x, Window.Size.y);

glBindMultiTextureEXT(GL_TEXTURE0, GL_TEXTURE_2D, Image2DName);
glBindImageTextureEXT(0, Image2DName, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);

glBindVertexArray(VertexArrayName);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, BufferName[buffer::ELEMENT]);

glDrawElementsInstancedBaseVertex(GL_TRIANGLES, ElementCount, GL_UNSIGNED_SHORT, NULL, 1, 0);

glf::checkError("display");
glf::swapBuffers();
}

int main(int argc, char* argv[])
{
if(glf::run(
argc, argv,
glm::ivec2(SAMPLE_SIZE_WIDTH, SAMPLE_SIZE_HEIGHT),
SAMPLE_MAJOR_VERSION,
SAMPLE_MINOR_VERSION))
return 0;
return 1;
}




// Fragment shader

#version 410 core
#extension GL_NV_gpu_shader5 : enable // For nVidia only
#extension GL_EXT_shader_image_load_store : enable

// Declare all the semantics
#define ATTR_POSITION 0
#define ATTR_COLOR 3
#define ATTR_TEXCOORD 4
#define FRAG_COLOR 0

layout(size4x32) coherent uniform image2D ImageData;
uniform uvec2 ImageSize;

in vert
{
vec2 Texcoord;
} Vert;

layout(location = FRAG_COLOR, index = 0) out vec4 Color;

void main()
{
vec4 Texel = imageLoad(ImageData, ivec2(Vert.Texcoord * 128));
Color = Texel + vec4(Vert.Texcoord, 1.0, 1.0) * 1.0;
}

// Vertex shader
#version 410 core

// Declare all the semantics
#define ATTR_POSITION 0
#define ATTR_COLOR 3
#define ATTR_TEXCOORD 4
#define FRAG_COLOR 0

uniform mat4 MVP;

layout(location = ATTR_POSITION) in vec2 Position;
layout(location = ATTR_TEXCOORD) in vec2 Texcoord;

out vert
{
vec2 Texcoord;
} Vert;

void main()
{
Vert.Texcoord = Texcoord;
gl_Position = MVP * vec4(Position, 0.0, 1.0);
}


Any idea?
I had a look at Cyril Crassin demos but still I can't find the issue :p

Thanks!

Chris Lux
03-11-2011, 02:15 AM
I am using EXT_shader_image_load_store on nvidia without major issues for the last weeks.

The only thing i can see in your code that i would test is to _not_ bind the same texture to a texture unit at the same time.

Groovounet
03-11-2011, 04:15 AM
Found it!

With glTextureImage2DEXT it would be better.

Never the less, AMD drivers crash, nVidia drivers say nothing (how typical!) and I am using the core profile with forward compatibility so the only think I should get is an OpenGL error!

Chris Lux
03-11-2011, 05:34 AM
Oh, i missed that one... ;)

Groovounet
03-11-2011, 05:52 AM
It makes us 2 but... that wasn't our duty to find it but the duty of the OpenGL implementations :p

By the way:
Are you aware of limitation like:

This is OK:

glTexImage2D(
GL_TEXTURE_2D,
GLint(Level),
GL_RGBA8,
GLsizei(Texture[Level].dimensions().x),
GLsizei(Texture[Level].dimensions().y),
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
Texture[Level].data());

This is NOT:

glTexImage2D(
GL_TEXTURE_2D,
GLint(Level),
GL_RGBA8,
GLsizei(Texture[Level].dimensions().x),
GLsizei(Texture[Level].dimensions().y),
0,
GL_BGRA,
GL_UNSIGNED_BYTE,
Texture[Level].data());

PS: I still have a crash on nVidia at texture creation... weird :p
PS2: Without DSA, no crash but the texture is black :p