Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

step030 Can not load SPIR-V shader #39

Open
MHDtA-dev opened this issue Apr 28, 2024 · 7 comments
Open

step030 Can not load SPIR-V shader #39

MHDtA-dev opened this issue Apr 28, 2024 · 7 comments

Comments

@MHDtA-dev
Copy link

MHDtA-dev commented Apr 28, 2024

I have a function that loads spv file:

std::vector<uint32_t> loadSpv(std::string path) {
    std::ifstream file(path, std::ios::ate | std::ios::binary);

    if (!file.is_open()) {
        throw std::runtime_error("Failed to load file");
    }

    size_t fileSize = (size_t)file.tellg();
    std::vector<uint32_t> buffer(fileSize / sizeof(uint32_t));
    file.seekg(0);
    file.read((char*) buffer.data(), fileSize);
    file.close();

    return buffer;
}

I am trying to create the shader as follows:

    auto vertexCode = loadSpv("Shaders/Triangle/v.spv");

    wgpu::ShaderModuleSPIRVDescriptor vert;
    vert.chain.next = nullptr;
    vert.chain.sType = wgpu::SType::ShaderModuleSPIRVDescriptor;
    vert.code = vertexCode.data();
    vert.codeSize = vertexCode.size() * sizeof(uint32_t);

    wgpu::ShaderModuleDescriptor vertDesc;
    vertDesc.nextInChain = &vert.chain;
    vertDesc.hintCount = 0;
    vertDesc.hints = nullptr;

    wgpu::ShaderModule vertex = device.createShaderModule(vertDesc);

But it crashes with error:

thread '<unnamed>' panicked at src/lib.rs:429:5:
wgpu uncaptured error:
Validation Error

Caused by:
    In wgpuDeviceCreateShaderModule
    invalid word count

I also tried to use this variant of loading:

std::vector<char> loadSpv(std::string path) {
    std::ifstream file(path, std::ios::ate | std::ios::binary);

    if (!file.is_open()) {
        throw std::runtime_error("Failed to open file");
    }

    size_t fileSize = (size_t) file.tellg();
    std::vector<char> buffer(fileSize);

    file.seekg(0);
    file.read(buffer.data(), fileSize);

    file.close();

    return buffer;
}
    auto vertexCode = loadSpv("Shaders/Triangle/v.spv");

    wgpu::ShaderModuleSPIRVDescriptor vert;
    vert.chain.next = nullptr;
    vert.chain.sType = wgpu::SType::ShaderModuleSPIRVDescriptor;
    vert.code = reinterpret_cast<const uint32_t*>(vertexCode.data());
    vert.codeSize = vertexCode.size();
    

    wgpu::ShaderModuleDescriptor vertDesc;
    vertDesc.nextInChain = &vert.chain;
    vertDesc.hintCount = 0;
    vertDesc.hints = nullptr;

    wgpu::ShaderModule vertex = device.createShaderModule(vertDesc);

But it causes the same error.

Here is my shader code:

#version 460

layout (location = 0) in vec2 inPos;

void main() {
    gl_Position = vec4(inPos, 1, 1);
}

Compiled with glslc v.vert -o v.spv

System: MacOS Ventura (Intel)

How can I correctly load SPIR-V shader?

@MHDtA-dev
Copy link
Author

Any update?

@cjsimon
Copy link

cjsimon commented Jun 6, 2024

gpuweb/gpuweb#847

Unfortunately, I don't think the WebGPU spec specifies loading SPIR-V directly. You'd have to use a transpiler like naga or tint to compile your shader code into wgsl.

Also note that WGSL was originally designed to be a human-editable version of SPIR-V programming model, so transpilation from SPIR-V to WGSL is in theory efficient and lossless (use Naga or Tint for this).

https://github.com/eliemichel/LearnWebGPU/blob/e53f715daee35ef09eb41110bcefe5e5ca00c982/basic-3d-rendering/hello-triangle.md#L368

The shader language officially used by WebGPU is called WGSL, namely the WebGPU Shading Language. Any implementation of WebGPU must support it, and the JavaScript version of the API only supports WGSL, but the native header webgpu.h also offers the possibility to provide shaders written in SPIR-V or GLSL (wgpu-native only).

https://github.com/eliemichel/LearnWebGPU/blob/e53f715daee35ef09eb41110bcefe5e5ca00c982/basic-3d-rendering/hello-triangle.md#L361

I assume this is referring to naga/spv-in?

These notes on SPIR-V to WGSL translation efforts in Tint make me wonder about the efficiency and losslessness on a high-level.

https://dawn.googlesource.com/dawn/+/ada5e7b0f9de129a54667f9e28f1865623261190/docs/tint/spirv-reader-overview.md

https://dawn.googlesource.com/dawn/+/ada5e7b0f9de129a54667f9e28f1865623261190/docs/tint/translations.md


Never mind... Just realized you're already using wgpu-native. This seems related: gfx-rs/wgpu#4915. Have you tried compiling with glslangValidator instead?

@eliemichel
Copy link
Owner

Unfortunately, I don't think the WebGPU spec specifies loading SPIR-V directly.

The Web version of WebGPU (i.a., what browsers support) does not support loading SPIR-V directly indeed. However, the native version of WebGPU backends has extra features, and both Dawn and wgpu-native do support it actually. Actually, the WGPUShaderModuleSPIRVDescriptor chain extension is even part of the standard native header. Of course, this feature does not support cross-compilation to WebAssembly.

Note that in the FetchDawn.cmake script provided by my WebGPU-distribution, I turn TINT_BUILD_SPV_READER off to speed up compilation, but it is easy to turn it back on.

As for the original issue, it is a wgpu-native specific one. After searching in their codebase, it seems to come from this line in wgpu/naga/src/front/spv/mod.rs. The "word count" in question (wc in the code) is the 16 most significant bits of the next 32-bit "word" that is being loaded from the SPIR-V shader. This shouldn't be 0 so there is something wrong with your SPIR-V file. I suggest you try and compile it back, or inspecting using a dedicated tool like SPIR-V Visualizer. If the problem persists, fill an issue in the wgpu repo!

@MHDtA-dev
Copy link
Author

MHDtA-dev commented Jun 7, 2024

I tried to compile with glslangValidator, but unfortunately it didn't work. I tested this on other systems(Windows 10 MSYS2 MinGW64 and Ubuntu 22.04 g++) and this issue also appears there. Also it can't be something with my spv file, because I was just able to successfully upload this shader to Vulkan using functions I have given above. The only one way out for me - use wgpu::ShaderModuleGLSLDescriptor which works correctly. Anyway, thanks for help.

P.S. Does not apply to this issue, after the last commit in the webgpu.hpp file of the wgpu branch, an error occurs that the CPP_VERSION macro is not defined. I suppose there should be __cplusplus instead

@eliemichel
Copy link
Owner

P.S. Does not apply to this issue, after the last commit in the webgpu.hpp file of the wgpu branch, an error occurs that the CPP_VERSION macro is not defined. I suppose there should be __cplusplus instead

Wow my bad, I fixed this thx for reporting!

Also it can't be something with my spv file, because I was just able to successfully upload this shader to Vulkan using functions I have given above.

Mmh ok, could you share your very spv file (+ the text version)? I'll try with both Dawn and wgpu-native, it may be a bug of the latter that we need to report.

@MHDtA-dev
Copy link
Author

Of course, uploaded it here

@eliemichel
Copy link
Owner

eliemichel commented Jun 8, 2024

Both wgpu-native and Dawn are unhappy with vert_glslc.spv or vert_glslangValidator.spv:

wgpu-native

Uncaptured device error: type 1 (Validation Error

Caused by:
    In wgpuDeviceCreateShaderModule
    unknown instruction 65021
)

Dawn

Uncaptured device error: type 1 (Produced invalid SPIRV. Please file a bug at https://crbug.com/tint.
 - While validating [ShaderModuleDescriptor]
 - While calling [Device "My Device"].CreateShaderModule([ShaderModuleDescriptor]).
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants