-
Notifications
You must be signed in to change notification settings - Fork 436
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
Lots of conflicts with reused uniform buffers in 0.22 #1557
Comments
@faulesocke Can you show shader's layout, please? |
Sure: #version 450 core
#include <light.inc.glsl>
layout(binding = 0) uniform Light {
DirectionalLight light;
};
layout(binding = 1) uniform Model {
mat4 model;
mat4 normal;
} model;
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 texcoord;
layout(location = 3) in vec3 tangent;
layout(location = 4) in vec3 bitangent; |
Could you run your code through |
That must be the problem! None of the uniform buffers are marked #[allow(unsafe_code)]
unsafe impl PipelineLayoutDesc for MainLayout {
fn num_sets(&self) -> usize {
1usize
}
fn num_bindings_in_set(&self, set: usize) -> Option<usize> {
match set {
0usize => Some(2usize),
_ => None,
}
}
fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc> {
match (set, binding) {
(0usize, 0usize) => Some(DescriptorDesc {
ty: DescriptorDescTy::Buffer(DescriptorBufferDesc {
dynamic: None,
storage: false,
}),
array_count: 1u32,
stages: self.0.clone(),
readonly: false,
}),
(0usize, 1usize) => Some(DescriptorDesc {
ty: DescriptorDescTy::Buffer(DescriptorBufferDesc {
dynamic: None,
storage: false,
}),
array_count: 1u32,
stages: self.0.clone(),
readonly: false,
}),
_ => None,
}
} |
If you can give me the full invocation of |
Here you are: mod shadow_vs {
vulkano_shaders::shader! {
ty: "vertex",
path: "shaders/dir_shadow.vert.glsl",
include: ["shaders/include/"],
}
} The #version 450 core
#include <light.inc.glsl>
layout(binding = 0) uniform Light {
DirectionalLight light;
};
layout(binding = 1) uniform Model {
mat4 model;
mat4 normal;
} model;
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 texcoord;
layout(location = 3) in vec3 tangent;
layout(location = 4) in vec3 bitangent;
void main() {
gl_Position = light.viewproj * model.model * vec4(position, 1.0);
} and struct DirectionalLight {
mat4 view;
mat4 proj;
mat4 viewproj;
vec3 direction;
vec3 color;
}; I guess you can minimalize/remove the vertex input in order to reproduce the issue. Thank you very much for your effort! |
On my system with the latest Vulkano master, these descriptors are marked as readonly. So that should be all you need to do. |
Migrating to current master fixed this problem, thank you. However, I still have an unresolved conflict with image bindings. I will investigate this and report back here when I know more. |
If they are descriptors with the |
@Rua no they are just I tracked my error down to the following situation: When I try to bind the same image to two different descriptor sets (with different layouts) and issue two draw commands, one for each descriptor set then
Should I open a new issue to discuss this problem, since it's separate from the others? |
If |
Well when using |
It certainly should, but who knows if Vulkano currently agrees with us! :D |
I've checked fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc> {
match (set, binding) {
(0usize, 2usize) => Some(DescriptorDesc {
ty: DescriptorDescTy::CombinedImageSampler(DescriptorImageDesc {
sampled: true,
dimensions: DescriptorImageDescDimensions::TwoDimensional,
format: None,
multisampled: false,
array_layers: DescriptorImageDescArray::Arrayed {
max_layers: None,
},
}),
array_count: 1u32,
stages: self.0.clone(),
readonly: true,
}),
(0usize, 1usize) => Some(DescriptorDesc {
ty: DescriptorDescTy::CombinedImageSampler(DescriptorImageDesc {
sampled: true,
dimensions: DescriptorImageDescDimensions::TwoDimensional,
format: None,
multisampled: false,
array_layers: DescriptorImageDescArray::Arrayed {
max_layers: None,
},
}),
array_count: 1u32,
stages: self.0.clone(),
readonly: true,
}),
// ... Oh, and I lied, I was actually using Edit: Here is the GLSL for the above descriptors: layout(binding = 0) uniform sampler2DArray gbuffer_diffuse;
layout(binding = 1) uniform sampler2DArray gbuffer_normals; |
Where in the code is this |
It's set in https://github.com/vulkano-rs/vulkano/blob/master/vulkano/src/command_buffer/synced/commands.rs#L2745-L2816. As you can see it's literally just the inverse of the |
Okay, in https://github.com/vulkano-rs/vulkano/blob/master/vulkano/src/command_buffer/synced/base.rs#L563 the
|
Ok, that means that this descriptor is correct, but it's colliding with a previous access somewhere that requires exclusive access. In your first post, you gave this message: Conflict {
command1_name: "vkCmdBindDescriptorSets",
command1_param: "Buffer bound to descriptor 0 of set 0",
command1_offset: 4,
command2_name: "vkCmdBindDescriptorSets",
command2_param: "Buffer bound to descriptor 0 of set 0",
command2_offset: 8,
}
|
The command buffer contains only two draw commands, but of course this results in more Perhaps it's time to mention, that I'm using a slightly modified version of the |
What do the descriptors for the first command look like? And are these perhaps being marked as not |
The first command has only 2 descriptors, I've already checked them, they are correctly marked as fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc> {
match (set, binding) {
(0usize, 0usize) => Some(DescriptorDesc {
ty: DescriptorDescTy::CombinedImageSampler(DescriptorImageDesc {
sampled: true,
dimensions: DescriptorImageDescDimensions::TwoDimensional,
format: None,
multisampled: false,
array_layers: DescriptorImageDescArray::Arrayed {
max_layers: None,
},
}),
array_count: 1u32,
stages: self.0.clone(),
readonly: true,
}),
(0usize, 1usize) => Some(DescriptorDesc {
ty: DescriptorDescTy::CombinedImageSampler(DescriptorImageDesc {
sampled: true,
dimensions: DescriptorImageDescDimensions::TwoDimensional,
format: None,
multisampled: false,
array_layers: DescriptorImageDescArray::NonArrayed,
}),
array_count: 1u32,
stages: self.0.clone(),
readonly: true,
}),
_ => None,
}
} The glsl source for these is: layout(binding = 0) uniform sampler2DArray gbuffer_diffuse;
layout(binding = 1) uniform sampler2D ssao_buffer; The second command has 6 descriptors in total and I only gave the first two in my post 30 minutes before (for readability). However, as you may guess, the same image (and the same sampler object) is bound to the descriptor binding 0 in both draw commands. |
The only thing left that I see, that could be causing this, is the code for handling image layout transitions. If the image is initialised, but not in the correct layout for a command, then a transition is inserted before the command, and this counts as exclusive access: https://github.com/vulkano-rs/vulkano/blob/master/vulkano/src/command_buffer/synced/base.rs#L736 |
This has to be the case here! I just inserted some more [.../vulkano/vulkano/src/command_buffer/synced/base.rs:556] entry.get() = ResourceState {
memory: PipelineMemoryAccess {
stages: PipelineStages {
top_of_pipe: false,
draw_indirect: false,
vertex_input: false,
vertex_shader: false,
tessellation_control_shader: false,
tessellation_evaluation_shader: false,
geometry_shader: false,
fragment_shader: true,
early_fragment_tests: false,
late_fragment_tests: false,
color_attachment_output: false,
compute_shader: false,
transfer: false,
bottom_of_pipe: false,
host: false,
all_graphics: false,
all_commands: false,
},
access: AccessFlagBits {
indirect_command_read: false,
index_read: false,
vertex_attribute_read: false,
uniform_read: false,
input_attachment_read: false,
shader_read: true,
shader_write: false,
color_attachment_read: false,
color_attachment_write: false,
depth_stencil_attachment_read: false,
depth_stencil_attachment_write: false,
transfer_read: false,
transfer_write: false,
host_read: false,
host_write: false,
memory_read: false,
memory_write: false,
},
exclusive: true,
},
exclusive_any: true,
initial_layout: ColorAttachmentOptimal,
current_layout: ShaderReadOnlyOptimal,
} |
But why is this transition happening? |
The code at https://github.com/vulkano-rs/vulkano/blob/master/vulkano/src/command_buffer/synced/commands.rs#L2777-L2796 is what chooses the layout for an image, and it does so based on the descriptor type. Since you're using a combined image sampler descriptor, it chooses the layout that the image returns for combined image samplers. The image has control over this though, so if you made your own custom image, then you should look at how you implemented |
I just copied the implementation from vulkanos So the error must be somewhere else. |
I've also changed my code to the following: Now I issue two draw commands, but both with the same pipeline (of course same descriptor set layout) but different descriptor sets (I create a new one for each draw call). I keep getting the same error. This is the only place in my code, I believe, where I use an |
Wow, this really fixed it. So the problem really is drawing with the same image in two different descriptor sets. |
Could this have something to do with the new |
However, what I do see is that What I see happening here is that |
I managed to reproduce the issue with vulkano master and a somewhat minimal example. To view it, please checkout my fork at https://github.com/faulesocke/vulkano/tree/bug then switch to the Now I am absolutely certain that this has nothing to do with my custom version of the |
Thank you, that will help a lot. I'll have a look soon. |
No hurry. I will investigate it further as well. Already learned a lot about the vulkano internals. |
Okay, it looks like the logic is somewhat fundamentally broken here. First, let me explain why it works when I only have one descriptor set: In this case no second Now why it doesn't work with two different sets:
In this case the Now when the second call to However this is actually not true. The image is already in the desired layout because of the previously inserted barrier. No further barriers are required. The code then tries to insert further barriers to resolve the conflict but before this makes one important check in https://github.com/vulkano-rs/vulkano/blob/master/vulkano/src/command_buffer/synced/base.rs#L595: When the command, which caused the In my opinion, this should be fixed by not setting the |
Nice investigation work! Unfortunately, I don't know why it was made this way. Most of Vulkano was written by Tomaka, who is unfortunately no longer an active contributor. I've done some work on The subtleties of Vulkan synchronisation are also notoriously difficult. You mention that the layout-transitioning barrier already acts as a write + barrier combination, so that anything that comes after will always see the image in the right layout. If that's the case, to what degree is a layout transition considered exclusive? On one side, it has a barrier built in, so I assume it doesn't conflict with operations on either side of the barrier. On the other side though, it does write the image, so if the image is accessed concurrently on another queue then that is definitely a conflict. Barriers only protect on a single queue. There's a lot that I need to figure out before I fully understand how this is supposed to work. But your research helps a lot. And if you manage to make a PR that would be even better! |
Is this still a problem or can it be closed? |
With 0.22 I get a lot of validation errors when recording draw commands. The offending code is always similar to this:
i.e. some loop that records draw commands and re-uses the same uniform buffer(s) over and over again. The error is always of the form
The error is returned by the
draw_indexed
call.This code worked in 0.21 but stopped working when I upgraded to 0.22. I tried upgrading to 0.22 because I had similar issues (also conflicts but with images instead of buffers and only in a new piece of code that isn't involved here) and thought the overhauled image code in 0.22 could solve my problems. But now I have buffer problems :D
Is there already a fix for this? I'm also fine with patching up vulkano myself and just remove some validation code for now. Would be nice if someone can give me a hint where this could come from.
You can probably reproduce this issue when porting the examples to 0.22.
The text was updated successfully, but these errors were encountered: