我的交叉点着色器总是只从我拥有的SSBO中读取零.
我try 使用debugPrintEXT
,但无法从交叉点着色器中打印出来.然而,当我试图通过光线有效载荷输出任何值作为命中 colored颜色 时,我得到的总是黑色.最初,我认为我复制数据的方式有问题,但事实并非如此,它与示例代码一样好,它可以工作(来自NVIDIA).然后,验证层不抛出警告/错误/不抛出任何内容.然后我判断了NVIDIA NSight显卡的缓冲区,其中有我复制到其中的数据,完全符合我想要的布局.然后我判断了SPIRV指令,它们都正确地引用了缓冲区的偏移量!我现在完全迷路了:即使是NVIDIA NSight也能看到正确的值,但看不到着色器!
因此,下面是着色器代码:
// Hitting a triangle.
#version 460 core
#extension GL_EXT_ray_tracing : enable
layout(location = 0) rayPayloadInEXT vec4 payload;
hitAttributeEXT vec2 attributes;
layout(push_constant) uniform rayParams {
vec3 rayOrigin;
vec3 rayDir;
mat4 transformMatrix;
float maxDistance;
};
struct PhongMaterial {
float ambient;
float diffuse;
float specular;
float shininess;
float reflective;
float transparency;
float refraction;
vec4 color;
float reserved_1;
vec4 reserved_2;
};
layout(set = 0, binding = 2) readonly buffer Materials {
PhongMaterial m[];
}
materials;
void main() {
PhongMaterial material = materials.m[0];
payload = material.color;
}
以下是铁 rust 的 struct 布局:
#[repr(C)]
pub struct PhongMaterial {
pub ambient: f32,
pub diffuse: f32,
pub specular: f32,
pub shininess: f32,
pub reflective: f32,
pub transparency: f32,
pub refraction: f32,
pub color: ColorRGBA,
reserved: [u8; 20],
}
The total byte size of the struct is 44 bytes. Aligning to a multiple of 16 results in 48 bytes copy when moving the data from the temporary CPU buffer to the GPU buffer. Here is the screenshot of NVIDIA NSight, which proves the shader must have the data: Here in the screenshot of NSight, the values are exactly the ones I have in Rust. And here is the shader's SPIRV:
OpName %58 "PhongMaterial"
OpMemberDecorate %58 0 Offset 0
OpMemberDecorate %58 1 Offset 4
OpMemberDecorate %58 2 Offset 8
OpMemberDecorate %58 3 Offset 12
OpMemberDecorate %58 4 Offset 16
OpMemberDecorate %58 5 Offset 20
OpMemberDecorate %58 6 Offset 24
OpMemberDecorate %58 7 Offset 32
OpMemberDecorate %58 8 Offset 48
OpMemberDecorate %58 9 Offset 64
我不明白哪里出了问题.我试着玩填充符,但没有帮助,在记忆对齐方面没有任何帮助.即便如此,如果是对齐问题,我认为着色器应该已经访问了这些值,至少是第一个值,因为这些值无论如何都是正确布局的.
更新:似乎我最近的命中着色器在执行对缓冲区的读取时都不起作用!
void main() {
PhongMaterial material = materials.m[0];
if (material.ambient <= 0.1) {
payload = vec4(1.0, 0.0, 0.0, 1.0);
} else if (material.ambient <= 0.5) {
payload = vec4(0.0, 1.0, 0.0, 1.0);
} else {
payload = vec4(0.0, 0.0, 1.0, 1.0);
}
在这里,这两个分支部分都没有走进go !"有效载荷"没有完全设定,所以我看到的 colored颜色 是一片漆黑.但是,如果我不try 访问"Material"缓冲区并从中读取值,或者只是在这些if-else之后为"有效负载"赋值,则我分配的 colored颜色 是可见的:
if (material.ambient <= 0.1) {
payload = vec4(1.0, 0.0, 0.0, 1.0);
} else if (material.ambient <= 0.5) {
payload = vec4(0.0, 1.0, 0.0, 1.0);
} else {
payload = vec4(0.0, 0.0, 1.0, 1.0);
}
payload = vec4(1.0, 1.0, 0.0, 1.0);
除此之外,如果我首先设置 colored颜色 ,在分支之前, colored颜色 又是黑色的,就好像没有设置有效载荷一样!
payload = vec4(1.0, 1.0, 0.0, 1.0);
if (material.ambient <= 0.1) {
payload = vec4(1.0, 0.0, 0.0, 1.0);
} else if (material.ambient <= 0.5) {
payload = vec4(0.0, 1.0, 0.0, 1.0);
} else {
payload = vec4(0.0, 0.0, 1.0, 1.0);
}
如果我只留下一个If并判断任何数字,它的计算结果总是为True.我是不是看到了UB?
Another screenshot from the NSight showing that the buffer is correctly laid out, bound to the hit shader correctly as well:
我目前的猜测是,着色器绑定表没有为命中着色器正确设置.但我不明白为什么当时甚至会援引它.
致决定投票支持结案的人: 每个知道Vulkan、Rust和GLSL的人都必须清楚复制步骤:使用所需类型的GPU缓冲区.NSight证明它是正确的,所以MCVE的这一点是不必要的.唯一不能正常工作的是着色器,它的代码用作MCVE.所需的行为是显而易见的-数据应该按其在缓冲区中的原样被读取,而不是始终为零.如果你有任何问题--问,除非你清楚,否则不要投票支持结案.即使你很确定,也要通知作者,而不是默默投票.如果被要求,人们可以提供任何类型的信息,但我已经提供了所有必要的信息.