Kode / Kinc

Modern low level game library and hardware abstraction.
http://kinc.tech
zlib License
511 stars 121 forks source link

Can't bind more than one image in compute shaders. #851

Closed e2002e closed 7 months ago

e2002e commented 7 months ago

When using compute API, we can only read / write to one image, no matter what we bind before execution. I have modified the ComputeShader sampler to have two images in test.comp.glsl, we ignore the first one, write directly to the texture2, and nothing is displayed. If we bind texture instead of texture2 to the fragment shader sampler, we got the image despite compute shader supposedly writing on texture2.

You can find the modified sample here: https://github.com/e2002e/ComputeShader

Lattest Kinc / Kha Lattest Nvidia drivers Debian 12

RobDangerous commented 7 months ago

Please use the issue template so I get the necessary info. What revision of Kinc are you on? Is this OpenGL?

e2002e commented 7 months ago

Hi, Kha commit 206d1ee3 Kinc commit b4d0aed0

I pinpointed the issue to getTextureUnit(). It's possible to read / write to texture2 in the example only if the first set texture units is texture2. Subsequent calls seem to ignore bindings.

RobDangerous commented 7 months ago

ok, you already answered 50% of my questions, good progress.

e2002e commented 7 months ago

Hello, I looked into the code and I see that the getTextureUnit() has the job of allocation the computeTextureUnits, it gives these a binding point. What I can tell from further tests is that all compute textures seem to share the same binding point: As I said, the only image that can be written / read is the first that we allocate, and I also noted that even when writing to another image in the compute shader, the operation will occur on the first allocated one anyway.

RobDangerous commented 7 months ago

But when will you tell me what graphics backend you are using so I can check what you are talking about?

e2002e commented 7 months ago

Open GL !

e2002e commented 7 months ago

Hello, I have checked out Kha and Kinc to main and pulled the lattest changes. There are compilations errors:

`../../../Kha/Backends/Kinc-hxcpp/main.cpp: In function ‘void {anonymous}::mix(kinc_a2_buffer_t*, int, void*)’:
../../../Kha/Backends/Kinc-hxcpp/main.cpp:229:74: error: ‘kinc_a2_buffer_t’ {aka ‘struct kinc_a2_buffer’} has no member named ‘format’
  229 |                 ::kha::audio2::Audio_obj::_callCallback(samples, buffer->format.samples_per_second);
      |                                                                          ^~~~~~
../../../Kha/Backends/Kinc-hxcpp/main.cpp:239:44: error: ‘kinc_a2_buffer_t’ {aka ‘struct kinc_a2_buffer’} has no member named ‘data’
  239 |                         *(float *)&buffer->data[buffer->write_location] = value;
      |                                            ^~~~
../../../Kha/Backends/Kinc-hxcpp/main.cpp: In function ‘void kha_kinc_init_audio()’:
../../../Kha/Backends/Kinc-hxcpp/main.cpp:343:30: error: invalid conversion from ‘void (*)(kinc_a2_buffer_t*, int, void*)’ {aka ‘void (*)(kinc_a2_buffer*, int, void*)’} to ‘void (*)(kinc_a2_buffer_t*, uint32_t, void*)’ {aka ‘void (*)(kinc_a2_buffer*, unsigned int, void*)’} [-fpermissive]
  343 |         kinc_a2_set_callback(mix, nullptr);
/Kha/Backends/Kinc-hxcpp/main.cpp:345:54: error: invalid conversion from ‘uint32_t (*)()’ {aka ‘unsigned int (*)()’} to ‘int’ [-fpermissive]
  345 |         ::kha::audio2::Audio_obj::samplesPerSecond = kinc_a2_samples_per_second;
RobDangerous commented 7 months ago

I know, I'm currently merging and fixing up a feature-branch. Check the test status before pulling and especially before reporting, please - when it shows a red x, I already know about it. Also please don't add unrelated things into a GitHub issue. grafik

e2002e commented 7 months ago

Ok, thanks for reminding.

e2002e commented 7 months ago

Hi rob, I've added some printf statements to the kinc_g4_compute_shader_get_texture_unit() function in Kha/Kinc/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/compute.c.h

This looks like:

    int index = compute_findTexture(shader, name);
    fprintf(stderr, "index=%d\n", index);
    if (index < 0) {
    int location = glGetUniformLocation(shader->impl._programid, name);
    glCheckErrors();
    fprintf(stderr, "location=%d\n", location);
    index = shader->impl.textureCount;
    shader->impl.textureValues[index] = location;
    strcpy(shader->impl.textures[index], name);
    ++shader->impl.textureCount;
    fprintf(stderr, "count=%d\n", shader->impl.textureCount);
}

And the output seems to reveal a bug:

Starting Kinc
Using OpenGL version 4.6 (forward-compatible).
index=-1
location=-1
count=1
index=-1
location=1
count=2

UPDATE: Actually I thought there was an issue with the uniform location but it turns out the shader optimizes out the unused texture. The issue's still the same though, the compute texture unit that we don't assign first can be writen / read to/from.

RobDangerous commented 7 months ago

Don't worry, I don't need help debugging this. I'll get to it when I get to it.

RobDangerous commented 7 months ago

Reminds me, if you want to come back to the Discord, feel free to - I opened up dedicated beginner channels for situations like this.