Opengl ES Buffer: Compute Shader -> Vertex Shader

#1

Thanks for your interest!

I’ve spent the longest time working on this problem, but I now suspect the heavens.

I am trying to write to a buffer with a compute shader, and read and write the new values to the display with a vertex and fragment shader.

As simple as it gets right? (Ha… Maybe for you… :frowning:)

:slight_smile:

Right now I’m working with opengl es 3.1 using java and Android 9.0. Though, I did get the pipeline working on my pc (windows, c++) using textures instead of buffers, so I replicated the process via opengl es using textures, but the compute shader was not showing any signs of activity, even after the same dispatch call; and no errors are to be found.

I am now trying buffers, but the results are the same, “no activity” symptoms.

So what changes can I make to this code to by pass the almighty? I am puzzled with solutions I find that do not work, and do not make any sense to me.

CODE

Compute Shader

#version 310 es

layout (local_size_x = 1) in;
uniform uint maxX;

layout (std430, binding = 1) buffer outPixels{
	vec4 pixel[];
} pixels;


void main(){
	pixels.pixel[gl_GlobalInvocationID.x+gl_GlobalInvocationID.y*maxX] = vec4(0.1f);
}

Vertex Shader

#version 310 es

layout (location = 0) in vec3 pos;
layout (location = 1) in vec4 colorV;
out vec4 colorF;

void main(){
	gl_Position = vec4(pos, 1.0);
	colorF = colorV;
}

Fragment Shader

#version 310 es

precision highp float;
in vec4 colorF;
out vec4 color;

void main() {
	color = colorF;
}

Shader Configuration Code

// Pixel Buffer
int[] cache = new int[1];
GLES31.glGenBuffers(1, cache, 0);
int pixels = cache[0];
GLES31.glBufferData(pixels, width*height*4*Float.BYTES, null, GLES31.GL_STREAM_COPY);

// COMPUTE SHADER
shaders.UseCompute(0);
GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, pixels);
GLES31.glBindBufferBase(GLES31.GL_SHADER_STORAGE_BUFFER, 1, pixels);
GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, 0);

IntBuffer buffer = IntBuffer.allocate(3);
GLES31.glGetIntegerv(GLES31.GL_MAX_COMPUTE_WORK_GROUP_COUNT, buffer);
GLES31.glUniform1ui(GLES31.glGetUniformLocation(shaders.computeShaders.get(0), "maxX"), buffer.get(0));

// VERTEX:FRAGMENT SHADER
shaders.UseVertFrag(0);

vaos = new ArrayList<Integer>();
int[] vao = new int[1];
GLES31.glGenVertexArrays(1, vao, 0);
GLES31.glBindVertexArray(vao[0]);
vaos.add(vao[0]);

// Quad Coordinates
float[] vertices = {
        -1.0f,-1.0f, 0.0f,
        -1.0f, 1.0f, 0.0f,
         1.0f, 1.0f, 0.0f,
        -1.0f,-1.0f, 0.0f,
         1.0f,-1.0f, 0.0f,
         1.0f, 1.0f, 0.0f
};
FloatBuffer vertexBuffer = FloatBuffer.allocate(vertices.length);
vertexBuffer.put(vertices, 0, vertices.length);
vertexBuffer.position(0);

// kiiDisplay.vs :: INPUTS
int[] vbo = new int[1];
GLES31.glGenBuffers(1, vbo, 0);
GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, vbo[0]);
GLES31.glBufferData(GLES31.GL_ARRAY_BUFFER, vertices.length*Float.BYTES, vertexBuffer, GLES31.GL_STATIC_DRAW);
GLES31.glEnableVertexAttribArray(0);
GLES31.glVertexAttribPointer(0, 3, GLES31.GL_FLOAT, false, Float.BYTES*3, 0);

GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, pixels);
GLES31.glEnableVertexAttribArray(1);
GLES31.glVertexAttribPointer(1, 1, GLES31.GL_FLOAT, false, Float.BYTES, 0);

GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, 0);


GLES31.glClearColor(0.7f,0.6f,0.7f,1.0f);
GLES31.glDisable(GLES31.GL_DEPTH_TEST);

GLES31.glBindVertexArray(0);

Draw Loop

GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT);

shaders.UseCompute(0);
GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, pixels);
GLES31.glDispatchCompute(100, 100, 1);
GLES31.glMemoryBarrier(GLES31.GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, 0);

shaders.UseVertFrag(0);
GLES31.glBindVertexArray(vaos.get(0));
GLES31.glDrawArrays(GLES31.GL_TRIANGLES, 0, 6);
GLES31.glBindVertexArray(0);

No errors are generated.
Fragment shader and vertex shaders have been tested to work, it’s the compute shaders that have not yet worked with Open GL ES 310.

Thanks for making it this far… This is it.

#2

The first parameter to glBufferData is the target to which you have bound the buffer object that you want to allocate, not the buffer object itself. So you need to bind pixels to a target, then call glBufferData on that target.