PDA

View Full Version : Filling texture with glTexStorage2D



Asatnin
04-26-2016, 03:04 PM
Hello, I need to perform some calculations with compute shader. Input data will be sent to it in image2D, so I've written this line in my compute shader:
layout(rg32f, binding = 0) readonly uniform image2D imageIn;
As you can see, each element of image consists of two floating-point numbers. Namely, they are real and imaginary parts of complex number. In C++ code I have structure for it and array with proper complex numbers:


struct complex_number {
float re, im;
}
...
complex_number *h_fft = new complex_number[N * N];
// filling h_fft

Now I need to send that array to imageIn in compute shader. What I do is generating texture first:


glGenTextures(1, &texture_H_t);
glBindTexture(GL_TEXTURE_2D, texture_H_t);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

Then in place of calculation I update texture with array of complex numbers by glTexSubImage2D():


glBindTexture(GL_TEXTURE_2D, texture_H_t);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, N, N, GL_RG, GL_FLOAT, h_fft);

And finally run compute shader:


glBindImageTexture(0, texture_H_t, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RG32F);
glDispatchCompute(...);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT );

However, it seems that imageIn variable in compute shader is filled by zeros. Also I tried using glTexImage2D() instead of glTexSubImage2D() - same result. I think that my problem is writing C++ structure to texture without some extra actions, but I have a little experience with OpenGL.
Could you please help me?

GClements
04-26-2016, 05:21 PM
In C++ code I have structure for it and array with proper complex numbers:

Why not use std::complex<float>? It shouldn't have any effect here, but may be easier to work with (both C99 and C++11 specify that the representation is identical to float[2], with the real component first),



Now I need to send that array to imageIn in compute shader. What I do is generating texture first:

Note that you don't need to set sampling parameters if shaders are only going to be accessing it as an image.



However, it seems that imageIn variable in compute shader is filled by zeros.

Why do you think that?

There's nothing obviously wrong with the code you posted.

What is the shader doing? How is it returning its results? You only mention its inputs, not the computation or its outputs.

Asatnin
04-27-2016, 05:17 AM
Why not use std::complex<float>?
I thought about it much later and realized not to change existing code. A matter of taste, though.


What is the shader doing? How is it returning its results? You only mention its inputs, not the computation or its outputs.
Debugging compute shader is a bit hard, so when something went wrong I chose to check correctness of input at first. Therefore, I created this vertex shader:


#version 430

layout(location = 0) in vec3 vertex_position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 img_coord;

//layout(rg32f, binding = 0) readonly uniform image2D imageIn;
layout(binding = 0) uniform sampler2D imageIn;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main() {
//vec2 height = imageLoad(imageIn, ivec2(img_coord.x, img_coord.y)).xy;
vec2 height = texture(imageIn, img_coord).xy;
vec3 disp = vec3(0.0, 0.0, 0.0);
if (height.x != 0.0 || height.y != 0.0) {
disp = vec3(0.0, 5.0, 0.0);
}

gl_Position = projection * view * model * vec4(vertex_position + disp, 1.0);
}

As you can see, I tried image2D and sampler2D types for input image (img_coord had integer coordinates for image2D and floating-point coordinates in range [0, 1] for sampler2D, of course). As a result, if-statement never executes and disp is always vec3(0.0, 0.0, 0.0): imageIn is always filled by zeros. Also, when using image2D I bind texture like this:


glBindImageTexture(0, texture_H_t, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32F);

And when using sampler2D I bind texture like this:


glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_H_t);

Asatnin
04-27-2016, 08:31 AM
Now, I've found solution. I tried using glGetError() function: it said GL_INVALID_VALUE after glUseProgram(comp_program) - the program with compute shader. I have program ID as a class variable:


prviate:
GLuint comp_program;

But in constructor I redefined it as:


GLuint comp_program = create_comp_program_from_file(...);

So, in class variable comp_program was rubbish.

GClements, thanks for your help! It was completely my error.