1

I'm using SDL2 and GLES3 to write a simple GUI toolkit. My drivers are nouveau. Code ran fine until I tried compiling a shader program, which resulted in segmentation fault during execution of glLinkProgram. GDB shows that error occurs in mesa's link_interface_blocks.cpp

│      308  validate_intrastage_interface_blocks(struct gl_shader_program *prog,│
│      309                                       const gl_shader **shader_list, │
│      310                                       unsigned num_shaders)          │
│      311  {                                                                   │
│      312     interface_block_definitions in_interfaces;                       │
│      313     interface_block_definitions out_interfaces;                      │
│      314     interface_block_definitions uniform_interfaces;                  │
│      315     interface_block_definitions buffer_interfaces;                   │
│      316                                                                      │
│      317     for (unsigned int i = 0; i < num_shaders; i++) {                 │
│      318        if (shader_list[i] == NULL)                                   │
│      319           continue;                                                  │
│      320                                                                      │
│  >   321        foreach_in_list(ir_instruction, node, shader_list[i]->ir) {   │
│      322           ir_variable *var = node->as_variable();                    │
│      323           if (!var)                                                  │
│      324              continue;     

Minimal code that causes the error:

#define GLEW_STATIC

#include "voidgui.h"
#include "table.h"
#include "window.h"
#include <GLES3/gl3.h>
#include <SDL2/SDL.h>

#include "common_frag_src.h"
#include "common_vert_src.h"

static GLuint compile_shader(GLuint type, const GLchar *src) {
  GLuint shader = glCreateShader(type);
  glShaderSource(shader, 1, &src, NULL);
  glCompileShader(shader);

  GLint ok;
  glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
  if (ok == GL_FALSE) {
    GLint log_len;
    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_len);
    char *log = calloc(log_len, sizeof(char));
    glGetShaderInfoLog(shader, log_len, NULL, log);

    printf("Failed to compile shader\n %s\n", log);
    glDeleteShader(shader);
    shader = 0;
  }

  return shader;
}

static GLuint link_program(const GLchar *vert_src, const GLchar *frag_src) {
  GLuint vert = compile_shader(GL_VERTEX_SHADER, vert_src);
  if (!vert) {
    goto error;
  }

  GLuint frag = compile_shader(GL_FRAGMENT_SHADER, frag_src);
  if (!frag) {
    glDeleteShader(vert);
    goto error;
  }

  GLuint prog = glCreateProgram();
  glAttachShader(prog, vert);
  glAttachShader(prog, frag);
  glLinkProgram(prog);

  glDetachShader(prog, vert);
  glDetachShader(prog, frag);
  glDeleteShader(vert);
  glDeleteShader(frag);

  GLint ok;
  glGetProgramiv(prog, GL_LINK_STATUS, &ok);
  if (ok == GL_FALSE) {
    ;
    printf("Failed to link shader\n");
    glDeleteProgram(prog);
    goto error;
  }

  return prog;

error:
  return 0;
}

struct void_window *void_gui_init(int time) {
  SDL_Init(SDL_INIT_EVERYTHING);

  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
  SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

  SDL_Window *window =
      SDL_CreateWindow("Void", 100, 100, 800, 600, SDL_WINDOW_OPENGL);

  SDL_GLContext context = SDL_GL_CreateContext(window);

  link_program(common_vert_src, common_frag_src); // arrays that contain shaders

  return 0;
}

Vertex shader:

attribute vec2 pos;

void main() {
    gl_Position = vec4(pos, 0.0, 1.0);
}

Fragment shader:

void main() {
    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}

Shaders seem to compile correctly and the program does get created. If I comment out glAttachShader linking fails as expected without segmentation faults. Seems to me like an initialization mistake, though most of the code above is copied from other projects.

genpfault
  • 51,148
  • 11
  • 85
  • 139
Oleg Sleva
  • 11
  • 2
  • 1
    It doesn't looks as if you are using Opengl-ES 3, more like (Desktop-)OpenGL 3.2 Core Profile. My guess is that the crash happens because you use a Deskop GL context, but use headers for OpenGL-ES. Try to add `SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);`. And you also forgot to make the context current (`SDL_GL_MakeCurrent(...)`) – BDL Mar 30 '23 at 13:18
  • 1
    Then, your shader code also doesn't match OpenGL-ES 3.X. Shaders have to start with `#version 3XX es`, attribute/varying has been replaced with in/out. The predefined `gl_FragColor` doesn't exist anymore and has to be replaced by a custom output. – BDL Mar 30 '23 at 13:26
  • @BDL suggestions from your first comment haven't helped, but I appreciate the explanation and will look into it. – Oleg Sleva Mar 30 '23 at 14:08
  • Could you update your question with the improved code? – BDL Mar 30 '23 at 21:07
  • @BDL now that I've tried it again the error appears to be fixed, but only if I use both of your corrections. Must have missed that the first time I checked because linking still fails and causes another segmentation fault later :) Thanks a ton! – Oleg Sleva Mar 30 '23 at 21:32
  • I'll look into it and try to assemble an answer later – Oleg Sleva Mar 30 '23 at 21:35

1 Answers1

0

I've got it working after reformatting shaders and correcting my profile to ES. The lesson here is that you should figure out exactly what are you using to avoid unnecessary trouble.

Oleg Sleva
  • 11
  • 2
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 04 '23 at 14:52