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 && 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, &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, &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 && glf::checkGLVersion(SAMPLE_MAJOR_VERSION, SAMPLE_MINOR_VERSION);
Validated = Validated && glf::checkExtension("GL_EXT_direct_state_access");
Validated = Validated && 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 && glf::checkError("begin");
}
bool end()
{
glDeleteBuffers(buffer::MAX, BufferName);
glDeleteProgram(ProgramName);
glDeleteTextures(1, &Image2DName);
glDeleteSamplers(1, &SamplerName);
glDeleteVertexArrays(1, &VertexArrayName);
glDeleteProgramPipelines(1, &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, &MVP[0][0]);
glProgramUniform1i(ProgramName, UniformImageData, 0);
glProgramUniform2uiv(ProgramName, UniformImageSize, 1, &ImageSize[0]);
glViewport(0, 0, Window.Size.x, Window.Size.y);
glClearBufferfv(GL_COLOR, 0, &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
Thanks!