Why does a vertex shader (Vulkan) work on linux, but not on Windows?

Issue

I am trying to cross compile a Vulkan project from windows to linux, this works, only the vertex shader causes a problem on windows though it works perfectly fine on Linux… (Note that the code and validations work on windows if I do not try to add the shader stage to the graphics pipeline, obviously there is nothing being rendered.)

The compiler on linux (cross compiler for windows is: x86_64-w64-mingw32-gcc, which is not the same as mingw). In order to link Vulkan properly I downloaded the windows library including it in the project in the standard fashion.

The error I get (triggered upon calling vkCreateShaderModule, the VkResult is then VK_ERROR_VALIDATION_FAILED_EXT):

message: Validation Error: [ UNASSIGNED-CoreValidation-Shader-InconsistentSpirv ] Object 0: handle = 0x1a4c760cf78, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x6bbb14 | SPIR-V module not valid: Error: Result Id is 0

The vertex shader:

#version 460

layout(location = 0) in vec3 in_position;

void main() {
    gl_Position = vec4(in_position.xyz, 1.0);
}

I tried compiling the shader with different versions (pretty much tried all viable glsl versions), but no luck.
The shaders are compiled as follows (glslc was included in the VulkanSDK):

glslc shader.vert -o vert.spv

Note that if I try this exact same thing for the fragment shader, it works fine, I include the fragment shader for the sake of completeness:

#version 460

layout(location = 0) out vec4 out_color;

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

I once again want to emphasize that when compiling for linux and running it there everything works just fine (I even get a triangle to pop up).

How I load the shader:

fseek(file, 0, SEEK_END);
shader->code_size = ftell(file);

uint8_t* code = (uint8_t*) calloc(shader->code_size, sizeof(uint8_t));

fseek(file, 0, SEEK_SET);
fread(code, 1, shader->code_size, file);

shader->code = code;

where file is a valid FILE pointer from stdio.h and shader is a wrapper around VkPipelineShaderStageCreateInfo which looks as follows:

typedef struct shader {
    VkPipelineShaderStageCreateInfo get;
    VkShaderModuleCreateInfo module_info;
    VkShaderModule module;
    size_t code_size;
    uint32_t *code;
} Shader;

Note there is an implicit cast (code pointer) from uint8_t to uint32_t, this has to happen one way or another since VkPipelineShaderStageCreateInfo expects a uint32_t pointer. Once again: works on linux…

I also tried changing the vert.spv file for older compiled files from previous projects (which have functioned correctly on windows in the past), but I get the same validation error.

Before I go ahead and scream in Khronos’ face for not fixing a bug, I want to make sure this is in fact a bug, so if you have any clue or suggestion for what might cause this issue, I would gladly hear it. If anyone can confirm this is a bug, I will file a bug report I guess.

EDIT:
I did try to compile the shader on windows as well (with glslc.exe also from the VulkanSDK, no luck).

Solution

Looks like you need to open the file in binary mode. See here for more info.

Answered By – Karl Schultz

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published