My goal is to generate a luminance waveform similar to this using a compute shader.
My setup is:
- Cpp window application
- EGL/egl.h
- GLES3/gl31.h (specifically requesting an ES 3.1 context)
- libGLESv2.dll from ANGLE's most recent build (04.01.2024)
Compute Shader:
#version 310 es
layout(local_size_x = 16, local_size_y = 16) in;
layout(binding = 0, rgba8ui) uniform highp readonly uimage2D u_sourceTexture;
layout(binding = 1, rgba8ui) uniform highp writeonly uimage2D u_waveformTexture;
void main() {
ivec2 sourceSize = imageSize(u_sourceTexture);
ivec2 waveformSize = imageSize(u_waveformTexture);
ivec2 gid = ivec2(gl_GlobalInvocationID.xy);
if (gid.x < sourceSize.x && gid.y < sourceSize.y) {
uvec4 color = imageLoad(u_sourceTexture, gid);
float luminance = dot(vec3(color.rgb) / 255.0, vec3(0.299, 0.587, 0.114));
int waveformY = int(clamp(luminance * float(waveformSize.y-1), 0.0, float(waveformSize.y - 1)));
int waveformX = int(clamp(float(gid.x) * float(waveformSize.x) / float(sourceSize.x), 0.0, float(waveformSize.x - 1)));
// Compute the position in the waveform texture
ivec2 waveformPos = ivec2(waveformX, waveformY);
// Write the color to the waveform texture
// this line causes the crash
imageStore(u_waveformTexture, waveformPos, color);
}
}
Part of my renderloop:
glUseProgram(m_shaderprog_compute_luma_waveform);
glBindImageTexture(
0, // image unit (not texture unit)
m_tex_source,
0,
GL_FALSE,
0,
GL_READ_ONLY,
GL_RGBA8UI
);
glBindImageTexture(
1, // image unit (not texture unit)
m_tex_luma_waveform,
0,
GL_FALSE,
0,
GL_WRITE_ONLY,
GL_RGBA8UI
);
const int groupSize = 16;
unsigned int sourceWidth = m_source_width();
unsigned int sourceHeight = m_source_height();
GLuint numGroupsX = (sourceWidth + groupSize - 1) / groupSize;
GLuint numGroupsY = (sourceHeight + groupSize - 1) / groupSize;
glDispatchCompute(numGroupsX, numGroupsY, 1);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
glUseProgram(0);
The texture in m_tex_source contains the correct data and can be displayed without a problem using a simple vertex and fragment shader.
The output texture is generated using:
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &m_tex_luma_waveform);
if (m_tex_luma_waveform == 0) {
throw std::runtime_error("Failed to create luma waveform texture");
}
glBindTexture(GL_TEXTURE_2D, m_tex_luma_waveform);
// Set our texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// 580 x 256 px with RGBA8ui data
glTexImage2D(
GL_TEXTURE_2D, // target
0, // level
GL_RGBA8UI, // internal format
m_luma_waveform_width, // width
m_luma_waveform_height, // height
0, // border
GL_RGBA_INTEGER, // format
GL_UNSIGNED_BYTE, // type
NULL // data
);
glBindTexture(GL_TEXTURE_2D, 0);
The input/source texture was similarly generated using:
... // generate and bind texture, set filters and wrap
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGBA,
image->width,
image->height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
image->pixels
);
The crash occurs here:
glDispatchCompute(numGroupsX, numGroupsY, 1);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
The exception is shown in the glMemoryBarrier line but probably still belongs to the shader execution.
This is the exception:
Exception thrown at 0x00007FFA387FBE36 (libGLESv2.dll) in angle_test.exe: 0xC0000005: Access violation reading location 0x00000000000000C8.
When I remove the line containig imageStore from the compute shader, the crash disappears.
Thanks for all the help in advance.
Compiling ANGLE from source in Debug mode helped and gave helpful error messages that indicated that I wasn't using immutable textures.
changing
to
resolved the issue, since
glTexStorage2Dcreates an immutable texture with fixed size and format, that is needed forglBindImageTexturein the renderloop.