My intersection shader always reads just zeroes from the SSBO I have.
I tried using debugPrintEXT
, but it wouldn't print out from within the intersection shader. However, when I try to output any value via the ray payload as the hit colour, all I get is black colour all the time. Initially, I thought there was a problem with how I copied the data, but no, it is all just as good as in the example code, which works (from NVIDIA). Then, the validation layer throws no warnings/errors/nothing. Then I checked in NVIDIA NSight graphics what the buffer has, and it has the data I copied to it, exactly with the layout I wanted. Then I checked the SPIRV instructions, and all of them correctly refer to the offsets of the buffer! I am completely lost now: even the NVIDIA NSight sees the correct values but not the shader!
So, here is the shader code:
// 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;
}
Here is the layout of the structure in Rust:
#[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
I don't get what is wrong. I tried to play with padding, but it just didn't help, nothing helped with regard to memory alignment. Even so, if it was an alignment issue, I think the shader should have accessed the values, at least the first ones, as those are laid out properly anyway.
Update: it seems that my closest hit shader doesn't even work when the read is performed to the buffer!
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);
}
Here, neither of the branch sections is walked into! The "payload" is not set entirely, so the colour I see is pitch black. However, if I don't try to access the "material" buffer and read values out of it, or just put an assignment to the "payload" after these if-elses, the colour I assign is visible:
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);
Besides that, if I set the colour first to that, before the branching, the colour is black again, as if the payload wasn't set!
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 I leave just one if and check for whatever number, it is always evaluated to true. Do I see some UB?
Another screenshot from the NSight showing that the buffer is correctly laid out, bound to the hit shader correctly as well:
My current guess is that the shader binding table isn't properly set up for the hit shader. But then I don't understand why it is even invoked then.
To whoever decided to vote for closing: The reproduction steps must be clear to everyone who knows vulkan and rust and glsl: use a GPU buffer of the desired type. The NSight proves that it is done correctly, so this of the MCVE is unnecessary. The only thing not working correctly here is the shader, and the code for it serves as MCVE. The desired behaviour is obvious - the data should be read as it is in the buffer instead of zeroes all the time. If you have any questions - ask, don't vote for closing unless it is clear to you. Even if you are sure, notify the author about that instead of silently voting. People may provide any sort of information if asked, but I have already provided all the necessary information.