🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

[OpenGL issue] First attempt at a compute shader appears to refuse to write any output

Started by
10 comments, last by taby 2 years, 8 months ago

Hello everyone,

I have a simple game prototype that uses OpenGL for rendering. I have been wanting to implement a postprocessing step as a compute shader, so I wrote a simple shader that writes pure white to every pixel in the image just as a test.
The problem I'm having is that the shader appears to do absolutely nothing, despite confirming with RenderDoc that it does execute, and that the image is bound correctly.

Compute shader source
CPU-side rendering code. When this snippet completes, the default framebuffer should be ready for presentation.

To breakdown the CPU-side code: render::main_scene() does the main geometry pass and renders into core_rt, an SRGBA/MSAA rendertarget. We blit this to ping_rt, an RGBA8/non-MSAA rendertarget, and the color attachment of this framebuffer is bound to the image sampler.
The compute shader is then dispatched with a workgroup count hardcoded to work with 1920x1080, just for now. glMemoryBarrier() is called so that the compute shader's work is visible when we do the remaining blits.

When it's all said and done, the final image is no different than if I were to comment out the call to glDispatchCompute(). Also, I have a RenderDoc capture of a frame in case that would help anyone help me.
One final note: I have tried enabling the GL debug context, but the only non-notification messages it gives me are performance warnings about vertex shaders being recompiled, no usage errors are generated.

I have been wrestling with this issue for days now, and across multiple forums, so please gamedev.net, you are my only hope,
-Nick

None

Advertisement

Nickmav1337 said:
The compute shader is then dispatched with a workgroup count hardcoded to work with 1920x1080, just for now. glMemoryBarrier() is called so that the compute shader's work is visible when we do the remaining blits.

I can't remember about OpenGL, but in Vulkan you would need an execution barrier as well before the memory barrier.
So maybe your CS starts work only after the blitting has already happened and you can't see results because of that. A bit unlikely, though - you should see at least some flickering white spots, if so.

OpenGL Super Bible book has a very good chapter on CS. Probably no example working on the framebuffer, but very good at explaining parallel programming building blocks.

@JoeJ I can't find any results when I try to google for OpenGL execution barrier. I know that I should pick up the OpenGL superbible but I just don't have a copy yet.

I have also tried really hacky crap like inserting a sleep(1000) after the memory barrier. If my problem was synchronization, surely that would reveal it.

One thing I am going to try after work is creating a texture view (a thing I only learned about yesterday) into the core_rt color attachment, and then binding that to the image sampler. This way I should be able to use the SRGB image in the compute shader directly. If nothing else that will get rid of the superfluous blits that are bit-crushing my render lol.

None

Hey, sorry for the late reply!

https://github.com/sjhalayka/qjs_compute_shader

This code shows how to use the compute shader. Check out the calls to init_all() and compute() functions in main.cpp. It should let you know what you're not doing correctly. Man, OpenGL is finicky and complicated. ?

@taby Thank you for that example. It at least confirmed for me that only a gl::MemoryBarrier is required; there's no execution barrier, but I still don't see steps that my program is missing.

None

Yeah, sorry for my bad guess about barriers.

I found this quote: Compute shaders can only access images or buffers. The default framebuffer is neither; it is a special object, and you cannot attach its images to anything.

So CS can't access frambuffer directly, and your plan to use a texture instead should work then.

@JoeJ The thing is, that's already what I was doing. I was attaching the GL name of the color attachment of the framebuffer (not the default framebuffer, one I've manually created), which is itself a texture, unless I'm misunderstanding something?

None

Ha ok, i see. But now i guess the problem maybe is related to those reamebuffer→texture→framebuffer transitions.
Unfortunately i can't help. I'm experienced with compute shaders, but anything related to gfx pipeline remains constant mystery and pain. :D
Maybe some tutorial on deferred shading can help…

Ok everyone I was able to solve this problem, though I don't know exactly how what I did fixes the issue.

Creating a texture view into the framebuffer's color attachment
Binding this new texture view to the image sampler of the compute shader

Instead of creating the postfx framebuffer's color attachment with glTexImage2D(), glTexStorage2D() is used instead so that a texture view (ping_linear_view) can be created into the texture. This is important because it's the only way to use an SRGB image in a compute shader. See https://www.khronos.org/opengl/wiki/Texture_Storage#Texture_views​ for more details, but basically I am able to “cast” a gl::SRGB8_ALPHA8 image into a gl::RGBA8 image for the purposes of compute shader reads/writes.

So there are two differences that I can see could have fixed the issue:

  1. The image the compute shader is manipulating is now allocated with immutable storage instead of mutable storage
  2. We aren't doing a bunch of blits back-and-forth before dispatching the compute shader

Now, the example that @taby shared shows a compute shader that manipulates an image allocated with mutable storage, so I'm leaning towards the second difference as being what fixed things, which is also what @joej hypothesized.

That's all I have to say about this. If anyone wants to add any insight or ideas that would be great, but this issue can be considered solved.

None

@Nickmav1337 I just realized that the old blits were happening after the shader not before, but same idea.

None

This topic is closed to new replies.

Advertisement