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

Time:07-29

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).

CodePudding user response:

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

  • Related