Segmentation Fault during vkCreateGraphicsPipelines
Segmentation Fault during vkCreateGraphicsPipelines

While working through some vulkan tutorials, I was hit by a bug that took me far too long to figure out! After deleting and rewriting the pipeline creation section, I hit the Internet and came across a list of possible errors that could cause a SEGV when calling vkCreateGraphicsPipelines. The typical culprit is a misconfigured shader.

glslangValidator
I'd always been disgusted with the common practice of shipping shaders as separate files alongside the executable (it is, however, a very nice feature when the requirements call for it!). With the new practice of compiling shaders to SPIR-V, I was dismayed to see the old pattern of keeping the compiled shader code in a separate file and loading it at runtime.

Fortunately, glslangValidator can emit a compiled shader as an array of uint32_t:

$ cat shader.frag
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec3 fragColor;
layout(location = 0) out vec4 outColor;
void main() {
    outColor = vec4(fragColor, 1.0);
}
$ glslangValidator -V --variable-name fragment -o fragment.c shader.frag
$ more fragment.c
        // Overload400-PrecQual.1845 24-Feb-2017
         #pragma once
const uint32_t fragment[] = {
        0x07230203,0x00010000,0x00080001,0x00000013,0x00000000,0x00020011,0x00000001,0x0006000b,
        // you get the idea
};

You can then manually paste the code into your project, or automate the process by abusing the #include directive:

#include "fragment.c"

The Problem
When I went to load uint32_t fragment[] into vkCreateShaderModule, I naively used the "get length of array" pattern to describe the shader code:

VkShaderModuleCreateInfo fragmentShaderModuleCreateInfo = {
			.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
			.codeSize = sizeof fragment / sizeof fragment[0],
			.pCode = fragment,
		};
vkCreateShaderModule(state->device, &fragmentShaderModuleCreateInfo, NULL, &(state->fragmentShaderModule));

The above compiles fine, and as long as you don't try and call vkCreateGraphicsPipelines with this as a dependency, you'll never know that you wrote bad code!

The Solution
Upon closer inspection of the VkShaderModuleCreateInfo docs, you'll see that codeSize is supposed to be specified in bytes! Had the array been const char*, I'd have never even known I'd written this bug.

If we change our code to specify the length of an uint32_t array in bytes, the segmentation fault goes away:

		.codeSize = sizeof fragment * sizeof fragment[0],

The best bugs really are only one character.


Leave a Comment?

Send me an email, then I'll place our discussion on this page (with your permission).


Return | About/Contact