You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GLSL Compute Shader编译报错:SSBO中uint类型赋值失败排查

Vulkan Compute Shader SSBO编译错误排查

我正尝试在Vulkan应用中添加Compute Shader,当前Shader仅实现将输入SSBO复制到输出SSBO的功能,Shader源码如下:

#version 320 es

layout(std140, binding = 0) uniform UniformBufferObjectTest {
    uint num_segments;
} ubo;

layout(std140, binding = 1) readonly buffer verticesSSBOIn {
    vec3 posIn;
    uint vert_typeIn;
    uvec4 mirrorsIn;
    vec3 other_posIn;
};

layout(std140, binding = 2) buffer verticesSSBOOut {
    vec3 posOut;
    uint vert_typeOut;
    uvec4 mirrorsOut;
    vec3 other_posOut;
};

layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;

void main() 
{
    uint index = gl_GlobalInvocationID.x;  

    if (index < ubo.num_segments) {
        posOut[index] = posIn[index];
        vert_typeOut[index] = vert_typeIn[index];
        mirrorsOut[index] = mirrorsIn[index];
        other_posOut[index] = other_posIn[index];
    }
}

使用glslc编译时出现如下错误:

$ make
~/opengl/vulkan/shaderc/build/glslc/glslc -fshader-stage=compute comp.glsl -o comp.spv
comp.glsl:29: error: 'expression' :  left of '[' is not of type array, matrix, or vector
comp.glsl:29: error: 'expression' :  left of '[' is not of type array, matrix, or vector
comp.glsl:29: error: 'assign' :  l-value required (can't modify a const)
3 errors generated.
make: *** [Makefile:40: comp.spv] Error 1

注释vert_typeOut[index] = vert_typeIn[index]这一行后即可正常编译,请问GLSL是否不支持Shader Storage Buffer Object(SSBO)中的uint类型?


问题原因与解决方法

GLSL完全支持SSBO中的uint类型,错误根源是SSBO的声明方式错误。

你的SSBO块中同时声明了多个独立变量(posIn、vert_typeIn等),但在代码中却用数组下标[index]去访问这些变量——单个uint或vec3不是数组,自然不能用索引访问。

GLSL里只有当SSBO块中仅声明一个变量时,编译器才会自动将其视为该类型的数组(语法糖)。但你的块里有多个变量,此时整个块对应的是一个结构体,而非多个独立数组。正确的做法是先定义包含所有顶点数据的结构体,再声明结构体的数组:

#version 320 es

layout(std140, binding = 0) uniform UniformBufferObjectTest {
    uint num_segments;
} ubo;

// 定义包含所有顶点字段的结构体
struct VertexData {
    vec3 pos;
    uint vert_type;
    uvec4 mirrors;
    vec3 other_pos;
};

// 输入SSBO:VertexData类型的数组
layout(std140, binding = 1) readonly buffer verticesSSBOIn {
    VertexData dataIn[];
};

// 输出SSBO:VertexData类型的数组
layout(std140, binding = 2) buffer verticesSSBOOut {
    VertexData dataOut[];
};

layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;

void main() 
{
    uint index = gl_GlobalInvocationID.x;  

    if (index < ubo.num_segments) {
        dataOut[index].pos = dataIn[index].pos;
        dataOut[index].vert_type = dataIn[index].vert_type;
        dataOut[index].mirrors = dataIn[index].mirrors;
        dataOut[index].other_pos = dataIn[index].other_pos;
    }
}

之前注释掉uint相关行能编译是巧合:编译器对向量类型的错误写法兼容性稍高,但本质整个访问逻辑都是错误的,只有改用结构体数组才能彻底解决问题。


内容的提问来源于stack exchange,提问作者user256552

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 15:10:11