4 ms·
Can you elaborate more on this? It seems interesting > if you are using gl.enable(gl.BLEND) in your core render loop, you have basically already failed.
by 29athrowaway 3y ago
Can you elaborate more on this? It seems interesting
> if you are using gl.enable(gl.BLEND) in your core render loop, you have basically already failed.
- tim1994 3y agoI'd also be interested in details on this but I assume the gl.enable() API changes fundamental things about the rendering pipeline. It allows enabling things like depth testing and stencil (both involve an extra buffer) and face culling (additional tests after vertex shader). For blending in particular I think it requires the fragment shader to first read the previous value from the frame buffer. Changes this stuff is probably not a trivial operation and requires a lot of communication with the GPU which is slow (just a guess). If you want to change blending for each draw call you can change the blending function or just return suitable alpha values from the fragment shader.
- TazeTSchnitzel 3y ago> Changes this stuff is probably not a trivial operation and requires a lot of communication with the GPU which is slow (just a guess). The GPU underneath looks a lot more like Vulkan than it does like OpenGL. Changing state should, in general, not require communicating with the GPU at all, that happens once you draw stuff (or do other operations like compiling shaders or creating textures).
- flohofwoe 3y agoYeah, but the problem specifically with GL is that it is almost unpredictable what actually happens at 'draw time', because small GL state changes can be amplified into big GPU state changs.
- TazeTSchnitzel 3y agoYeah, that's definitely an issue. Vulkan has some of the same issues, they're just moved to the pipeline creation stage.
- TazeTSchnitzel 3y agoAs Jasper said, you write a library to manage GL state for you, rather than calling GL functions directly to manage state (like glEnable and glDisable, among countless others). The risk is simply that you will forget to change things back and one drawing operation will accidentally affect the next.
- flohofwoe 3y agoOne reason is that small innocent changes like this can cause a large wave of dependent changes inside the GL implementation, shaders may be patched or recompiled, internal 'state group objects' discarded and recreated, and those expensive actions might happen at a random point further down in another GL call. Also those details differ between GPU vendor drivers, and sometimes even driver versions. This is what makes GL extremely unpredictable when it comes to profiling the CPU overhead, and why modern 3D APIs prefer bundling state into immuntable state-group-objects. For other things, specifically WebGL may need to run expensive input validation which might also trigger at more or less random places. Also: it's very easy to forget one tiny state change out of dozens, which then mess up rendering in more or less subtle ways, not just for the rest of the frame, but the rest of the application lifetime.
- Jasper_ 3y agoBasically, if you have one piece of codebase call gl.enable(gl.BLEND), then either that needs to reset it at the end with gl.disable(gl.BLEND) and you have some vague ambiguous default state that everything enters and leaves. If you don't, then either your code up ahead needs to unset any possible state added while outside and call gl.disable(gl.BLEND) before it renders, or it's dependent on state set from around it. That latter issue is a real problem, because it makes the frame a lot harder to refactor. One of the biggest stumbling blocks for any new graphics programmer that started on OpenGL is implementing something like a Z-prepass or a shadow map, where you have the same object drawing to two passes, because the GL state machine makes it very easy to accidentally depend on some hidden piece of state you didn't know you were using. The right answer is to have a state tracker that knows the current state, and some combination of object/pass/material know the state intended to switch to. And gl.BLEND is the easy case. Things like VAOs and FBOs are dangerous to have bound latently, because of GL's brutal bind-to-modify API design. Bind-to-modify was optionally dropped when EXT_direct_state_access was added, but that never made its way to GLES/WebGL, unfortunately.