Compute shaders issues

Say I want to generate a 512x512 image inside a compute shader by passing an array of size 512x3, and painting each column in an image accordingly
Example: if array[8] = [0.8, 0.2, 0.3], then the column img[8] in the final image will be of this color.

I relied on this post and the code addressed in this post, but I couldn’t get it to work.

Expectation
image
reault
image
close up
image

main.py

import panda3d.core as p3d
from direct.showbase.ShowBase import ShowBase
from array import array

immutableTextureStore = p3d.ConfigVariableBool("gl-immutable-texture-storage", False)
immutableTextureStore.setValue(True)

base = ShowBase(windowType='offscreen')


_TOTAL_ = 512
floats = []
for i in range(_TOTAL_):
    floats += [i/_TOTAL_, 0, 0]
initial_data = array('f', floats)
buffer = p3d.ShaderBuffer('elements', initial_data.tobytes(), p3d.GeomEnums.UH_static)

img = p3d.Texture()
img.setup_2d_texture(512, 512, p3d.Texture.T_unsigned_byte, p3d.Texture.F_rgba8)

shader = p3d.Shader.load_compute(p3d.Shader.SL_GLSL, "shaders/c_dummy.glsl")
node_p = p3d.NodePath("dummy")
node_p.set_shader(shader)
node_p.set_shader_input("img", img)
node_p.set_shader_input("ElementBuffer", buffer)

sattr = node_p.get_attrib(p3d.ShaderAttrib)
base.graphicsEngine.dispatchCompute((_TOTAL_//16, 1, 1), sattr, base.win.get_gsg())
base.graphicsEngine.extractTextureData(img, base.win.get_gsg())

frame = p3d.PNMImage()
img.store(frame)
frame.write("test.png")

compute_shader.glsl

#version 430

layout (local_size_x = 16, local_size_y = 1) in;

struct Element
{
    vec3 color;
};

layout(std430) buffer ElementBuffer { Element elements[]; };
uniform writeonly image2D img;

float size = 512.;
void main()
{
  ivec2 texelCoords = ivec2(gl_GlobalInvocationID.xy);
  int id = texelCoords.x;

  vec3 c = elements[id].color;
  for (int i=0; i < size; i++)
    imageStore(img, ivec2(id, i), vec4(c, 1));
}

any ideas?

The problem is the oddball alignment rules for vec3. Really, you should avoid using the vec3 type in SSBOs. Either use three individual float variables or switch to vec4.

1 Like

@rdb
What if I want to have an output buffer from the shader?
I extended my input buffer to be 512x512 and I want it to write both to an image and to buffer back to the cpu

How can I access the values in elements_out?

modified shader

#version 430

layout (local_size_x = 16, local_size_y = 16) in;

struct Element
{
    vec4 color;
};

buffer ElementBufferIn { Element elements_in[]; };
buffer ElementBufferOut { Element elements_out[]; };
uniform writeonly image2D img;

float size = pow(512., 2);
void main()
{
  ivec2 texelCoords = ivec2(gl_GlobalInvocationID.xy);
  int id = texelCoords.x * 512 + texelCoords.y;
  vec4 c = elements_in[id].color;
  
  elements_out[id].color = c;
  imageStore(img, texelCoords, c);
}

added this to python

initial_data_out = array('f', list(range(512 * 512 * 4))) # init empty list
buffer_out = p3d.ShaderBuffer('elements_out', initial_data_out.tobytes(), p3d.GeomEnums.UH_static)
node_p.set_shader_input("ElementBufferOut", buffer_out)

It’s not possible to directly download the contents of a ShaderBuffer at the moment.

You should instead write to a buffer texture and you can download that with extract_texture_data.