Skip to content

Commit 2e53c08

Browse files
authoredNov 6, 2024··
Merge pull request #38 from FireflyInTheDusk/patch-2
Update My Screen is Black article
2 parents e21c014 + d0102f1 commit 2e53c08

File tree

1 file changed

+69
-71
lines changed
  • blog/2024/2024-11-01-my-screen-is-black

1 file changed

+69
-71
lines changed
 

‎blog/2024/2024-11-01-my-screen-is-black/index.md

+69-71
Original file line numberDiff line numberDiff line change
@@ -12,156 +12,154 @@ image: 'https://raw.githubusercontent.com/graphicsprogramming/blog/main/blog/202
1212

1313
<!-- truncate -->
1414

15-
Those were my findings over the months and years of exposing myself to OpenGL. I hope it helps anyone.
15+
These are my findings over the months and years of exposing myself to OpenGL. I hope it helps someone.
1616

17-
### First Things To Do
17+
The OpenGL specification is mentioned several times throughout the article, it can be found [here](https://registry.khronos.org/OpenGL/specs/gl/glspec46.core.pdf).
1818

19-
Hook up [RenderDoc](https://renderdoc.org). If you have not read its getting-started, read it before anything else.
20-
There is also a plugin available "Where is my drawcall" hook it up by following the instructions on RenderDoc's site.
19+
### First things to do
2120

22-
Setup `glDebugMessageCallback` see [here](https://deccer.github.io/OpenGL-Getting-Started/02-debugging/02-debug-callback/) for example code.
21+
Install [RenderDoc](https://renderdoc.org). If you have not read its getting-started, read it before anything else.
22+
There is also a plugin called [Where is my Draw?](https://github.com/baldurk/renderdoc-contrib/blob/main/baldurk/whereismydraw/README.md) — install it by following the instructions [on the official repo](https://github.com/baldurk/renderdoc-contrib/tree/main).
2323

24-
If you use `glGetError` with or without macros like `GLCALL` or `GLCHECK` or rolled your own, get rid of it. `glDebugMessageCallback` will replace those. There is a high chance that you used it incorrectly anyway because you copy pasted it from some questionable source.
24+
Set up `glDebugMessageCallback`. See [here](https://deccer.github.io/OpenGL-Getting-Started/02-debugging/02-debug-callback/) for example code.
2525

26-
Make sure you check that shader compilation *and* linking was successful. See `glGetShaderiv` & `glGetProgramiv` on compile and link status.
26+
If you use `glGetError` with or without macros like `GLCALL` or `GLCHECK`, or you rolled your own error checking functions, get rid of them. `glDebugMessageCallback` will replace them, while avoiding any subtle bugs that may have been caused by error checking copy-paste.
2727

28-
### You are on a Mac
28+
Always check that both shader compilation *and* linking were successful. Search for `glGetShaderiv` and `glGetProgramiv` for more on compile and link status.
2929

30-
Please port your engine to `metal` or `webgpu` at least, seriously. There is no support for `KHR_debug` and you cannot use anything > gl 4.1. That is enough reason
30+
### If you are on a Mac
3131

32-
You are getting `UNSUPPORTED (log once): POSSIBLE ISSUE: unit 0 GLD_TEXTURE_INDEX_2D is unloadable and bound to sampler type (Float) - using zero texture because texture unloadable`. You need to call glGenerateMipmap(GL_TEXTURE_2D) after glTexImage2D() or set max level to 0 if you dont need/want mips.
32+
Please port your application to Metal or WebGPU at least, seriously. There is no support for `KHR_debug` and you cannot use anything newer than OpenGL 4.1. That is enough reason to not want to use OpenGL on a Mac. If you insist on using a Mac, stay with OpenGL 3.3.
3333

34-
If you insist on using Mac, stay with OpenGL 3.3.
34+
You are getting `UNSUPPORTED (log once): POSSIBLE ISSUE: unit 0 GLD_TEXTURE_INDEX_2D is unloadable and bound to sampler type (Float) - using zero texture because texture unloadable`. You need to call `glGenerateMipmap(GL_TEXTURE_2D)` after `glTexImage2D()` or set max level to 0 if you don't need or want mips.
3535

3636
### RenderDoc is crashing when trying to run your application
3737

38-
This is most likely **not** RenderDoc's fault, but yours. Something in your code is fishy and RenderDoc doesnt like it. Use a debugger/code-sanitizer to figure out
39-
what is going on in your application. Most likely some problem around memory allocation/freeing/UB related thing.
38+
There is a high chance something in the application's code is fishy. Use a debugger or code-sanitizer to figure out what is going on in your application. Most likely some problem with memory allocation, freeing or some kind of UB.
4039

41-
Another reason why RenderDoc is crashing is that it doesnt like certain extensions you might be using in your code. RenderDoc used to tell you usually and not just
42-
crash, but that behaviour has changed since 1.36 or so. I don't know why. I have not bothered asking baldur yet. But what you can do is check your code for
43-
things involving bindless textures, and bindless buffers. Stuff like `glMakeTextureResidentARB`, `glProgramUniform...64NV`, `glGetTextureHandleARB`. RenderDoc also does
44-
not support legacy OpenGL. Make sure you arent using those either `glVertexXy`, `glNormalXy` etc. To debug old school stuff, use `apitrace` or nVidia's NSight Graphics.
45-
Older versions of `gEDebugger` or `CodeXL` might work too.
40+
Another reason why RenderDoc is crashing is that it doesn't like certain extensions you might be using in your code. RenderDoc used to tell you and not just
41+
crash, but that behaviour has changed since 1.36 or so. But what you can do is check your code for things involving bindless textures, and bindless buffers. Stuff like `glMakeTextureResidentARB`, `glProgramUniform...64NV`, `glGetTextureHandleARB`.
4642

47-
### You use GLAD but it is giving you a hard time about symbols not found and multiple definitions or the likes
43+
RenderDoc also does not support legacy OpenGL. Make sure you aren't using `glVertexXy`, `glNormalXy` etc. To debug old school stuff, use apitrace or nVidia's NSight Graphics.
44+
Older versions of gEDebugger or CodeXL might work too.
4845

49-
It is most likely that the headers you are using are just outdated. Regenerate the header on dav1d's site. Or check your build system that it is
50-
pulling a recent version of glad.
46+
### You use GLAD but it is giving you a hard time about symbols not being found, about multiple definitions, or other similar errors
5147

52-
### Debug Callback Says
48+
It is most likely that the headers you are using are just outdated. Regenerate the header on [dav1d's site](https://glad.dav1d.de/), or check that your build system is pulling a recent version of glad.
5349

54-
- `GL_INVALID_OPERATION error generated. Array object is not active.`:
55-
You didn't bind a VAO. Core Context OpenGL requires a VAO bound at all times. Bind one.
50+
### Debug callback says
5651

57-
### Shader Compiler Log Says
52+
- `GL_INVALID_OPERATION error generated. Array object is not active.`
53+
54+
You didn't bind a VAO. Core Context OpenGL requires a VAO bound at all times.
55+
56+
### Shader compiler log says
5857

5958
- `function "main" is already defined`
60-
You probably compile your fragment shader as vertex shader or other way around
59+
60+
You probably compile your fragment shader as vertex shader or the other way around.
6161

6262
### You are unable to figure out if an extension is supported
6363

64-
`GL_NV_conservative_raster` for example despite calling `glGetString(GL_EXTENSIONS)` and all that.
65-
You either need to query extensions with a forward compatible context or you switch to query `GL_NUM_EXTENSIONS` first and
66-
then iterate over all of them with `glGetStringi` and then check if the extension is part of that list. The latter requires a core OpenGL context.
64+
- `GL_NV_conservative_raster` for example, despite calling `glGetString(GL_EXTENSIONS)`
65+
66+
You either need to query extensions with a forward compatible context or switch to query `GL_NUM_EXTENSIONS` first and then iterate over all of them with `glGetStringi` and then check if the extension is part of that list. The latter requires a core OpenGL context.
6767

68-
### Exception when calling glDrawElements - aka "0xC0000005"
68+
### Exception when calling glDrawElements a.k.a. "0xC0000005"
6969

70-
You most likely have no indexbuffer is bound. Or it is not associated to/with the current VAO.
70+
You most likely have no index buffer bound, or it is not associated with the current VAO.
7171

72-
### Exception when calling glDrawArrays / or worse the driver is crashing
72+
### Exception when calling glDrawArrays or worse, the driver is crashing
7373

74-
You probably want to draw more primitives than you have in your vertexbuffer, check arguments of your `glDrawArrays` call.
75-
Potentially you might not have set the vertex count variable and that contains an ununitialized value because you used c/c++ and are a doofus.
74+
- You're probably drawing more primitives than you have in your vertex buffer, check the arguments of your `glDrawArrays` call.
75+
- You might have not set the vertex count variable and as a result it contains an uninitialized value, assuming you used a language like C or C++.
7676

7777
### Textures/Triangles are black
7878

7979
Did you forget to bind the texture in question?
8080

81-
When you are not using `glXXXTextureStorage` but not good and old `glTexImageXX` make sure the texture is complete.
82-
**Check** with **OpenGL Specification** what completeness entails.
81+
If you are using `glTexImageXX`, make sure the texture is complete. Check with the OpenGL Specification what completeness entails.
8382

84-
If it was not complete it should have told you about it in the debug callback. **Shame on you** if you still have not set it up.
83+
If it was not complete it should have told you about it in the debug callback. **Shame on you** if you still have not set it up :)
8584

8685
You might be using sampler objects. Make sure you bind one.
8786

88-
You might be sampling from a corner of your texture where its actually black, Check your UVs.
87+
You might be sampling from a corner of your texture where it's actually black, check your UVs.
8988

90-
Another very likely reason is you didn't understand VAOs and copy pastaed it from learnopengl and added your own twist to it.
91-
Check that your VAO setup is correct. Make sure stride, offset is set correctly. And if you are using multiple vertexbuffers for all your attributes, make sure
89+
Check that your VAO setup is correct. Make sure stride, offset are set correctly. And if you are using multiple vertex buffers for all your attributes, make sure
9290
they are bound properly.
9391

9492
You tried to use vertex colors, but you didn't setup the VAO properly.
93+
9594
Vertex colors might just be black. If it wasn't intentional, check the contents of your VBO.
9695

9796
### Screen is Black
9897

9998
- Check if your screen is on/connected properly
100-
- Camera (projection/view matrices are fucked) is not looking at the scene in question
101-
- No texture is sampled due to missing or wrong uvs => default value is 0 aka black (depends on the driver)
99+
- Make sure your clear color is not pure black
100+
- Camera is not looking at the scene in question (projection and/or view matrices are wrong)
101+
- No texture is sampled due to missing or wrong uvs => default value is most likely 0, meaning black (the value depends on the driver)
102102
- No shader bound (especially fragment shader)
103-
- Fragment shader doesnt write anything to its output
104-
- No viewport is set/is too small
105-
- you might be rendering to a framebuffer, but not blitting that framebuffer to the default one or using it in a way to see its contents.
106-
- Let clearcolor be something else than pure black
107-
- are you rendering to multiple render targets?
108-
- if yes, check that you called the right `gl(Named)DrawBuffers`. Check that you didnt call `gl(Named)DrawBuffer` once per render target.
109-
- are you playing with depth-pre-pass-isms?
110-
- make sure the gl state between passes is the same, face winding, cullmode, etc. See Appending A.3 in the gl spec for more clues about invariance.
111-
- check winding order and cullmode, you might be looking at the wrong side of your faces
112-
- you check renderdoc and wonder why the vertex list contains the same (perhaps even first element) only, for all vertices. Make sure your `glDrawElements(..., ..., GL_UNSIGNED_INT, ...)` or whatever datatype your indexbuffer consists of matches that parameter
113-
- Perhaps you are trying to read an int/uint or long/ulong value from your vertex attribute. Get some glasses and double check that you called the right `glVertexAttrib`**`X`**`Pointer` when setting up your VAO.
103+
- Fragment shader doesn't write anything to its output
104+
- No viewport is set, or it is too small
105+
- You might be rendering to a framebuffer, but not using it in a way that lets you see its contents like blitting it to the default framebuffer.
106+
- Are you rendering to multiple render targets?
107+
108+
If you are, check that you called the right `gl(Named)DrawBuffers`. Check that you didn't call `gl(Named)DrawBuffer`, once per render target.
109+
- Are you playing with depth-pre-pass-isms?
110+
111+
Make sure the gl state between passes is the same, face winding, cull mode, etc. See Appendix A.3 in the gl spec for more clues about invariance.
112+
- Check winding order and cull mode, you might be looking at the wrong side of your faces
113+
- You checked RenderDoc and wonder why the vertex list contains the same (perhaps even first element) only, for all vertices. Make sure your `glDrawElements(..., ..., GL_UNSIGNED_INT, ...)` or whatever datatype your indexbuffer consists of matches that parameter.
114+
- Perhaps you are trying to read an int/uint or long/ulong value from your vertex attribute. Double check that you called the right `glVertexAttrib`**`X`**`Pointer` when setting up your VAO.
114115

115116
All these things can be checked with a graphics debugger of your choice.
116117

117118
### Textures look funny, like a garbled version of the actual image
118119

119-
Make sure your internalformat and actual pixel format match.
120-
You probably used stb_image to load, but used 0 as the last parameter, and pixel data has 3 components, instead of the 4 (GL_RGBA) you told OpenGL about.
121-
Request 4 channels from stb_image. There is almost never a reason to request 3 or less channels for color bearing pixelmaps.
120+
Make sure your internal format and actual pixel format match.
121+
You probably used stb_image to load, but used 0 as the last parameter, and pixel data has 3 components, instead of the 4 (`GL_RGBA`) you told OpenGL about.
122+
Request 4 channels from stb_image. There is almost never a reason to request 3 or fewer channels for textures with color data.
122123

123124
### Textures look like one color component is more prominent than others
124125

125-
Happens when you are used to DirectXisms
126-
127126
- Colors are more shifted towards blue
128127

129-
- You probably messed up the format and asked for GL_BRG.. of sorts => make sure they match
128+
- Original pixel data was probably in `RGB` but you asked for `GL_BRG` or some other non-matching format => make sure they match
130129

131130
- Colors are more shifted towards red
132131

133-
- Original pixeldata was probably in BGR... but you asked for GL_RGB... of sorts => make sure they match
132+
- Original pixel data was probably in `BGR` but you asked for `GL_RGB` or some other non-matching format => make sure they match
134133

135134
### Textures seem to work, but the mesh also appears to be shaded weirdly as if its in some black fog
136135

137136
Did you generate mipmaps?
138137

139138
### Render artifacts like small missing tiles on a floor
140139

141-
VERY likely an alignment issue. **Check** the alignment rules in the **GLSL Specification**.
140+
Very likely an alignment issue. Check the alignment rules in the GLSL Specification.
142141

143-
Other reasons could be that you are binding multiple textures to the same slot/unit. Check your `glBindTextureUnit` calls and if you are stuck in non DSA land,
142+
Other reasons could be that you are binding multiple textures to the same slot/unit. Check your `glBindTextureUnit` calls and if you are stuck in non-DSA land,
144143
check your `glBindTexture/glActiveTexture/glUniform1f` combinations.
145144

146-
Another classic is not using a flat index when indexing into material buffers or texture arrays.
145+
Another classic reason is not using a flat index when indexing into material buffers or texture arrays.
147146

148147
```glsl
149148
layout(location = n) flat int in v_material_index;
150149
```
151150

152151
Synchronization issues could be yet another reason. Perhaps a missing `glMemoryBarrier` at the right spot.
153152

154-
### Depth buffer not cleared
153+
### Depth buffer not cleared despite calling `glClear(GL_DEPTH_BUFFER_BIT)`
155154

156-
- Despite calling `glClear(GL_DEPTH_BUFFER_BIT)` => check if `glDepthMask` was set to `GL_FALSE`. When you use FBOs migrate to glClearNamedFramebuffer() if you havent already (still requires glDepthMask set properly)
155+
Check if `glDepthMask` was set to `GL_FALSE`. When using FBOs, use `glClearNamedFramebuffer()` (it still requires `glDepthMask` to be set properly)
157156

158157
### Weird "Z-Fighting"
159158

160-
- check your depth buffer, near and far planes... try near 0.1f and 512/1024 as farplane
161-
- your depth buffer might be too small and is set to D16 only, set it to something D24 or D32
162-
- you use SDL2 and on your platform the default might be set to D16, find the SDL2_GL_Set_Attribute which sets the depth bits for the default fbo
159+
- Check your depth buffer, near, and far planes. Try near `0.1f` and `512/1024` as far plane.
160+
- Your depth buffer might be too small and is set to `D16` only, set it to something `D24` or `D32`.
161+
- You use SDL2 and on your platform the default might be set to `D16`, find the `SDL2_GL_Set_Attribute` which sets the depth bits for the default FBO.
163162

164-
### PS
163+
### P.S.
165164

166-
`RenderDoc` is not a profiler, the frametimes you see reported there are not really usable. Use an actual gpu profiler like `NSight Graphics`. I hear you complain already
167-
that Version YYYY.XX doesnt support your potato GPU. NVidia provides downloads for older versions as well, you just dont get the latest bling features with it.
165+
`RenderDoc` is not a profiler, the frametimes you see reported there are not really usable. Use an actual GPU profiler like NSight Graphics. NVidia provides downloads for older versions as well, in case you have an older GPU. You just dont get the latest bling features with them.

0 commit comments

Comments
 (0)
Please sign in to comment.