mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2025-02-16 17:12:29 +00:00
Remove DescriptorSetBuilder
, use descriptor writes directly (#1774)
* Remove DescriptorSetBuilder, use descriptor writes directly * Merge two error types
This commit is contained in:
parent
974087c0f4
commit
2151697af0
@ -15,7 +15,7 @@
|
||||
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{WriteDescriptorSet, PersistentDescriptorSet};
|
||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||
use vulkano::device::{Device, DeviceExtensions, Features};
|
||||
use vulkano::instance::{Instance, InstanceExtensions};
|
||||
@ -148,11 +148,11 @@ fn main() {
|
||||
// If you want to run the pipeline on multiple different buffers, you need to create multiple
|
||||
// descriptor sets that each contain the buffer you want to run the shader on.
|
||||
let layout = pipeline.layout().descriptor_set_layouts().get(0).unwrap();
|
||||
let mut set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
set_builder.add_buffer(data_buffer.clone()).unwrap();
|
||||
|
||||
let set = set_builder.build().unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[WriteDescriptorSet::buffer(0, data_buffer.clone())],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// In order to execute our operation, we have to build a command buffer.
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
|
@ -12,7 +12,7 @@ use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, SecondaryAutoCommandBuffer,
|
||||
};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{WriteDescriptorSet, PersistentDescriptorSet};
|
||||
use vulkano::device::Queue;
|
||||
use vulkano::image::ImageViewAbstract;
|
||||
use vulkano::pipeline::graphics::color_blend::{
|
||||
@ -118,11 +118,11 @@ impl AmbientLightingSystem {
|
||||
.descriptor_set_layouts()
|
||||
.get(0)
|
||||
.unwrap();
|
||||
let mut descriptor_set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
descriptor_set_builder.add_image(color_input).unwrap();
|
||||
|
||||
let descriptor_set = descriptor_set_builder.build().unwrap();
|
||||
let descriptor_set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[WriteDescriptorSet::image_view(0, color_input)],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let viewport = Viewport {
|
||||
origin: [0.0, 0.0],
|
||||
|
@ -13,7 +13,7 @@ use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, SecondaryAutoCommandBuffer,
|
||||
};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{WriteDescriptorSet, PersistentDescriptorSet};
|
||||
use vulkano::device::Queue;
|
||||
use vulkano::image::ImageViewAbstract;
|
||||
use vulkano::pipeline::graphics::color_blend::{
|
||||
@ -129,15 +129,14 @@ impl DirectionalLightingSystem {
|
||||
.descriptor_set_layouts()
|
||||
.get(0)
|
||||
.unwrap();
|
||||
let mut descriptor_set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
descriptor_set_builder
|
||||
.add_image(color_input)
|
||||
.unwrap()
|
||||
.add_image(normals_input)
|
||||
.unwrap();
|
||||
|
||||
let descriptor_set = descriptor_set_builder.build().unwrap();
|
||||
let descriptor_set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[
|
||||
WriteDescriptorSet::image_view(0, color_input),
|
||||
WriteDescriptorSet::image_view(1, normals_input),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let viewport = Viewport {
|
||||
origin: [0.0, 0.0],
|
||||
|
@ -13,7 +13,7 @@ use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, SecondaryAutoCommandBuffer,
|
||||
};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{WriteDescriptorSet, PersistentDescriptorSet};
|
||||
use vulkano::device::Queue;
|
||||
use vulkano::image::ImageViewAbstract;
|
||||
use vulkano::pipeline::graphics::color_blend::{
|
||||
@ -140,17 +140,15 @@ impl PointLightingSystem {
|
||||
.descriptor_set_layouts()
|
||||
.get(0)
|
||||
.unwrap();
|
||||
let mut descriptor_set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
descriptor_set_builder
|
||||
.add_image(color_input)
|
||||
.unwrap()
|
||||
.add_image(normals_input)
|
||||
.unwrap()
|
||||
.add_image(depth_input)
|
||||
.unwrap();
|
||||
|
||||
let descriptor_set = descriptor_set_builder.build().unwrap();
|
||||
let descriptor_set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[
|
||||
WriteDescriptorSet::image_view(0, color_input),
|
||||
WriteDescriptorSet::image_view(1, normals_input),
|
||||
WriteDescriptorSet::image_view(2, depth_input),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let viewport = Viewport {
|
||||
origin: [0.0, 0.0],
|
||||
|
@ -17,7 +17,7 @@
|
||||
use std::mem;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor_set::{DescriptorSet, PersistentDescriptorSet};
|
||||
use vulkano::descriptor_set::{DescriptorSet, WriteDescriptorSet, PersistentDescriptorSet};
|
||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||
use vulkano::device::{Device, DeviceExtensions, Features};
|
||||
use vulkano::instance::{Instance, InstanceExtensions};
|
||||
@ -155,15 +155,14 @@ fn main() {
|
||||
.unwrap();
|
||||
|
||||
let layout = pipeline.layout().descriptor_set_layouts().get(0).unwrap();
|
||||
let mut set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
set_builder
|
||||
.add_buffer(input_buffer.clone())
|
||||
.unwrap()
|
||||
.add_buffer(output_buffer.clone())
|
||||
.unwrap();
|
||||
|
||||
let set = set_builder.build().unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[
|
||||
WriteDescriptorSet::buffer(0, input_buffer.clone()),
|
||||
WriteDescriptorSet::buffer(1, output_buffer.clone()),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Build the command buffer, using different offsets for each call.
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
|
@ -19,7 +19,7 @@ use std::io::BufWriter;
|
||||
use std::path::Path;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{WriteDescriptorSet, PersistentDescriptorSet};
|
||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||
use vulkano::device::{Device, DeviceExtensions, Features};
|
||||
use vulkano::format::Format;
|
||||
@ -196,11 +196,11 @@ fn main() {
|
||||
let view = ImageView::new(image.clone()).unwrap();
|
||||
|
||||
let layout = pipeline.layout().descriptor_set_layouts().get(0).unwrap();
|
||||
let mut set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
set_builder.add_image(view.clone()).unwrap();
|
||||
|
||||
let set = set_builder.build().unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[WriteDescriptorSet::image_view(0, view.clone())],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let buf = CpuAccessibleBuffer::from_iter(
|
||||
device.clone(),
|
||||
|
@ -18,7 +18,7 @@ use vulkano::{
|
||||
submit::SubmitCommandBufferBuilder, AutoCommandBufferBuilder, CommandBufferUsage,
|
||||
SubpassContents,
|
||||
},
|
||||
descriptor_set::PersistentDescriptorSet,
|
||||
descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
Device, DeviceExtensions, Queue,
|
||||
@ -173,13 +173,15 @@ fn main() {
|
||||
|
||||
let layout = pipeline.layout().descriptor_set_layouts().get(0).unwrap();
|
||||
|
||||
let mut set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
set_builder
|
||||
.add_sampled_image(image_view, sampler.clone())
|
||||
.unwrap();
|
||||
|
||||
let set = set_builder.build().unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[WriteDescriptorSet::image_view_sampler(
|
||||
0,
|
||||
image_view,
|
||||
sampler.clone(),
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut recreate_swapchain = false;
|
||||
let mut previous_frame_end: Option<Box<dyn GpuFuture>> = Some(Box::new(now(device.clone())));
|
||||
|
@ -12,7 +12,7 @@ use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet};
|
||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||
use vulkano::device::{Device, DeviceExtensions, Features};
|
||||
use vulkano::format::Format;
|
||||
@ -205,13 +205,15 @@ fn main() {
|
||||
.unwrap();
|
||||
|
||||
let layout = pipeline.layout().descriptor_set_layouts().get(0).unwrap();
|
||||
let mut set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
set_builder
|
||||
.add_sampled_image(texture.clone(), sampler.clone())
|
||||
.unwrap();
|
||||
|
||||
let set = set_builder.build().unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[WriteDescriptorSet::image_view_sampler(
|
||||
0,
|
||||
texture.clone(),
|
||||
sampler.clone(),
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut viewport = Viewport {
|
||||
origin: [0.0, 0.0],
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, ImmutableBuffer};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet};
|
||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||
use vulkano::device::{Device, DeviceExtensions, Features};
|
||||
use vulkano::instance::{Instance, InstanceExtensions};
|
||||
@ -145,16 +145,15 @@ void main() {
|
||||
};
|
||||
|
||||
let layout = pipeline.layout().descriptor_set_layouts().get(0).unwrap();
|
||||
let mut set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
set_builder
|
||||
.add_buffer(data_buffer.clone())
|
||||
.unwrap()
|
||||
// Now you can just add immutable buffer like other buffers.
|
||||
.add_buffer(immutable_data_buffer.clone())
|
||||
.unwrap();
|
||||
|
||||
let set = set_builder.build().unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[
|
||||
WriteDescriptorSet::buffer(0, data_buffer.clone()),
|
||||
// Now you can just add immutable buffer like other buffers.
|
||||
WriteDescriptorSet::buffer(1, immutable_data_buffer.clone()),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
|
@ -21,7 +21,7 @@ use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{WriteDescriptorSet, PersistentDescriptorSet};
|
||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||
use vulkano::device::{Device, DeviceExtensions, Features};
|
||||
use vulkano::format::Format;
|
||||
@ -215,12 +215,13 @@ fn main() {
|
||||
.unwrap();
|
||||
|
||||
let layout = pipeline.layout().descriptor_set_layouts().get(0).unwrap();
|
||||
let mut set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
// Use `add_image` instead of `add_sampled_image`, since the sampler is already in the layout.
|
||||
set_builder.add_image(texture.clone()).unwrap();
|
||||
|
||||
let set = set_builder.build().unwrap();
|
||||
// Use `image_view` instead of `image_view_sampler`, since the sampler is already in the layout.
|
||||
let set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[WriteDescriptorSet::image_view(0, texture.clone())],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut viewport = Viewport {
|
||||
origin: [0.0, 0.0],
|
||||
|
@ -36,7 +36,7 @@ use vulkano::buffer::{BufferUsage, CpuBufferPool};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DrawIndirectCommand, SubpassContents,
|
||||
};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet};
|
||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||
use vulkano::device::{Device, DeviceExtensions, Features};
|
||||
use vulkano::image::view::ImageView;
|
||||
@ -330,15 +330,14 @@ fn main() {
|
||||
.descriptor_set_layouts()
|
||||
.get(0)
|
||||
.unwrap();
|
||||
let mut cs_desciptor_set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
cs_desciptor_set_builder
|
||||
.add_buffer(vertices.clone())
|
||||
.unwrap()
|
||||
.add_buffer(indirect_args.clone())
|
||||
.unwrap();
|
||||
|
||||
let cs_desciptor_set = cs_desciptor_set_builder.build().unwrap();
|
||||
let cs_desciptor_set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[
|
||||
WriteDescriptorSet::buffer(0, vertices.clone()),
|
||||
WriteDescriptorSet::buffer(1, indirect_args.clone()),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
|
@ -14,7 +14,7 @@ use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
|
||||
use vulkano::command_buffer::PrimaryCommandBuffer;
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{WriteDescriptorSet, PersistentDescriptorSet};
|
||||
use vulkano::device::Queue;
|
||||
use vulkano::image::ImageAccess;
|
||||
use vulkano::pipeline::{ComputePipeline, Pipeline, PipelineBindPoint};
|
||||
@ -98,13 +98,14 @@ impl FractalComputePipeline {
|
||||
let img_dims = image.image().dimensions().width_height();
|
||||
let pipeline_layout = self.pipeline.layout();
|
||||
let desc_layout = pipeline_layout.descriptor_set_layouts().get(0).unwrap();
|
||||
let mut desc_set_builder = PersistentDescriptorSet::start(desc_layout.clone());
|
||||
desc_set_builder
|
||||
.add_image(image.clone())
|
||||
.unwrap()
|
||||
.add_buffer(self.palette.clone())
|
||||
.unwrap();
|
||||
let set = desc_set_builder.build().unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
desc_layout.clone(),
|
||||
[
|
||||
WriteDescriptorSet::image_view(0, image.clone()),
|
||||
WriteDescriptorSet::buffer(1, self.palette.clone()),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
self.gfx_queue.device().clone(),
|
||||
self.gfx_queue.family(),
|
||||
|
@ -12,7 +12,7 @@ use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, SecondaryAutoCommandBuffer,
|
||||
};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{WriteDescriptorSet, PersistentDescriptorSet};
|
||||
use vulkano::device::Queue;
|
||||
use vulkano::image::ImageViewAbstract;
|
||||
use vulkano::pipeline::graphics::input_assembly::InputAssemblyState;
|
||||
@ -126,11 +126,15 @@ impl PixelsDrawPipeline {
|
||||
0.0,
|
||||
)
|
||||
.unwrap();
|
||||
let mut desc_set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
desc_set_builder
|
||||
.add_sampled_image(image.clone(), sampler)
|
||||
.unwrap();
|
||||
desc_set_builder.build().unwrap()
|
||||
PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[WriteDescriptorSet::image_view_sampler(
|
||||
0,
|
||||
image.clone(),
|
||||
sampler,
|
||||
)],
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Draw input `image` over a quad of size -1.0 to 1.0
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet};
|
||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||
use vulkano::device::{Device, DeviceExtensions, Features};
|
||||
use vulkano::instance::{Instance, InstanceExtensions};
|
||||
@ -106,11 +106,11 @@ fn main() {
|
||||
};
|
||||
|
||||
let layout = pipeline.layout().descriptor_set_layouts().get(0).unwrap();
|
||||
let mut set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
set_builder.add_buffer(data_buffer.clone()).unwrap();
|
||||
|
||||
let set = set_builder.build().unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[WriteDescriptorSet::buffer(0, data_buffer.clone())],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The `vulkano_shaders::shaders!` macro generates a struct with the correct representation of the push constants struct specified in the shader.
|
||||
// Here we create an instance of the generated struct.
|
||||
|
@ -12,7 +12,7 @@ use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents};
|
||||
use vulkano::descriptor_set::DescriptorSetBuilder;
|
||||
use vulkano::descriptor_set::WriteDescriptorSet;
|
||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||
use vulkano::device::{Device, DeviceExtensions, Features};
|
||||
use vulkano::format::Format;
|
||||
@ -276,12 +276,12 @@ fn main() {
|
||||
.unwrap()
|
||||
.set_viewport(0, [viewport.clone()])
|
||||
.bind_pipeline_graphics(pipeline.clone())
|
||||
.push_descriptor_set(PipelineBindPoint::Graphics, pipeline.layout().clone(), 0, {
|
||||
let layout = pipeline.layout().descriptor_set_layouts().get(0).unwrap();
|
||||
let mut set_builder = DescriptorSetBuilder::start(layout.clone());
|
||||
set_builder.add_image(texture.clone()).unwrap();
|
||||
set_builder.build().unwrap()
|
||||
})
|
||||
.push_descriptor_set(
|
||||
PipelineBindPoint::Graphics,
|
||||
pipeline.layout().clone(),
|
||||
0,
|
||||
[WriteDescriptorSet::image_view(0, texture.clone())],
|
||||
)
|
||||
.bind_vertex_buffers(0, vertex_buffer.clone())
|
||||
.draw(vertex_buffer.len() as u32, 1, 0, 0)
|
||||
.unwrap()
|
||||
|
@ -15,7 +15,7 @@ use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, Subp
|
||||
use vulkano::descriptor_set::layout::{
|
||||
DescriptorSetDesc, DescriptorSetLayout, DescriptorSetLayoutError,
|
||||
};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet};
|
||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||
use vulkano::device::{Device, DeviceExtensions, Features};
|
||||
use vulkano::format::Format;
|
||||
@ -318,19 +318,19 @@ fn main() {
|
||||
.unwrap();
|
||||
|
||||
let layout = pipeline.layout().descriptor_set_layouts().get(0).unwrap();
|
||||
let mut set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
set_builder
|
||||
.enter_array()
|
||||
.unwrap()
|
||||
.add_sampled_image(mascot_texture.clone(), sampler.clone())
|
||||
.unwrap()
|
||||
.add_sampled_image(vulkano_texture.clone(), sampler.clone())
|
||||
.unwrap()
|
||||
.leave_array()
|
||||
.unwrap();
|
||||
|
||||
let set = set_builder.build().unwrap();
|
||||
let set = PersistentDescriptorSet::new_variable(
|
||||
layout.clone(),
|
||||
2,
|
||||
[WriteDescriptorSet::image_view_sampler_array(
|
||||
0,
|
||||
0,
|
||||
[
|
||||
(mascot_texture.clone() as _, sampler.clone()),
|
||||
(vulkano_texture.clone() as _, sampler.clone()),
|
||||
],
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut viewport = Viewport {
|
||||
origin: [0.0, 0.0],
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet};
|
||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||
use vulkano::device::{Device, DeviceExtensions, Features};
|
||||
use vulkano::instance::{Instance, InstanceExtensions};
|
||||
@ -108,11 +108,11 @@ fn main() {
|
||||
};
|
||||
|
||||
let layout = pipeline.layout().descriptor_set_layouts().get(0).unwrap();
|
||||
let mut set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
set_builder.add_buffer(data_buffer.clone()).unwrap();
|
||||
|
||||
let set = set_builder.build().unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[WriteDescriptorSet::buffer(0, data_buffer.clone())],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
|
@ -30,7 +30,7 @@
|
||||
use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet};
|
||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||
use vulkano::device::{Device, DeviceExtensions, Features, Queue};
|
||||
use vulkano::instance::{Instance, InstanceExtensions};
|
||||
@ -172,11 +172,11 @@ fn main() {
|
||||
parameters: shaders::ty::Parameters,
|
||||
) {
|
||||
let layout = pipeline.layout().descriptor_set_layouts().get(0).unwrap();
|
||||
let mut set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
set_builder.add_buffer(data_buffer.clone()).unwrap();
|
||||
|
||||
let set = set_builder.build().unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[WriteDescriptorSet::buffer(0, data_buffer.clone())],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
queue.device().clone(),
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{WriteDescriptorSet, PersistentDescriptorSet};
|
||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||
use vulkano::device::{Device, DeviceExtensions, Features};
|
||||
use vulkano::instance::{Instance, InstanceExtensions};
|
||||
@ -110,11 +110,11 @@ fn main() {
|
||||
};
|
||||
|
||||
let layout = pipeline.layout().descriptor_set_layouts().get(0).unwrap();
|
||||
let mut set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
set_builder.add_buffer(data_buffer.clone()).unwrap();
|
||||
|
||||
let set = set_builder.build().unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[WriteDescriptorSet::buffer(0, data_buffer.clone())],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
|
@ -14,7 +14,7 @@ use std::time::Instant;
|
||||
use vulkano::buffer::cpu_pool::CpuBufferPool;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{WriteDescriptorSet, PersistentDescriptorSet};
|
||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||
use vulkano::device::{Device, DeviceExtensions, Features};
|
||||
use vulkano::format::Format;
|
||||
@ -223,11 +223,11 @@ fn main() {
|
||||
};
|
||||
|
||||
let layout = pipeline.layout().descriptor_set_layouts().get(0).unwrap();
|
||||
let mut set_builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
set_builder.add_buffer(uniform_buffer_subbuffer).unwrap();
|
||||
|
||||
let set = set_builder.build().unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[WriteDescriptorSet::buffer(0, uniform_buffer_subbuffer)],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let (image_num, suboptimal, acquire_future) =
|
||||
match swapchain::acquire_next_image(swapchain.clone(), None) {
|
||||
|
@ -238,7 +238,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe trait BufferViewAbstract: Send + Sync {
|
||||
pub unsafe trait BufferViewAbstract: DeviceOwned + Send + Sync {
|
||||
/// Returns the inner handle used by this buffer view.
|
||||
fn inner(&self) -> ash::vk::BufferView;
|
||||
|
||||
|
@ -37,8 +37,7 @@ use crate::command_buffer::ImageUninitializedSafe;
|
||||
use crate::command_buffer::PrimaryCommandBuffer;
|
||||
use crate::command_buffer::SecondaryCommandBuffer;
|
||||
use crate::command_buffer::SubpassContents;
|
||||
use crate::descriptor_set::builder::DescriptorSetBuilderOutput;
|
||||
use crate::descriptor_set::DescriptorSetsCollection;
|
||||
use crate::descriptor_set::{check_descriptor_write, DescriptorSetsCollection, WriteDescriptorSet};
|
||||
use crate::device::physical::QueueFamily;
|
||||
use crate::device::Device;
|
||||
use crate::device::DeviceOwned;
|
||||
@ -1758,12 +1757,13 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// [`khr_push_descriptor`](crate::device::DeviceExtensions::khr_push_descriptor)
|
||||
/// extension is not enabled on the device.
|
||||
/// - Panics if `set_num` is not less than the number of sets in `pipeline_layout`.
|
||||
/// - Panics if an element of `descriptor_writes` is not compatible with `pipeline_layout`.
|
||||
pub fn push_descriptor_set(
|
||||
&mut self,
|
||||
pipeline_bind_point: PipelineBindPoint,
|
||||
pipeline_layout: Arc<PipelineLayout>,
|
||||
set_num: u32,
|
||||
descriptor_writes: DescriptorSetBuilderOutput, // TODO: make partial writes possible
|
||||
descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>,
|
||||
) -> &mut Self {
|
||||
match pipeline_bind_point {
|
||||
PipelineBindPoint::Compute => assert!(
|
||||
@ -1785,12 +1785,12 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
"the descriptor set slot being bound must be less than the number of sets in pipeline_layout"
|
||||
);
|
||||
|
||||
let pipeline_set = &pipeline_layout.descriptor_set_layouts()[set_num as usize];
|
||||
assert!(
|
||||
pipeline_set.is_compatible_with(descriptor_writes.layout()),
|
||||
"descriptor_writes is not compatible with slot {} in pipeline_layout",
|
||||
set_num as usize,
|
||||
);
|
||||
let descriptor_writes: SmallVec<[_; 8]> = descriptor_writes.into_iter().collect();
|
||||
let descriptor_set_layout = &pipeline_layout.descriptor_set_layouts()[set_num as usize];
|
||||
|
||||
for write in &descriptor_writes {
|
||||
check_descriptor_write(write, descriptor_set_layout, 0).unwrap();
|
||||
}
|
||||
|
||||
unsafe {
|
||||
self.inner.push_descriptor_set(
|
||||
|
@ -25,10 +25,10 @@ use crate::command_buffer::CommandBufferExecError;
|
||||
use crate::command_buffer::ImageUninitializedSafe;
|
||||
use crate::command_buffer::SecondaryCommandBuffer;
|
||||
use crate::command_buffer::SubpassContents;
|
||||
use crate::descriptor_set::builder::DescriptorSetBuilderOutput;
|
||||
use crate::descriptor_set::layout::DescriptorType;
|
||||
use crate::descriptor_set::DescriptorBindingResources;
|
||||
use crate::descriptor_set::DescriptorSetWithOffsets;
|
||||
use crate::descriptor_set::WriteDescriptorSet;
|
||||
use crate::format::ClearValue;
|
||||
use crate::image::ImageAccess;
|
||||
use crate::image::ImageLayout;
|
||||
@ -1531,13 +1531,13 @@ impl SyncCommandBufferBuilder {
|
||||
pipeline_bind_point: PipelineBindPoint,
|
||||
pipeline_layout: Arc<PipelineLayout>,
|
||||
set_num: u32,
|
||||
descriptor_writes: DescriptorSetBuilderOutput,
|
||||
descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>,
|
||||
) {
|
||||
struct Cmd {
|
||||
pipeline_bind_point: PipelineBindPoint,
|
||||
pipeline_layout: Arc<PipelineLayout>,
|
||||
set_num: u32,
|
||||
descriptor_writes: DescriptorSetBuilderOutput,
|
||||
descriptor_writes: SmallVec<[WriteDescriptorSet; 8]>,
|
||||
}
|
||||
|
||||
impl Command for Cmd {
|
||||
@ -1550,11 +1550,14 @@ impl SyncCommandBufferBuilder {
|
||||
self.pipeline_bind_point,
|
||||
&self.pipeline_layout,
|
||||
self.set_num,
|
||||
self.descriptor_writes.writes(),
|
||||
&self.descriptor_writes,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let descriptor_writes: SmallVec<[WriteDescriptorSet; 8]> =
|
||||
descriptor_writes.into_iter().collect();
|
||||
|
||||
let state = self.current_state.invalidate_descriptor_sets(
|
||||
pipeline_bind_point,
|
||||
pipeline_layout.clone(),
|
||||
@ -1572,7 +1575,10 @@ impl SyncCommandBufferBuilder {
|
||||
SetOrPush::Push(set_resources) => set_resources,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
set_resources.update(descriptor_writes.writes());
|
||||
|
||||
for write in &descriptor_writes {
|
||||
set_resources.update(write);
|
||||
}
|
||||
|
||||
self.append_command(
|
||||
Cmd {
|
||||
@ -2632,7 +2638,7 @@ impl SyncCommandBufferBuilder {
|
||||
.binding(binding)
|
||||
.unwrap()
|
||||
{
|
||||
DescriptorBindingResources::None => continue,
|
||||
DescriptorBindingResources::None(_) => continue,
|
||||
DescriptorBindingResources::Buffer(elements) => {
|
||||
resources.extend(elements.iter().flatten().cloned().map(buffer_resource));
|
||||
}
|
||||
|
@ -492,6 +492,7 @@ mod tests {
|
||||
use crate::descriptor_set::layout::DescriptorSetLayout;
|
||||
use crate::descriptor_set::layout::DescriptorType;
|
||||
use crate::descriptor_set::PersistentDescriptorSet;
|
||||
use crate::descriptor_set::WriteDescriptorSet;
|
||||
use crate::device::Device;
|
||||
use crate::pipeline::layout::PipelineLayout;
|
||||
use crate::pipeline::PipelineBindPoint;
|
||||
@ -682,13 +683,14 @@ mod tests {
|
||||
PipelineLayout::new(device.clone(), [set_layout.clone(), set_layout.clone()], [])
|
||||
.unwrap();
|
||||
|
||||
let set = {
|
||||
let mut builder = PersistentDescriptorSet::start(set_layout.clone());
|
||||
builder
|
||||
.add_sampler(Sampler::simple_repeat_linear(device.clone()))
|
||||
.unwrap();
|
||||
builder.build().unwrap()
|
||||
};
|
||||
let set = PersistentDescriptorSet::new(
|
||||
set_layout.clone(),
|
||||
[WriteDescriptorSet::sampler(
|
||||
0,
|
||||
Sampler::simple_repeat_linear(device.clone()),
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut set_builder = sync.bind_descriptor_sets();
|
||||
set_builder.add(set.clone());
|
||||
@ -734,13 +736,14 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let set = {
|
||||
let mut builder = PersistentDescriptorSet::start(set_layout.clone());
|
||||
builder
|
||||
.add_sampler(Sampler::simple_repeat_linear(device.clone()))
|
||||
.unwrap();
|
||||
builder.build().unwrap()
|
||||
};
|
||||
let set = PersistentDescriptorSet::new(
|
||||
set_layout.clone(),
|
||||
[WriteDescriptorSet::sampler(
|
||||
0,
|
||||
Sampler::simple_repeat_linear(device.clone()),
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut set_builder = sync.bind_descriptor_sets();
|
||||
set_builder.add(set);
|
||||
|
@ -17,9 +17,8 @@ use crate::command_buffer::CommandBufferLevel;
|
||||
use crate::command_buffer::CommandBufferUsage;
|
||||
use crate::command_buffer::SecondaryCommandBuffer;
|
||||
use crate::command_buffer::SubpassContents;
|
||||
use crate::descriptor_set::sys::DescriptorWrite;
|
||||
use crate::descriptor_set::sys::DescriptorWriteInfo;
|
||||
use crate::descriptor_set::sys::UnsafeDescriptorSet;
|
||||
use crate::descriptor_set::{DescriptorWriteInfo, WriteDescriptorSet};
|
||||
use crate::device::Device;
|
||||
use crate::device::DeviceOwned;
|
||||
use crate::format::ClearValue;
|
||||
@ -1356,24 +1355,20 @@ impl UnsafeCommandBufferBuilder {
|
||||
///
|
||||
/// If the list is empty then the command is automatically ignored.
|
||||
#[inline]
|
||||
pub unsafe fn push_descriptor_set(
|
||||
pub unsafe fn push_descriptor_set<'a>(
|
||||
&mut self,
|
||||
pipeline_bind_point: PipelineBindPoint,
|
||||
pipeline_layout: &PipelineLayout,
|
||||
set_num: u32,
|
||||
descriptor_writes: &[DescriptorWrite],
|
||||
descriptor_writes: impl IntoIterator<Item = &'a WriteDescriptorSet>,
|
||||
) {
|
||||
debug_assert!(self.device().enabled_extensions().khr_push_descriptor);
|
||||
|
||||
if descriptor_writes.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let (infos, mut writes): (SmallVec<[_; 8]>, SmallVec<[_; 8]>) = descriptor_writes
|
||||
.into_iter()
|
||||
.map(|write| {
|
||||
let descriptor = pipeline_layout.descriptor_set_layouts()[set_num as usize]
|
||||
.descriptor(write.binding_num)
|
||||
.descriptor(write.binding())
|
||||
.unwrap();
|
||||
|
||||
(
|
||||
@ -1383,6 +1378,10 @@ impl UnsafeCommandBufferBuilder {
|
||||
})
|
||||
.unzip();
|
||||
|
||||
if writes.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the info pointers separately.
|
||||
for (info, write) in infos.iter().zip(writes.iter_mut()) {
|
||||
match info {
|
||||
|
@ -80,7 +80,7 @@ pub(in super::super) fn check_descriptor_sets_validity<'a, P: Pipeline>(
|
||||
let binding_resources = set_resources.binding(binding_num).unwrap();
|
||||
|
||||
match binding_resources {
|
||||
DescriptorBindingResources::None => (),
|
||||
DescriptorBindingResources::None(_) => (),
|
||||
DescriptorBindingResources::Buffer(elements) => {
|
||||
check_resources(set_num, binding_num, reqs, elements, |_| Ok(()))?;
|
||||
}
|
||||
|
@ -1,610 +0,0 @@
|
||||
// Copyright (c) 2017 The vulkano developers
|
||||
// Licensed under the Apache License, Version 2.0
|
||||
// <LICENSE-APACHE or
|
||||
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
|
||||
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
|
||||
// at your option. All files in the project carrying such
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use crate::buffer::{BufferAccess, BufferView};
|
||||
use crate::descriptor_set::layout::{DescriptorDesc, DescriptorType};
|
||||
use crate::descriptor_set::sys::DescriptorWrite;
|
||||
use crate::descriptor_set::{
|
||||
DescriptorSetError, DescriptorSetLayout, MissingBufferUsage, MissingImageUsage,
|
||||
};
|
||||
use crate::device::{Device, DeviceOwned};
|
||||
use crate::image::ImageViewAbstract;
|
||||
use crate::sampler::Sampler;
|
||||
use crate::VulkanObject;
|
||||
use std::sync::Arc;
|
||||
|
||||
struct BuilderDescriptor {
|
||||
desc: Option<DescriptorDesc>,
|
||||
array_element: u32,
|
||||
}
|
||||
|
||||
/// A builder for constructing a new descriptor set.
|
||||
pub struct DescriptorSetBuilder {
|
||||
layout: Arc<DescriptorSetLayout>,
|
||||
variable_descriptor_count: u32,
|
||||
writes: Vec<DescriptorWrite>,
|
||||
|
||||
cur_binding: u32,
|
||||
descriptors: Vec<BuilderDescriptor>,
|
||||
in_array: bool,
|
||||
poisoned: bool,
|
||||
}
|
||||
|
||||
impl DescriptorSetBuilder {
|
||||
/// Starts the process of building a descriptor set. Returns a builder.
|
||||
///
|
||||
/// # Panic
|
||||
///
|
||||
/// - Panics if the set id is out of range.
|
||||
pub fn start(layout: Arc<DescriptorSetLayout>) -> Self {
|
||||
let mut descriptors = Vec::with_capacity(layout.num_bindings() as usize);
|
||||
let mut desc_writes_capacity = 0;
|
||||
|
||||
for binding_i in 0..layout.num_bindings() {
|
||||
if let Some(desc) = layout.descriptor(binding_i) {
|
||||
desc_writes_capacity += desc.descriptor_count as usize;
|
||||
descriptors.push(BuilderDescriptor {
|
||||
desc: Some(desc),
|
||||
array_element: 0,
|
||||
});
|
||||
} else {
|
||||
descriptors.push(BuilderDescriptor {
|
||||
desc: None,
|
||||
array_element: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
layout,
|
||||
variable_descriptor_count: 0,
|
||||
writes: Vec::with_capacity(desc_writes_capacity),
|
||||
|
||||
cur_binding: 0,
|
||||
descriptors,
|
||||
in_array: false,
|
||||
poisoned: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Finalizes the building process and returns the generated output.
|
||||
pub fn build(self) -> Result<DescriptorSetBuilderOutput, DescriptorSetError> {
|
||||
if self.poisoned {
|
||||
return Err(DescriptorSetError::BuilderPoisoned);
|
||||
}
|
||||
|
||||
if self.in_array {
|
||||
return Err(DescriptorSetError::InArray);
|
||||
}
|
||||
|
||||
if self.cur_binding != self.descriptors.len() as u32 {
|
||||
return Err(DescriptorSetError::DescriptorsMissing {
|
||||
expected: self.descriptors.len() as u32,
|
||||
obtained: self.cur_binding,
|
||||
});
|
||||
} else {
|
||||
Ok(DescriptorSetBuilderOutput {
|
||||
layout: self.layout,
|
||||
writes: self.writes,
|
||||
variable_descriptor_count: self.variable_descriptor_count,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn poison_on_err(
|
||||
&mut self,
|
||||
func: impl FnOnce(&mut Self) -> Result<(), DescriptorSetError>,
|
||||
) -> Result<&mut Self, DescriptorSetError> {
|
||||
if self.poisoned {
|
||||
return Err(DescriptorSetError::BuilderPoisoned);
|
||||
}
|
||||
|
||||
match func(self) {
|
||||
Ok(()) => Ok(self),
|
||||
Err(err) => {
|
||||
self.poisoned = true;
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Call this function if the next element of the set is an array in order to set the value of
|
||||
/// each element.
|
||||
///
|
||||
/// This function can be called even if the descriptor isn't an array, and it is valid to enter
|
||||
/// the "array", add one element, then leave.
|
||||
pub fn enter_array(&mut self) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.poison_on_err(|builder| {
|
||||
if builder.in_array {
|
||||
Err(DescriptorSetError::InArray)
|
||||
} else if builder.cur_binding >= builder.descriptors.len() as u32 {
|
||||
Err(DescriptorSetError::TooManyDescriptors)
|
||||
} else if builder.descriptors[builder.cur_binding as usize]
|
||||
.desc
|
||||
.is_none()
|
||||
{
|
||||
Err(DescriptorSetError::DescriptorIsEmpty)
|
||||
} else {
|
||||
builder.in_array = true;
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Leaves the array. Call this once you added all the elements of the array.
|
||||
pub fn leave_array(&mut self) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.poison_on_err(|builder| {
|
||||
if !builder.in_array {
|
||||
Err(DescriptorSetError::NotInArray)
|
||||
} else {
|
||||
let descriptor = &builder.descriptors[builder.cur_binding as usize];
|
||||
let inner_desc = match descriptor.desc.as_ref() {
|
||||
Some(some) => some,
|
||||
None => unreachable!(),
|
||||
};
|
||||
|
||||
if inner_desc.variable_count {
|
||||
if descriptor.array_element > inner_desc.descriptor_count {
|
||||
return Err(DescriptorSetError::ArrayTooManyDescriptors {
|
||||
capacity: inner_desc.descriptor_count,
|
||||
obtained: descriptor.array_element,
|
||||
});
|
||||
}
|
||||
|
||||
debug_assert!(builder.cur_binding as usize == builder.descriptors.len() - 1);
|
||||
debug_assert!(builder.variable_descriptor_count == 0);
|
||||
builder.variable_descriptor_count = descriptor.array_element;
|
||||
} else if descriptor.array_element != inner_desc.descriptor_count {
|
||||
return Err(DescriptorSetError::ArrayLengthMismatch {
|
||||
expected: inner_desc.descriptor_count,
|
||||
obtained: descriptor.array_element,
|
||||
});
|
||||
}
|
||||
|
||||
builder.in_array = false;
|
||||
builder.cur_binding += 1;
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Skips the current descriptor if it is empty.
|
||||
pub fn add_empty(&mut self) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.poison_on_err(|builder| {
|
||||
// Should be unreachable as enter_array prevents entering an array for empty descriptors.
|
||||
debug_assert!(!builder.in_array);
|
||||
|
||||
if builder.descriptors[builder.cur_binding as usize]
|
||||
.desc
|
||||
.is_some()
|
||||
{
|
||||
return Err(DescriptorSetError::WrongDescriptorType);
|
||||
}
|
||||
|
||||
builder.cur_binding += 1;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Binds a buffer as the next descriptor or array element.
|
||||
pub fn add_buffer(
|
||||
&mut self,
|
||||
buffer: Arc<dyn BufferAccess>,
|
||||
) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.poison_on_err(|builder| {
|
||||
if buffer.inner().buffer.device().internal_object()
|
||||
!= builder.layout.device().internal_object()
|
||||
{
|
||||
return Err(DescriptorSetError::ResourceWrongDevice);
|
||||
}
|
||||
|
||||
let leave_array = if !builder.in_array {
|
||||
builder.enter_array()?;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let descriptor = &mut builder.descriptors[builder.cur_binding as usize];
|
||||
let inner_desc = match descriptor.desc.as_ref() {
|
||||
Some(some) => some,
|
||||
None => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
};
|
||||
|
||||
// Note that the buffer content is not checked. This is technically not unsafe as
|
||||
// long as the data in the buffer has no invalid memory representation (ie. no
|
||||
// bool, no enum, no pointer, no str) and as long as the robust buffer access
|
||||
// feature is enabled.
|
||||
// TODO: this is not checked ^
|
||||
|
||||
// TODO: eventually shouldn't be an assert ; for now robust_buffer_access is always
|
||||
// enabled so this assert should never fail in practice, but we put it anyway
|
||||
// in case we forget to adjust this code
|
||||
|
||||
match inner_desc.ty {
|
||||
DescriptorType::StorageBuffer | DescriptorType::StorageBufferDynamic => {
|
||||
assert!(
|
||||
builder
|
||||
.layout
|
||||
.device()
|
||||
.enabled_features()
|
||||
.robust_buffer_access
|
||||
);
|
||||
|
||||
if !buffer.inner().buffer.usage().storage_buffer {
|
||||
return Err(DescriptorSetError::MissingBufferUsage(
|
||||
MissingBufferUsage::StorageBuffer,
|
||||
));
|
||||
}
|
||||
}
|
||||
DescriptorType::UniformBuffer => {
|
||||
assert!(
|
||||
builder
|
||||
.layout
|
||||
.device()
|
||||
.enabled_features()
|
||||
.robust_buffer_access
|
||||
);
|
||||
|
||||
if !buffer.inner().buffer.usage().uniform_buffer {
|
||||
return Err(DescriptorSetError::MissingBufferUsage(
|
||||
MissingBufferUsage::UniformBuffer,
|
||||
));
|
||||
}
|
||||
}
|
||||
DescriptorType::UniformBufferDynamic => {
|
||||
assert!(
|
||||
builder
|
||||
.layout
|
||||
.device()
|
||||
.enabled_features()
|
||||
.robust_buffer_access
|
||||
);
|
||||
|
||||
if !buffer.inner().buffer.usage().uniform_buffer {
|
||||
return Err(DescriptorSetError::MissingBufferUsage(
|
||||
MissingBufferUsage::UniformBuffer,
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
}
|
||||
|
||||
unsafe {
|
||||
builder.writes.push(DescriptorWrite::buffer(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[buffer],
|
||||
));
|
||||
}
|
||||
|
||||
descriptor.array_element += 1;
|
||||
|
||||
if leave_array {
|
||||
builder.leave_array()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Binds a buffer view as the next descriptor or array element.
|
||||
pub fn add_buffer_view<B>(
|
||||
&mut self,
|
||||
view: Arc<BufferView<B>>,
|
||||
) -> Result<&mut Self, DescriptorSetError>
|
||||
where
|
||||
B: BufferAccess + 'static,
|
||||
{
|
||||
self.poison_on_err(|builder| {
|
||||
if view.device().internal_object() != builder.layout.device().internal_object() {
|
||||
return Err(DescriptorSetError::ResourceWrongDevice);
|
||||
}
|
||||
|
||||
let leave_array = if !builder.in_array {
|
||||
builder.enter_array()?;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let descriptor = &mut builder.descriptors[builder.cur_binding as usize];
|
||||
let inner_desc = match descriptor.desc.as_ref() {
|
||||
Some(some) => some,
|
||||
None => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
};
|
||||
|
||||
match inner_desc.ty {
|
||||
DescriptorType::StorageTexelBuffer => {
|
||||
// TODO: storage_texel_buffer_atomic
|
||||
|
||||
if !view.storage_texel_buffer() {
|
||||
return Err(DescriptorSetError::MissingBufferUsage(
|
||||
MissingBufferUsage::StorageTexelBuffer,
|
||||
));
|
||||
}
|
||||
}
|
||||
DescriptorType::UniformTexelBuffer => {
|
||||
if !view.uniform_texel_buffer() {
|
||||
return Err(DescriptorSetError::MissingBufferUsage(
|
||||
MissingBufferUsage::UniformTexelBuffer,
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
}
|
||||
|
||||
unsafe {
|
||||
builder.writes.push(DescriptorWrite::buffer_view(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[view as Arc<_>],
|
||||
));
|
||||
}
|
||||
|
||||
descriptor.array_element += 1;
|
||||
|
||||
if leave_array {
|
||||
builder.leave_array()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Binds an image view as the next descriptor or array element.
|
||||
pub fn add_image(
|
||||
&mut self,
|
||||
image_view: Arc<dyn ImageViewAbstract>,
|
||||
) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.poison_on_err(|builder| {
|
||||
if image_view.image().inner().image.device().internal_object()
|
||||
!= builder.layout.device().internal_object()
|
||||
{
|
||||
return Err(DescriptorSetError::ResourceWrongDevice);
|
||||
}
|
||||
|
||||
let leave_array = if !builder.in_array {
|
||||
builder.enter_array()?;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let descriptor = &mut builder.descriptors[builder.cur_binding as usize];
|
||||
let inner_desc = match descriptor.desc.as_ref() {
|
||||
Some(some) => some,
|
||||
None => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
};
|
||||
|
||||
match &inner_desc.ty {
|
||||
DescriptorType::CombinedImageSampler
|
||||
if !inner_desc.immutable_samplers.is_empty() =>
|
||||
{
|
||||
if !image_view.image().inner().image.usage().sampled {
|
||||
return Err(DescriptorSetError::MissingImageUsage(
|
||||
MissingImageUsage::Sampled,
|
||||
));
|
||||
}
|
||||
|
||||
if !image_view.can_be_sampled(
|
||||
&inner_desc.immutable_samplers[descriptor.array_element as usize],
|
||||
) {
|
||||
return Err(DescriptorSetError::IncompatibleImageViewSampler);
|
||||
}
|
||||
}
|
||||
DescriptorType::SampledImage => {
|
||||
if !image_view.image().inner().image.usage().sampled {
|
||||
return Err(DescriptorSetError::MissingImageUsage(
|
||||
MissingImageUsage::Sampled,
|
||||
));
|
||||
}
|
||||
}
|
||||
DescriptorType::StorageImage => {
|
||||
if !image_view.image().inner().image.usage().storage {
|
||||
return Err(DescriptorSetError::MissingImageUsage(
|
||||
MissingImageUsage::Storage,
|
||||
));
|
||||
}
|
||||
|
||||
if !image_view.component_mapping().is_identity() {
|
||||
return Err(DescriptorSetError::NotIdentitySwizzled);
|
||||
}
|
||||
}
|
||||
DescriptorType::InputAttachment => {
|
||||
if !image_view.image().inner().image.usage().input_attachment {
|
||||
return Err(DescriptorSetError::MissingImageUsage(
|
||||
MissingImageUsage::InputAttachment,
|
||||
));
|
||||
}
|
||||
|
||||
if !image_view.component_mapping().is_identity() {
|
||||
return Err(DescriptorSetError::NotIdentitySwizzled);
|
||||
}
|
||||
|
||||
let image_layers = image_view.array_layers();
|
||||
let num_layers = image_layers.end - image_layers.start;
|
||||
|
||||
if image_view.ty().is_arrayed() {
|
||||
return Err(DescriptorSetError::UnexpectedArrayed);
|
||||
}
|
||||
}
|
||||
_ => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
}
|
||||
|
||||
unsafe {
|
||||
builder.writes.push(DescriptorWrite::image_view(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[image_view],
|
||||
));
|
||||
}
|
||||
|
||||
descriptor.array_element += 1;
|
||||
|
||||
if leave_array {
|
||||
builder.leave_array()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Binds an image view with a sampler as the next descriptor or array element.
|
||||
///
|
||||
/// If the descriptor set layout contains immutable samplers for this descriptor, use
|
||||
/// `add_image` instead.
|
||||
pub fn add_sampled_image(
|
||||
&mut self,
|
||||
image_view: Arc<dyn ImageViewAbstract>,
|
||||
sampler: Arc<Sampler>,
|
||||
) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.poison_on_err(|builder| {
|
||||
if image_view.image().inner().image.device().internal_object()
|
||||
!= builder.layout.device().internal_object()
|
||||
{
|
||||
return Err(DescriptorSetError::ResourceWrongDevice);
|
||||
}
|
||||
|
||||
if sampler.device().internal_object() != builder.layout.device().internal_object() {
|
||||
return Err(DescriptorSetError::ResourceWrongDevice);
|
||||
}
|
||||
|
||||
if !image_view.image().inner().image.usage().sampled {
|
||||
return Err(DescriptorSetError::MissingImageUsage(
|
||||
MissingImageUsage::Sampled,
|
||||
));
|
||||
}
|
||||
|
||||
if !image_view.can_be_sampled(&sampler) {
|
||||
return Err(DescriptorSetError::IncompatibleImageViewSampler);
|
||||
}
|
||||
|
||||
let leave_array = if !builder.in_array {
|
||||
builder.enter_array()?;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let descriptor = &mut builder.descriptors[builder.cur_binding as usize];
|
||||
let inner_desc = match descriptor.desc.as_ref() {
|
||||
Some(some) => some,
|
||||
None => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
};
|
||||
|
||||
match &inner_desc.ty {
|
||||
DescriptorType::CombinedImageSampler => {
|
||||
if !inner_desc.immutable_samplers.is_empty() {
|
||||
return Err(DescriptorSetError::SamplerIsImmutable);
|
||||
}
|
||||
}
|
||||
_ => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
}
|
||||
|
||||
unsafe {
|
||||
builder.writes.push(DescriptorWrite::image_view_sampler(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[(image_view, sampler)],
|
||||
));
|
||||
}
|
||||
|
||||
descriptor.array_element += 1;
|
||||
|
||||
if leave_array {
|
||||
builder.leave_array()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Binds a sampler as the next descriptor or array element.
|
||||
pub fn add_sampler(&mut self, sampler: Arc<Sampler>) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.poison_on_err(|builder| {
|
||||
if sampler.device().internal_object() != builder.layout.device().internal_object() {
|
||||
return Err(DescriptorSetError::ResourceWrongDevice);
|
||||
}
|
||||
|
||||
let leave_array = if !builder.in_array {
|
||||
builder.enter_array()?;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let descriptor = &mut builder.descriptors[builder.cur_binding as usize];
|
||||
let inner_desc = match descriptor.desc.as_ref() {
|
||||
Some(some) => some,
|
||||
None => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
};
|
||||
|
||||
match &inner_desc.ty {
|
||||
DescriptorType::Sampler => {
|
||||
if !inner_desc.immutable_samplers.is_empty() {
|
||||
return Err(DescriptorSetError::SamplerIsImmutable);
|
||||
}
|
||||
}
|
||||
_ => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
}
|
||||
|
||||
unsafe {
|
||||
builder.writes.push(DescriptorWrite::sampler(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[sampler],
|
||||
));
|
||||
}
|
||||
|
||||
descriptor.array_element += 1;
|
||||
|
||||
if leave_array {
|
||||
builder.leave_array()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl DeviceOwned for DescriptorSetBuilder {
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.layout.device()
|
||||
}
|
||||
}
|
||||
|
||||
/// The output of the descriptor set builder.
|
||||
///
|
||||
/// This is not a descriptor set yet, but can be used to write the descriptors to one.
|
||||
pub struct DescriptorSetBuilderOutput {
|
||||
layout: Arc<DescriptorSetLayout>,
|
||||
variable_descriptor_count: u32,
|
||||
writes: Vec<DescriptorWrite>,
|
||||
}
|
||||
|
||||
impl DescriptorSetBuilderOutput {
|
||||
/// Returns the descriptor set layout.
|
||||
#[inline]
|
||||
pub fn layout(&self) -> &Arc<DescriptorSetLayout> {
|
||||
&self.layout
|
||||
}
|
||||
|
||||
/// Returns the number of variable descriptors.
|
||||
#[inline]
|
||||
pub fn variable_descriptor_count(&self) -> u32 {
|
||||
self.variable_descriptor_count
|
||||
}
|
||||
|
||||
/// Returns the descriptor writes.
|
||||
#[inline]
|
||||
pub fn writes(&self) -> &[DescriptorWrite] {
|
||||
&self.writes
|
||||
}
|
||||
}
|
@ -73,33 +73,35 @@
|
||||
//! - The `DescriptorSetsCollection` trait is implemented on collections of types that implement
|
||||
//! `DescriptorSet`. It is what you pass to the draw functions.
|
||||
|
||||
pub use self::builder::DescriptorSetBuilder;
|
||||
pub use self::collection::DescriptorSetsCollection;
|
||||
use self::layout::DescriptorSetLayout;
|
||||
pub use self::persistent::PersistentDescriptorSet;
|
||||
pub use self::resources::{DescriptorBindingResources, DescriptorSetResources};
|
||||
pub use self::single_layout_pool::SingleLayoutDescSetPool;
|
||||
use self::sys::UnsafeDescriptorSet;
|
||||
pub(crate) use self::update::{check_descriptor_write, DescriptorWriteInfo};
|
||||
pub use self::update::{DescriptorSetUpdateError, WriteDescriptorSet, WriteDescriptorSetElements};
|
||||
use crate::buffer::BufferAccess;
|
||||
use crate::buffer::BufferViewAbstract;
|
||||
use crate::descriptor_set::layout::DescriptorType;
|
||||
use crate::device::DeviceOwned;
|
||||
use crate::image::ImageViewAbstract;
|
||||
use crate::sampler::Sampler;
|
||||
use crate::OomError;
|
||||
use crate::VulkanObject;
|
||||
use smallvec::SmallVec;
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use fnv::FnvHashMap;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::hash::Hash;
|
||||
use std::hash::Hasher;
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub mod builder;
|
||||
mod collection;
|
||||
pub mod layout;
|
||||
pub mod persistent;
|
||||
pub mod pool;
|
||||
mod resources;
|
||||
pub mod single_layout_pool;
|
||||
pub mod sys;
|
||||
mod update;
|
||||
|
||||
/// Trait for objects that contain a collection of resources that will be accessible by shaders.
|
||||
///
|
||||
@ -142,6 +144,269 @@ impl Hash for dyn DescriptorSet {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct DescriptorSetInner {
|
||||
handle: ash::vk::DescriptorSet,
|
||||
layout: Arc<DescriptorSetLayout>,
|
||||
variable_descriptor_count: u32,
|
||||
resources: DescriptorSetResources,
|
||||
}
|
||||
|
||||
impl DescriptorSetInner {
|
||||
pub(crate) fn new(
|
||||
handle: ash::vk::DescriptorSet,
|
||||
layout: Arc<DescriptorSetLayout>,
|
||||
variable_descriptor_count: u32,
|
||||
descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>,
|
||||
) -> Result<Self, DescriptorSetUpdateError> {
|
||||
assert!(
|
||||
!layout.desc().is_push_descriptor(),
|
||||
"the provided descriptor set layout is for push descriptors, and cannot be used to build a descriptor set object"
|
||||
);
|
||||
|
||||
let max_count = layout.variable_descriptor_count();
|
||||
|
||||
assert!(
|
||||
variable_descriptor_count <= max_count,
|
||||
"the provided variable_descriptor_count ({}) is greater than the maximum number of variable count descriptors in the layout ({})",
|
||||
variable_descriptor_count,
|
||||
max_count,
|
||||
);
|
||||
|
||||
let mut resources = DescriptorSetResources::new(&layout, variable_descriptor_count);
|
||||
|
||||
let descriptor_writes = descriptor_writes.into_iter();
|
||||
let (lower_size_bound, _) = descriptor_writes.size_hint();
|
||||
let mut descriptor_write_info: SmallVec<[_; 8]> = SmallVec::with_capacity(lower_size_bound);
|
||||
let mut write_descriptor_set: SmallVec<[_; 8]> = SmallVec::with_capacity(lower_size_bound);
|
||||
|
||||
for write in descriptor_writes {
|
||||
let layout_binding =
|
||||
check_descriptor_write(&write, &layout, variable_descriptor_count)?;
|
||||
|
||||
resources.update(&write);
|
||||
descriptor_write_info.push(write.to_vulkan_info(layout_binding.ty));
|
||||
write_descriptor_set.push(write.to_vulkan(handle, layout_binding.ty));
|
||||
}
|
||||
|
||||
if !write_descriptor_set.is_empty() {
|
||||
for (info, write) in descriptor_write_info
|
||||
.iter()
|
||||
.zip(write_descriptor_set.iter_mut())
|
||||
{
|
||||
match info {
|
||||
DescriptorWriteInfo::Image(info) => {
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_image_info = info.as_ptr();
|
||||
}
|
||||
DescriptorWriteInfo::Buffer(info) => {
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_buffer_info = info.as_ptr();
|
||||
}
|
||||
DescriptorWriteInfo::BufferView(info) => {
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_texel_buffer_view = info.as_ptr();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let fns = layout.device().fns();
|
||||
|
||||
fns.v1_0.update_descriptor_sets(
|
||||
layout.device().internal_object(),
|
||||
write_descriptor_set.len() as u32,
|
||||
write_descriptor_set.as_ptr(),
|
||||
0,
|
||||
ptr::null(),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(DescriptorSetInner {
|
||||
handle,
|
||||
layout,
|
||||
variable_descriptor_count,
|
||||
resources,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn layout(&self) -> &Arc<DescriptorSetLayout> {
|
||||
&self.layout
|
||||
}
|
||||
|
||||
pub(crate) fn variable_descriptor_count(&self) -> u32 {
|
||||
self.variable_descriptor_count
|
||||
}
|
||||
|
||||
pub(crate) fn resources(&self) -> &DescriptorSetResources {
|
||||
&self.resources
|
||||
}
|
||||
}
|
||||
|
||||
/// The resources that are bound to a descriptor set.
|
||||
#[derive(Clone)]
|
||||
pub struct DescriptorSetResources {
|
||||
binding_resources: FnvHashMap<u32, DescriptorBindingResources>,
|
||||
}
|
||||
|
||||
impl DescriptorSetResources {
|
||||
/// Creates a new `DescriptorSetResources` matching the provided descriptor set layout, and
|
||||
/// all descriptors set to `None`.
|
||||
pub fn new(layout: &DescriptorSetLayout, variable_descriptor_count: u32) -> Self {
|
||||
assert!(variable_descriptor_count <= layout.variable_descriptor_count());
|
||||
|
||||
let binding_resources = layout
|
||||
.desc()
|
||||
.bindings()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(b, d)| d.as_ref().map(|d| (b as u32, d)))
|
||||
.map(|(binding_num, binding_desc)| {
|
||||
let count = if binding_desc.variable_count {
|
||||
variable_descriptor_count
|
||||
} else {
|
||||
binding_desc.descriptor_count
|
||||
} as usize;
|
||||
|
||||
let binding_resources = match binding_desc.ty {
|
||||
DescriptorType::UniformBuffer
|
||||
| DescriptorType::StorageBuffer
|
||||
| DescriptorType::UniformBufferDynamic
|
||||
| DescriptorType::StorageBufferDynamic => {
|
||||
DescriptorBindingResources::Buffer(smallvec![None; count])
|
||||
}
|
||||
DescriptorType::UniformTexelBuffer | DescriptorType::StorageTexelBuffer => {
|
||||
DescriptorBindingResources::BufferView(smallvec![None; count])
|
||||
}
|
||||
DescriptorType::SampledImage
|
||||
| DescriptorType::StorageImage
|
||||
| DescriptorType::InputAttachment => {
|
||||
DescriptorBindingResources::ImageView(smallvec![None; count])
|
||||
}
|
||||
DescriptorType::CombinedImageSampler => {
|
||||
if binding_desc.immutable_samplers.is_empty() {
|
||||
DescriptorBindingResources::ImageViewSampler(smallvec![None; count])
|
||||
} else {
|
||||
DescriptorBindingResources::ImageView(smallvec![None; count])
|
||||
}
|
||||
}
|
||||
DescriptorType::Sampler => {
|
||||
if binding_desc.immutable_samplers.is_empty() {
|
||||
DescriptorBindingResources::Sampler(smallvec![None; count])
|
||||
} else if layout.desc().is_push_descriptor() {
|
||||
// For push descriptors, no resource is written by default, this needs
|
||||
// to be done explicitly via a dummy write.
|
||||
DescriptorBindingResources::None(smallvec![None; count])
|
||||
} else {
|
||||
// For regular descriptor sets, all descriptors are considered valid
|
||||
// from the start.
|
||||
DescriptorBindingResources::None(smallvec![Some(()); count])
|
||||
}
|
||||
}
|
||||
};
|
||||
(binding_num, binding_resources)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Self { binding_resources }
|
||||
}
|
||||
|
||||
/// Applies a descriptor write to the resources.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the binding number of a write does not exist in the resources.
|
||||
/// - See also [`DescriptorBindingResources::update`].
|
||||
pub fn update<'a>(&mut self, write: &WriteDescriptorSet) {
|
||||
self.binding_resources
|
||||
.get_mut(&write.binding())
|
||||
.expect("descriptor write has invalid binding number")
|
||||
.update(write)
|
||||
}
|
||||
|
||||
/// Returns a reference to the bound resources for `binding`. Returns `None` if the binding
|
||||
/// doesn't exist.
|
||||
#[inline]
|
||||
pub fn binding(&self, binding: u32) -> Option<&DescriptorBindingResources> {
|
||||
self.binding_resources.get(&binding)
|
||||
}
|
||||
}
|
||||
|
||||
/// The resources that are bound to a single descriptor set binding.
|
||||
#[derive(Clone)]
|
||||
pub enum DescriptorBindingResources {
|
||||
None(Elements<()>),
|
||||
Buffer(Elements<Arc<dyn BufferAccess>>),
|
||||
BufferView(Elements<Arc<dyn BufferViewAbstract>>),
|
||||
ImageView(Elements<Arc<dyn ImageViewAbstract>>),
|
||||
ImageViewSampler(Elements<(Arc<dyn ImageViewAbstract>, Arc<Sampler>)>),
|
||||
Sampler(Elements<Arc<Sampler>>),
|
||||
}
|
||||
|
||||
type Elements<T> = SmallVec<[Option<T>; 1]>;
|
||||
|
||||
impl DescriptorBindingResources {
|
||||
/// Applies a descriptor write to the resources.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the resource types do not match.
|
||||
/// - Panics if the write goes out of bounds.
|
||||
pub fn update(&mut self, write: &WriteDescriptorSet) {
|
||||
fn write_resources<T: Clone>(first: usize, resources: &mut [Option<T>], elements: &[T]) {
|
||||
resources
|
||||
.get_mut(first..first + elements.len())
|
||||
.expect("descriptor write for binding out of bounds")
|
||||
.iter_mut()
|
||||
.zip(elements)
|
||||
.for_each(|(resource, element)| {
|
||||
*resource = Some(element.clone());
|
||||
});
|
||||
}
|
||||
|
||||
let first = write.first_array_element() as usize;
|
||||
|
||||
match (self, write.elements()) {
|
||||
(
|
||||
DescriptorBindingResources::None(resources),
|
||||
WriteDescriptorSetElements::None(num_elements),
|
||||
) => {
|
||||
resources
|
||||
.get_mut(first..first + *num_elements as usize)
|
||||
.expect("descriptor write for binding out of bounds")
|
||||
.iter_mut()
|
||||
.for_each(|resource| {
|
||||
*resource = Some(());
|
||||
});
|
||||
}
|
||||
(
|
||||
DescriptorBindingResources::Buffer(resources),
|
||||
WriteDescriptorSetElements::Buffer(elements),
|
||||
) => write_resources(first, resources, elements),
|
||||
(
|
||||
DescriptorBindingResources::BufferView(resources),
|
||||
WriteDescriptorSetElements::BufferView(elements),
|
||||
) => write_resources(first, resources, elements),
|
||||
(
|
||||
DescriptorBindingResources::ImageView(resources),
|
||||
WriteDescriptorSetElements::ImageView(elements),
|
||||
) => write_resources(first, resources, elements),
|
||||
(
|
||||
DescriptorBindingResources::ImageViewSampler(resources),
|
||||
WriteDescriptorSetElements::ImageViewSampler(elements),
|
||||
) => write_resources(first, resources, elements),
|
||||
(
|
||||
DescriptorBindingResources::Sampler(resources),
|
||||
WriteDescriptorSetElements::Sampler(elements),
|
||||
) => write_resources(first, resources, elements),
|
||||
_ => panic!(
|
||||
"descriptor write for binding {} has wrong resource type",
|
||||
write.binding(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DescriptorSetWithOffsets {
|
||||
descriptor_set: Arc<dyn DescriptorSet>,
|
||||
@ -234,143 +499,44 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Error related to descriptor sets.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DescriptorSetError {
|
||||
/// The number of array layers of an image doesn't match what was expected.
|
||||
ArrayLayersMismatch {
|
||||
/// Number of expected array layers for the image.
|
||||
expected: u32,
|
||||
/// Number of array layers of the image that was added.
|
||||
obtained: u32,
|
||||
},
|
||||
|
||||
/// Array doesn't contain the correct amount of descriptors
|
||||
ArrayLengthMismatch {
|
||||
/// Expected length
|
||||
expected: u32,
|
||||
/// Obtained length
|
||||
obtained: u32,
|
||||
},
|
||||
|
||||
/// Runtime array contains too many descriptors
|
||||
ArrayTooManyDescriptors {
|
||||
/// Capacity of array
|
||||
capacity: u32,
|
||||
/// Obtained length
|
||||
obtained: u32,
|
||||
},
|
||||
|
||||
/// The builder has previously return an error and is an unknown state.
|
||||
BuilderPoisoned,
|
||||
|
||||
/// Operation can not be performed on an empty descriptor.
|
||||
DescriptorIsEmpty,
|
||||
|
||||
/// Not all descriptors have been added.
|
||||
DescriptorsMissing {
|
||||
/// Expected bindings
|
||||
expected: u32,
|
||||
/// Obtained bindings
|
||||
obtained: u32,
|
||||
},
|
||||
|
||||
/// The builder is within an array, but the operation requires it not to be.
|
||||
InArray,
|
||||
|
||||
/// The image view isn't compatible with the sampler.
|
||||
IncompatibleImageViewSampler,
|
||||
|
||||
/// The buffer is missing the correct usage.
|
||||
MissingBufferUsage(MissingBufferUsage),
|
||||
|
||||
/// The image is missing the correct usage.
|
||||
MissingImageUsage(MissingImageUsage),
|
||||
|
||||
/// The image view has a component swizzle that is different from identity.
|
||||
NotIdentitySwizzled,
|
||||
|
||||
/// The builder is not in an array, but the operation requires it to be.
|
||||
NotInArray,
|
||||
|
||||
/// Out of memory
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum DescriptorSetCreationError {
|
||||
DescriptorSetUpdateError(DescriptorSetUpdateError),
|
||||
OomError(OomError),
|
||||
|
||||
/// Resource belongs to another device.
|
||||
ResourceWrongDevice,
|
||||
|
||||
/// Provided a dynamically assigned sampler, but the descriptor has an immutable sampler.
|
||||
SamplerIsImmutable,
|
||||
|
||||
/// Builder doesn't expect anymore descriptors
|
||||
TooManyDescriptors,
|
||||
|
||||
/// Expected a non-arrayed image, but got an arrayed image.
|
||||
UnexpectedArrayed,
|
||||
|
||||
/// Expected one type of resource but got another.
|
||||
WrongDescriptorType,
|
||||
}
|
||||
|
||||
impl From<OomError> for DescriptorSetError {
|
||||
fn from(error: OomError) -> Self {
|
||||
Self::OomError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for DescriptorSetError {}
|
||||
|
||||
impl fmt::Display for DescriptorSetError {
|
||||
impl std::error::Error for DescriptorSetCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
write!(
|
||||
fmt,
|
||||
"{}",
|
||||
match *self {
|
||||
Self::ArrayLayersMismatch { .. } =>
|
||||
"the number of array layers of an image doesn't match what was expected",
|
||||
Self::ArrayLengthMismatch { .. } =>
|
||||
"array doesn't contain the correct amount of descriptors",
|
||||
Self::ArrayTooManyDescriptors { .. } =>
|
||||
"runtime array contains too many descriptors",
|
||||
Self::BuilderPoisoned =>
|
||||
"the builder has previously return an error and is an unknown state",
|
||||
Self::DescriptorIsEmpty => "operation can not be performed on an empty descriptor",
|
||||
Self::DescriptorsMissing { .. } => "not all descriptors have been added",
|
||||
Self::InArray => "the builder is within an array, but the operation requires it not to be",
|
||||
Self::IncompatibleImageViewSampler =>
|
||||
"the image view isn't compatible with the sampler",
|
||||
Self::MissingBufferUsage(_) => "the buffer is missing the correct usage",
|
||||
Self::MissingImageUsage(_) => "the image is missing the correct usage",
|
||||
Self::NotIdentitySwizzled =>
|
||||
"the image view has a component swizzle that is different from identity",
|
||||
Self::NotInArray => "the builder is not in an array, but the operation requires it to be",
|
||||
Self::OomError(_) => "out of memory",
|
||||
Self::ResourceWrongDevice => "resource belongs to another device",
|
||||
Self::SamplerIsImmutable => "provided a dynamically assigned sampler, but the descriptor has an immutable sampler",
|
||||
Self::TooManyDescriptors => "builder doesn't expect anymore descriptors",
|
||||
Self::UnexpectedArrayed => "expected a non-arrayed image, but got an arrayed image",
|
||||
Self::WrongDescriptorType => "expected one type of resource but got another",
|
||||
}
|
||||
)
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
match self {
|
||||
Self::DescriptorSetUpdateError(err) => Some(err),
|
||||
Self::OomError(err) => Some(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Part of the DescriptorSetError for the case
|
||||
// of missing usage on a buffer.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum MissingBufferUsage {
|
||||
StorageBuffer,
|
||||
UniformBuffer,
|
||||
StorageTexelBuffer,
|
||||
UniformTexelBuffer,
|
||||
impl std::fmt::Display for DescriptorSetCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::DescriptorSetUpdateError(err) => {
|
||||
write!(f, "an error occurred while updating the descriptor set")
|
||||
}
|
||||
Self::OomError(err) => write!(f, "out of memory"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Part of the DescriptorSetError for the case
|
||||
// of missing usage on an image.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum MissingImageUsage {
|
||||
InputAttachment,
|
||||
Sampled,
|
||||
Storage,
|
||||
impl From<DescriptorSetUpdateError> for DescriptorSetCreationError {
|
||||
#[inline]
|
||||
fn from(err: DescriptorSetUpdateError) -> Self {
|
||||
Self::DescriptorSetUpdateError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OomError> for DescriptorSetCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
@ -21,17 +21,14 @@
|
||||
//! # Example
|
||||
//! TODO:
|
||||
|
||||
use crate::buffer::BufferView;
|
||||
use crate::descriptor_set::builder::DescriptorSetBuilder;
|
||||
use crate::descriptor_set::pool::standard::StdDescriptorPoolAlloc;
|
||||
use crate::descriptor_set::pool::{DescriptorPool, DescriptorPoolAlloc};
|
||||
use crate::descriptor_set::resources::DescriptorSetResources;
|
||||
use crate::descriptor_set::update::WriteDescriptorSet;
|
||||
use crate::descriptor_set::{
|
||||
BufferAccess, DescriptorSet, DescriptorSetError, DescriptorSetLayout, UnsafeDescriptorSet,
|
||||
DescriptorSet, DescriptorSetCreationError, DescriptorSetInner, DescriptorSetLayout,
|
||||
DescriptorSetResources, UnsafeDescriptorSet,
|
||||
};
|
||||
use crate::device::{Device, DeviceOwned};
|
||||
use crate::image::ImageViewAbstract;
|
||||
use crate::sampler::Sampler;
|
||||
use crate::VulkanObject;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::sync::Arc;
|
||||
@ -39,21 +36,79 @@ use std::sync::Arc;
|
||||
/// A simple, immutable descriptor set that is expected to be long-lived.
|
||||
pub struct PersistentDescriptorSet<P = StdDescriptorPoolAlloc> {
|
||||
alloc: P,
|
||||
resources: DescriptorSetResources,
|
||||
layout: Arc<DescriptorSetLayout>,
|
||||
inner: DescriptorSetInner,
|
||||
}
|
||||
|
||||
impl PersistentDescriptorSet {
|
||||
/// Starts the process of building a `PersistentDescriptorSet`. Returns a builder.
|
||||
pub fn start(layout: Arc<DescriptorSetLayout>) -> PersistentDescriptorSetBuilder {
|
||||
/// Creates and returns a new descriptor set with a variable descriptor count of 0.
|
||||
///
|
||||
/// See `new_with_pool` for more.
|
||||
#[inline]
|
||||
pub fn new(
|
||||
layout: Arc<DescriptorSetLayout>,
|
||||
descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>,
|
||||
) -> Result<Arc<PersistentDescriptorSet>, DescriptorSetCreationError> {
|
||||
let mut pool = Device::standard_descriptor_pool(layout.device());
|
||||
Self::new_with_pool(layout, 0, &mut pool, descriptor_writes)
|
||||
}
|
||||
|
||||
/// Creates and returns a new descriptor set with the requested variable descriptor count.
|
||||
///
|
||||
/// See `new_with_pool` for more.
|
||||
#[inline]
|
||||
pub fn new_variable(
|
||||
layout: Arc<DescriptorSetLayout>,
|
||||
variable_descriptor_count: u32,
|
||||
descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>,
|
||||
) -> Result<Arc<PersistentDescriptorSet>, DescriptorSetCreationError> {
|
||||
let mut pool = Device::standard_descriptor_pool(layout.device());
|
||||
Self::new_with_pool(
|
||||
layout,
|
||||
variable_descriptor_count,
|
||||
&mut pool,
|
||||
descriptor_writes,
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates and returns a new descriptor set with the requested variable descriptor count,
|
||||
/// allocating it from the provided pool.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if `layout` was created for push descriptors rather than descriptor sets.
|
||||
/// - Panics if `variable_descriptor_count` is too large for the given `layout`.
|
||||
pub fn new_with_pool<P>(
|
||||
layout: Arc<DescriptorSetLayout>,
|
||||
variable_descriptor_count: u32,
|
||||
pool: &mut P,
|
||||
descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>,
|
||||
) -> Result<Arc<PersistentDescriptorSet<P::Alloc>>, DescriptorSetCreationError>
|
||||
where
|
||||
P: ?Sized + DescriptorPool,
|
||||
{
|
||||
assert!(
|
||||
!layout.desc().is_push_descriptor(),
|
||||
"the provided descriptor set layout is for push descriptors, and cannot be used to build a descriptor set object"
|
||||
);
|
||||
|
||||
PersistentDescriptorSetBuilder {
|
||||
inner: DescriptorSetBuilder::start(layout),
|
||||
}
|
||||
let max_count = layout.variable_descriptor_count();
|
||||
|
||||
assert!(
|
||||
variable_descriptor_count <= max_count,
|
||||
"the provided variable_descriptor_count ({}) is greater than the maximum number of variable count descriptors in the set ({})",
|
||||
variable_descriptor_count,
|
||||
max_count,
|
||||
);
|
||||
|
||||
let alloc = pool.alloc(&layout, variable_descriptor_count)?;
|
||||
let inner = DescriptorSetInner::new(
|
||||
alloc.inner().internal_object(),
|
||||
layout,
|
||||
variable_descriptor_count,
|
||||
descriptor_writes,
|
||||
)?;
|
||||
|
||||
Ok(Arc::new(PersistentDescriptorSet { alloc, inner }))
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,12 +123,12 @@ where
|
||||
|
||||
#[inline]
|
||||
fn layout(&self) -> &Arc<DescriptorSetLayout> {
|
||||
&self.layout
|
||||
self.inner.layout()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn resources(&self) -> &DescriptorSetResources {
|
||||
&self.resources
|
||||
self.inner.resources()
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +138,7 @@ where
|
||||
{
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.layout.device()
|
||||
self.inner.layout().device()
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,138 +165,3 @@ where
|
||||
self.device().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// Prototype of a `PersistentDescriptorSet`.
|
||||
pub struct PersistentDescriptorSetBuilder {
|
||||
inner: DescriptorSetBuilder,
|
||||
}
|
||||
|
||||
impl PersistentDescriptorSetBuilder {
|
||||
/// Call this function if the next element of the set is an array in order to set the value of
|
||||
/// each element.
|
||||
///
|
||||
/// Returns an error if the descriptor is empty, there are no remaining descriptors, or if the
|
||||
/// builder is already in an error.
|
||||
///
|
||||
/// This function can be called even if the descriptor isn't an array, and it is valid to enter
|
||||
/// the "array", add one element, then leave.
|
||||
#[inline]
|
||||
pub fn enter_array(&mut self) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.inner.enter_array()?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Leaves the array. Call this once you added all the elements of the array.
|
||||
///
|
||||
/// Returns an error if the array is missing elements, or if the builder is not in an array.
|
||||
#[inline]
|
||||
pub fn leave_array(&mut self) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.inner.leave_array()?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Skips the current descriptor if it is empty.
|
||||
#[inline]
|
||||
pub fn add_empty(&mut self) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.inner.add_empty()?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Binds a buffer as the next descriptor.
|
||||
///
|
||||
/// An error is returned if the buffer isn't compatible with the descriptor.
|
||||
#[inline]
|
||||
pub fn add_buffer(
|
||||
&mut self,
|
||||
buffer: Arc<dyn BufferAccess>,
|
||||
) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.inner.add_buffer(buffer)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Binds a buffer view as the next descriptor.
|
||||
///
|
||||
/// An error is returned if the buffer isn't compatible with the descriptor.
|
||||
#[inline]
|
||||
pub fn add_buffer_view<B>(
|
||||
&mut self,
|
||||
view: Arc<BufferView<B>>,
|
||||
) -> Result<&mut Self, DescriptorSetError>
|
||||
where
|
||||
B: BufferAccess + 'static,
|
||||
{
|
||||
self.inner.add_buffer_view(view)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Binds an image view as the next descriptor.
|
||||
///
|
||||
/// An error is returned if the image view isn't compatible with the descriptor.
|
||||
#[inline]
|
||||
pub fn add_image(
|
||||
&mut self,
|
||||
image_view: Arc<dyn ImageViewAbstract>,
|
||||
) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.inner.add_image(image_view)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Binds an image view with a sampler as the next descriptor.
|
||||
///
|
||||
/// If the descriptor set layout contains immutable samplers for this descriptor, use
|
||||
/// `add_image` instead.
|
||||
///
|
||||
/// An error is returned if the image view isn't compatible with the descriptor.
|
||||
#[inline]
|
||||
pub fn add_sampled_image(
|
||||
&mut self,
|
||||
image_view: Arc<dyn ImageViewAbstract>,
|
||||
sampler: Arc<Sampler>,
|
||||
) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.inner.add_sampled_image(image_view, sampler)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Binds a sampler as the next descriptor.
|
||||
///
|
||||
/// An error is returned if the sampler isn't compatible with the descriptor.
|
||||
#[inline]
|
||||
pub fn add_sampler(&mut self, sampler: Arc<Sampler>) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.inner.add_sampler(sampler)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Builds a `PersistentDescriptorSet` from the builder.
|
||||
#[inline]
|
||||
pub fn build(
|
||||
self,
|
||||
) -> Result<Arc<PersistentDescriptorSet<StdDescriptorPoolAlloc>>, DescriptorSetError> {
|
||||
let mut pool = Device::standard_descriptor_pool(self.inner.device());
|
||||
self.build_with_pool(&mut pool)
|
||||
}
|
||||
|
||||
/// Builds a `PersistentDescriptorSet` from the builder.
|
||||
pub fn build_with_pool<P>(
|
||||
self,
|
||||
pool: &mut P,
|
||||
) -> Result<Arc<PersistentDescriptorSet<P::Alloc>>, DescriptorSetError>
|
||||
where
|
||||
P: ?Sized + DescriptorPool,
|
||||
{
|
||||
let writes = self.inner.build()?;
|
||||
let mut alloc = pool.alloc(writes.layout(), writes.variable_descriptor_count())?;
|
||||
let mut resources =
|
||||
DescriptorSetResources::new(writes.layout(), writes.variable_descriptor_count());
|
||||
|
||||
unsafe {
|
||||
alloc.inner_mut().write(writes.layout(), writes.writes());
|
||||
resources.update(writes.writes());
|
||||
}
|
||||
|
||||
Ok(Arc::new(PersistentDescriptorSet {
|
||||
alloc,
|
||||
resources,
|
||||
layout: writes.layout().clone(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
@ -1,166 +0,0 @@
|
||||
// Copyright (c) 2017 The vulkano developers
|
||||
// Licensed under the Apache License, Version 2.0
|
||||
// <LICENSE-APACHE or
|
||||
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
|
||||
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
|
||||
// at your option. All files in the project carrying such
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use crate::buffer::BufferViewAbstract;
|
||||
use crate::descriptor_set::layout::{DescriptorSetLayout, DescriptorType};
|
||||
use crate::descriptor_set::sys::{DescriptorWrite, DescriptorWriteElements};
|
||||
use crate::descriptor_set::BufferAccess;
|
||||
use crate::image::ImageViewAbstract;
|
||||
use crate::sampler::Sampler;
|
||||
use fnv::FnvHashMap;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// The resources that are bound to a descriptor set.
|
||||
#[derive(Clone)]
|
||||
pub struct DescriptorSetResources {
|
||||
descriptors: FnvHashMap<u32, DescriptorBindingResources>,
|
||||
}
|
||||
|
||||
impl DescriptorSetResources {
|
||||
/// Creates a new `DescriptorSetResources` matching the provided descriptor set layout, and
|
||||
/// all descriptors set to `None`.
|
||||
pub fn new(layout: &DescriptorSetLayout, variable_descriptor_count: u32) -> Self {
|
||||
assert!(variable_descriptor_count <= layout.variable_descriptor_count());
|
||||
|
||||
let descriptors = layout
|
||||
.desc()
|
||||
.bindings()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(b, d)| d.as_ref().map(|d| (b as u32, d)))
|
||||
.map(|(binding_num, binding_desc)| {
|
||||
let count = if binding_desc.variable_count {
|
||||
variable_descriptor_count
|
||||
} else {
|
||||
binding_desc.descriptor_count
|
||||
} as usize;
|
||||
|
||||
let binding_resources = match binding_desc.ty {
|
||||
DescriptorType::UniformBuffer
|
||||
| DescriptorType::StorageBuffer
|
||||
| DescriptorType::UniformBufferDynamic
|
||||
| DescriptorType::StorageBufferDynamic => {
|
||||
DescriptorBindingResources::Buffer(smallvec![None; count])
|
||||
}
|
||||
DescriptorType::UniformTexelBuffer | DescriptorType::StorageTexelBuffer => {
|
||||
DescriptorBindingResources::BufferView(smallvec![None; count])
|
||||
}
|
||||
DescriptorType::SampledImage
|
||||
| DescriptorType::StorageImage
|
||||
| DescriptorType::InputAttachment => {
|
||||
DescriptorBindingResources::ImageView(smallvec![None; count])
|
||||
}
|
||||
DescriptorType::CombinedImageSampler => {
|
||||
if binding_desc.immutable_samplers.is_empty() {
|
||||
DescriptorBindingResources::ImageViewSampler(smallvec![None; count])
|
||||
} else {
|
||||
DescriptorBindingResources::ImageView(smallvec![None; count])
|
||||
}
|
||||
}
|
||||
DescriptorType::Sampler => {
|
||||
if binding_desc.immutable_samplers.is_empty() {
|
||||
DescriptorBindingResources::Sampler(smallvec![None; count])
|
||||
} else {
|
||||
DescriptorBindingResources::None
|
||||
}
|
||||
}
|
||||
};
|
||||
(binding_num, binding_resources)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Self { descriptors }
|
||||
}
|
||||
|
||||
/// Applies descriptor writes to the resources.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the binding number of a write does not exist in the resources.
|
||||
/// - See also [`DescriptorBindingResources::update`].
|
||||
pub fn update<'a>(&mut self, writes: impl IntoIterator<Item = &'a DescriptorWrite>) {
|
||||
for write in writes {
|
||||
self.descriptors
|
||||
.get_mut(&write.binding_num)
|
||||
.expect("descriptor write has invalid binding number")
|
||||
.update(write)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the bound resources for `binding`. Returns `None` if the binding
|
||||
/// doesn't exist.
|
||||
#[inline]
|
||||
pub fn binding(&self, binding: u32) -> Option<&DescriptorBindingResources> {
|
||||
self.descriptors.get(&binding)
|
||||
}
|
||||
}
|
||||
|
||||
/// The resources that are bound to a single descriptor set binding.
|
||||
#[derive(Clone)]
|
||||
pub enum DescriptorBindingResources {
|
||||
None,
|
||||
Buffer(Elements<Arc<dyn BufferAccess>>),
|
||||
BufferView(Elements<Arc<dyn BufferViewAbstract>>),
|
||||
ImageView(Elements<Arc<dyn ImageViewAbstract>>),
|
||||
ImageViewSampler(Elements<(Arc<dyn ImageViewAbstract>, Arc<Sampler>)>),
|
||||
Sampler(Elements<Arc<Sampler>>),
|
||||
}
|
||||
|
||||
type Elements<T> = SmallVec<[Option<T>; 1]>;
|
||||
|
||||
impl DescriptorBindingResources {
|
||||
/// Applies a descriptor write to the resources.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the resource types do not match.
|
||||
/// - Panics if the write goes out of bounds.
|
||||
pub fn update(&mut self, write: &DescriptorWrite) {
|
||||
fn write_resources<T: Clone>(first: usize, resources: &mut [Option<T>], elements: &[T]) {
|
||||
resources
|
||||
.get_mut(first..first + elements.len())
|
||||
.expect("descriptor write for binding out of bounds")
|
||||
.iter_mut()
|
||||
.zip(elements)
|
||||
.for_each(|(resource, element)| {
|
||||
*resource = Some(element.clone());
|
||||
});
|
||||
}
|
||||
|
||||
let first = write.first_array_element() as usize;
|
||||
|
||||
match (self, write.elements()) {
|
||||
(
|
||||
DescriptorBindingResources::Buffer(resources),
|
||||
DescriptorWriteElements::Buffer(elements),
|
||||
) => write_resources(first, resources, elements),
|
||||
(
|
||||
DescriptorBindingResources::BufferView(resources),
|
||||
DescriptorWriteElements::BufferView(elements),
|
||||
) => write_resources(first, resources, elements),
|
||||
(
|
||||
DescriptorBindingResources::ImageView(resources),
|
||||
DescriptorWriteElements::ImageView(elements),
|
||||
) => write_resources(first, resources, elements),
|
||||
(
|
||||
DescriptorBindingResources::ImageViewSampler(resources),
|
||||
DescriptorWriteElements::ImageViewSampler(elements),
|
||||
) => write_resources(first, resources, elements),
|
||||
(
|
||||
DescriptorBindingResources::Sampler(resources),
|
||||
DescriptorWriteElements::Sampler(elements),
|
||||
) => write_resources(first, resources, elements),
|
||||
_ => panic!(
|
||||
"descriptor write for binding {} has wrong resource type",
|
||||
write.binding_num,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
@ -7,17 +7,16 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use super::resources::DescriptorSetResources;
|
||||
use crate::buffer::BufferView;
|
||||
use crate::descriptor_set::builder::DescriptorSetBuilder;
|
||||
use crate::descriptor_set::layout::DescriptorSetLayout;
|
||||
use crate::descriptor_set::pool::{
|
||||
DescriptorPoolAlloc, DescriptorPoolAllocError, DescriptorSetAllocateInfo, UnsafeDescriptorPool,
|
||||
};
|
||||
use crate::descriptor_set::{BufferAccess, DescriptorSet, DescriptorSetError, UnsafeDescriptorSet};
|
||||
use crate::descriptor_set::update::WriteDescriptorSet;
|
||||
use crate::descriptor_set::{
|
||||
DescriptorSet, DescriptorSetCreationError, DescriptorSetInner, DescriptorSetResources,
|
||||
UnsafeDescriptorSet,
|
||||
};
|
||||
use crate::device::{Device, DeviceOwned};
|
||||
use crate::image::ImageViewAbstract;
|
||||
use crate::sampler::Sampler;
|
||||
use crate::OomError;
|
||||
use crate::VulkanObject;
|
||||
use crossbeam_queue::SegQueue;
|
||||
@ -66,16 +65,22 @@ impl SingleLayoutDescSetPool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Starts the process of building a new descriptor set.
|
||||
///
|
||||
/// The set will corresponds to the set layout that was passed to `new`.
|
||||
pub fn next(&mut self) -> SingleLayoutDescSetBuilder {
|
||||
let layout = self.layout.clone();
|
||||
/// Returns a new descriptor set, either by creating a new one or returning an existing one
|
||||
/// from the internal reserve.
|
||||
#[inline]
|
||||
pub fn next(
|
||||
&mut self,
|
||||
descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>,
|
||||
) -> Result<Arc<SingleLayoutDescSet>, DescriptorSetCreationError> {
|
||||
let alloc = self.next_alloc()?;
|
||||
let inner = DescriptorSetInner::new(
|
||||
alloc.inner().internal_object(),
|
||||
self.layout.clone(),
|
||||
0,
|
||||
descriptor_writes,
|
||||
)?;
|
||||
|
||||
SingleLayoutDescSetBuilder {
|
||||
pool: self,
|
||||
inner: DescriptorSetBuilder::start(layout),
|
||||
}
|
||||
Ok(Arc::new(SingleLayoutDescSet { alloc, inner }))
|
||||
}
|
||||
|
||||
fn next_alloc(&mut self) -> Result<SingleLayoutPoolAlloc, OomError> {
|
||||
@ -183,8 +188,7 @@ impl Drop for SingleLayoutPoolAlloc {
|
||||
/// A descriptor set created from a `SingleLayoutDescSetPool`.
|
||||
pub struct SingleLayoutDescSet {
|
||||
alloc: SingleLayoutPoolAlloc,
|
||||
resources: DescriptorSetResources,
|
||||
layout: Arc<DescriptorSetLayout>,
|
||||
inner: DescriptorSetInner,
|
||||
}
|
||||
|
||||
unsafe impl DescriptorSet for SingleLayoutDescSet {
|
||||
@ -195,19 +199,19 @@ unsafe impl DescriptorSet for SingleLayoutDescSet {
|
||||
|
||||
#[inline]
|
||||
fn layout(&self) -> &Arc<DescriptorSetLayout> {
|
||||
&self.layout
|
||||
self.inner.layout()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn resources(&self) -> &DescriptorSetResources {
|
||||
&self.resources
|
||||
self.inner.resources()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl DeviceOwned for SingleLayoutDescSet {
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.layout.device()
|
||||
self.inner.layout().device()
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,124 +232,3 @@ impl Hash for SingleLayoutDescSet {
|
||||
self.device().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// Prototype of a `SingleLayoutDescSet`.
|
||||
pub struct SingleLayoutDescSetBuilder<'a> {
|
||||
pool: &'a mut SingleLayoutDescSetPool,
|
||||
inner: DescriptorSetBuilder,
|
||||
}
|
||||
|
||||
impl<'a> SingleLayoutDescSetBuilder<'a> {
|
||||
/// Call this function if the next element of the set is an array in order to set the value of
|
||||
/// each element.
|
||||
///
|
||||
/// Returns an error if the descriptor is empty, there are no remaining descriptors, or if the
|
||||
/// builder is already in an error.
|
||||
///
|
||||
/// This function can be called even if the descriptor isn't an array, and it is valid to enter
|
||||
/// the "array", add one element, then leave.
|
||||
#[inline]
|
||||
pub fn enter_array(&mut self) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.inner.enter_array()?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Leaves the array. Call this once you added all the elements of the array.
|
||||
///
|
||||
/// Returns an error if the array is missing elements, or if the builder is not in an array.
|
||||
#[inline]
|
||||
pub fn leave_array(&mut self) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.inner.leave_array()?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Skips the current descriptor if it is empty.
|
||||
#[inline]
|
||||
pub fn add_empty(&mut self) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.inner.add_empty()?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Binds a buffer as the next descriptor.
|
||||
///
|
||||
/// An error is returned if the buffer isn't compatible with the descriptor.
|
||||
#[inline]
|
||||
pub fn add_buffer(
|
||||
&mut self,
|
||||
buffer: Arc<dyn BufferAccess>,
|
||||
) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.inner.add_buffer(buffer)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Binds a buffer view as the next descriptor.
|
||||
///
|
||||
/// An error is returned if the buffer isn't compatible with the descriptor.
|
||||
#[inline]
|
||||
pub fn add_buffer_view<B>(
|
||||
&mut self,
|
||||
view: Arc<BufferView<B>>,
|
||||
) -> Result<&mut Self, DescriptorSetError>
|
||||
where
|
||||
B: BufferAccess + 'static,
|
||||
{
|
||||
self.inner.add_buffer_view(view)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Binds an image view as the next descriptor.
|
||||
///
|
||||
/// An error is returned if the image view isn't compatible with the descriptor.
|
||||
#[inline]
|
||||
pub fn add_image(
|
||||
&mut self,
|
||||
image_view: Arc<dyn ImageViewAbstract + 'static>,
|
||||
) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.inner.add_image(image_view)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Binds an image view with a sampler as the next descriptor.
|
||||
///
|
||||
/// If the descriptor set layout contains immutable samplers for this descriptor, use
|
||||
/// `add_image` instead.
|
||||
///
|
||||
/// An error is returned if the image view isn't compatible with the descriptor.
|
||||
#[inline]
|
||||
pub fn add_sampled_image(
|
||||
&mut self,
|
||||
image_view: Arc<dyn ImageViewAbstract + 'static>,
|
||||
sampler: Arc<Sampler>,
|
||||
) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.inner.add_sampled_image(image_view, sampler)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Binds a sampler as the next descriptor.
|
||||
///
|
||||
/// An error is returned if the sampler isn't compatible with the descriptor.
|
||||
#[inline]
|
||||
pub fn add_sampler(&mut self, sampler: Arc<Sampler>) -> Result<&mut Self, DescriptorSetError> {
|
||||
self.inner.add_sampler(sampler)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Builds a `SingleLayoutDescSet` from the builder.
|
||||
pub fn build(self) -> Result<Arc<SingleLayoutDescSet>, DescriptorSetError> {
|
||||
let writes = self.inner.build()?;
|
||||
debug_assert!(writes.variable_descriptor_count() == 0);
|
||||
let mut alloc = self.pool.next_alloc()?;
|
||||
let mut resources = DescriptorSetResources::new(writes.layout(), 0);
|
||||
|
||||
unsafe {
|
||||
alloc.inner_mut().write(writes.layout(), writes.writes());
|
||||
resources.update(writes.writes());
|
||||
}
|
||||
|
||||
Ok(Arc::new(SingleLayoutDescSet {
|
||||
alloc,
|
||||
resources,
|
||||
layout: writes.layout().clone(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
@ -9,17 +9,13 @@
|
||||
|
||||
//! Low-level descriptor set.
|
||||
|
||||
use crate::buffer::{BufferAccess, BufferInner, BufferViewAbstract};
|
||||
use crate::descriptor_set::layout::{DescriptorSetLayout, DescriptorType};
|
||||
use crate::descriptor_set::layout::DescriptorSetLayout;
|
||||
use crate::descriptor_set::update::{DescriptorWriteInfo, WriteDescriptorSet};
|
||||
use crate::device::DeviceOwned;
|
||||
use crate::image::view::ImageViewAbstract;
|
||||
use crate::sampler::Sampler;
|
||||
use crate::DeviceSize;
|
||||
use crate::VulkanObject;
|
||||
use smallvec::SmallVec;
|
||||
use std::fmt;
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Low-level descriptor set.
|
||||
///
|
||||
@ -50,12 +46,12 @@ impl UnsafeDescriptorSet {
|
||||
pub unsafe fn write<'a>(
|
||||
&mut self,
|
||||
layout: &DescriptorSetLayout,
|
||||
writes: impl IntoIterator<Item = &'a DescriptorWrite>,
|
||||
writes: impl IntoIterator<Item = &'a WriteDescriptorSet>,
|
||||
) {
|
||||
let (infos, mut writes): (SmallVec<[_; 8]>, SmallVec<[_; 8]>) = writes
|
||||
.into_iter()
|
||||
.map(|write| {
|
||||
let descriptor_type = layout.descriptor(write.binding_num).unwrap().ty;
|
||||
let descriptor_type = layout.descriptor(write.binding()).unwrap().ty;
|
||||
|
||||
(
|
||||
write.to_vulkan_info(descriptor_type),
|
||||
@ -120,294 +116,3 @@ impl fmt::Debug for UnsafeDescriptorSet {
|
||||
write!(fmt, "<Vulkan descriptor set {:?}>", self.handle)
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a single write entry to a descriptor set.
|
||||
///
|
||||
/// Use the various constructors to build a `DescriptorWrite`. While it is safe to build a
|
||||
/// `DescriptorWrite`, it is unsafe to actually use it to write to a descriptor set.
|
||||
pub struct DescriptorWrite {
|
||||
pub(crate) binding_num: u32,
|
||||
first_array_element: u32,
|
||||
elements: DescriptorWriteElements,
|
||||
}
|
||||
|
||||
impl DescriptorWrite {
|
||||
#[inline]
|
||||
pub unsafe fn buffer(
|
||||
binding_num: u32,
|
||||
first_array_element: u32,
|
||||
elements: impl IntoIterator<Item = Arc<dyn BufferAccess>>,
|
||||
) -> Self {
|
||||
let elements: SmallVec<_> = elements.into_iter().collect();
|
||||
assert!(!elements.is_empty());
|
||||
Self {
|
||||
binding_num,
|
||||
first_array_element,
|
||||
elements: DescriptorWriteElements::Buffer(elements),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn buffer_view(
|
||||
binding_num: u32,
|
||||
first_array_element: u32,
|
||||
elements: impl IntoIterator<Item = Arc<dyn BufferViewAbstract>>,
|
||||
) -> Self {
|
||||
let elements: SmallVec<_> = elements.into_iter().collect();
|
||||
assert!(!elements.is_empty());
|
||||
Self {
|
||||
binding_num,
|
||||
first_array_element,
|
||||
elements: DescriptorWriteElements::BufferView(elements),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn image_view(
|
||||
binding_num: u32,
|
||||
first_array_element: u32,
|
||||
elements: impl IntoIterator<Item = Arc<dyn ImageViewAbstract>>,
|
||||
) -> Self {
|
||||
let elements: SmallVec<_> = elements.into_iter().collect();
|
||||
assert!(!elements.is_empty());
|
||||
Self {
|
||||
binding_num,
|
||||
first_array_element,
|
||||
elements: DescriptorWriteElements::ImageView(elements),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn image_view_sampler(
|
||||
binding_num: u32,
|
||||
first_array_element: u32,
|
||||
elements: impl IntoIterator<Item = (Arc<dyn ImageViewAbstract>, Arc<Sampler>)>,
|
||||
) -> Self {
|
||||
let elements: SmallVec<_> = elements.into_iter().collect();
|
||||
assert!(!elements.is_empty());
|
||||
Self {
|
||||
binding_num,
|
||||
first_array_element,
|
||||
elements: DescriptorWriteElements::ImageViewSampler(elements),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn sampler(
|
||||
binding_num: u32,
|
||||
first_array_element: u32,
|
||||
elements: impl IntoIterator<Item = Arc<Sampler>>,
|
||||
) -> Self {
|
||||
let elements: SmallVec<_> = elements.into_iter().collect();
|
||||
assert!(!elements.is_empty());
|
||||
Self {
|
||||
binding_num,
|
||||
first_array_element,
|
||||
elements: DescriptorWriteElements::Sampler(elements),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the binding number that is updated by this descriptor write.
|
||||
#[inline]
|
||||
pub fn binding_num(&self) -> u32 {
|
||||
self.binding_num
|
||||
}
|
||||
|
||||
/// Returns the first array element in the binding that is updated by this descriptor write.
|
||||
#[inline]
|
||||
pub fn first_array_element(&self) -> u32 {
|
||||
self.first_array_element
|
||||
}
|
||||
|
||||
/// Returns a reference to the elements held by this descriptor write.
|
||||
#[inline]
|
||||
pub fn elements(&self) -> &DescriptorWriteElements {
|
||||
&self.elements
|
||||
}
|
||||
|
||||
pub(crate) fn to_vulkan_info(&self, descriptor_type: DescriptorType) -> DescriptorWriteInfo {
|
||||
match &self.elements {
|
||||
DescriptorWriteElements::Buffer(elements) => {
|
||||
debug_assert!(matches!(
|
||||
descriptor_type,
|
||||
DescriptorType::UniformBuffer
|
||||
| DescriptorType::StorageBuffer
|
||||
| DescriptorType::UniformBufferDynamic
|
||||
| DescriptorType::StorageBufferDynamic
|
||||
));
|
||||
DescriptorWriteInfo::Buffer(
|
||||
elements
|
||||
.iter()
|
||||
.map(|buffer| {
|
||||
let size = buffer.size();
|
||||
let BufferInner { buffer, offset } = buffer.inner();
|
||||
|
||||
debug_assert_eq!(
|
||||
offset
|
||||
% buffer
|
||||
.device()
|
||||
.physical_device()
|
||||
.properties()
|
||||
.min_storage_buffer_offset_alignment,
|
||||
0
|
||||
);
|
||||
debug_assert!(
|
||||
size <= buffer
|
||||
.device()
|
||||
.physical_device()
|
||||
.properties()
|
||||
.max_storage_buffer_range
|
||||
as DeviceSize
|
||||
);
|
||||
ash::vk::DescriptorBufferInfo {
|
||||
buffer: buffer.internal_object(),
|
||||
offset,
|
||||
range: size,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
DescriptorWriteElements::BufferView(elements) => {
|
||||
debug_assert!(matches!(
|
||||
descriptor_type,
|
||||
DescriptorType::UniformTexelBuffer | DescriptorType::StorageTexelBuffer
|
||||
));
|
||||
DescriptorWriteInfo::BufferView(
|
||||
elements
|
||||
.iter()
|
||||
.map(|buffer_view| buffer_view.inner())
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
DescriptorWriteElements::ImageView(elements) => {
|
||||
// Note: combined image sampler can occur with immutable samplers
|
||||
debug_assert!(matches!(
|
||||
descriptor_type,
|
||||
DescriptorType::CombinedImageSampler
|
||||
| DescriptorType::SampledImage
|
||||
| DescriptorType::StorageImage
|
||||
| DescriptorType::InputAttachment
|
||||
));
|
||||
DescriptorWriteInfo::Image(
|
||||
elements
|
||||
.iter()
|
||||
.map(|image_view| {
|
||||
let layouts = image_view.image().descriptor_layouts().expect(
|
||||
"descriptor_layouts must return Some when used in an image view",
|
||||
);
|
||||
ash::vk::DescriptorImageInfo {
|
||||
sampler: ash::vk::Sampler::null(),
|
||||
image_view: image_view.inner().internal_object(),
|
||||
image_layout: layouts.layout_for(descriptor_type).into(),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
DescriptorWriteElements::ImageViewSampler(elements) => {
|
||||
debug_assert!(matches!(
|
||||
descriptor_type,
|
||||
DescriptorType::CombinedImageSampler
|
||||
));
|
||||
DescriptorWriteInfo::Image(
|
||||
elements
|
||||
.iter()
|
||||
.map(|(image_view, sampler)| {
|
||||
let layouts = image_view.image().descriptor_layouts().expect(
|
||||
"descriptor_layouts must return Some when used in an image view",
|
||||
);
|
||||
ash::vk::DescriptorImageInfo {
|
||||
sampler: sampler.internal_object(),
|
||||
image_view: image_view.inner().internal_object(),
|
||||
image_layout: layouts.layout_for(descriptor_type).into(),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
DescriptorWriteElements::Sampler(elements) => {
|
||||
debug_assert!(matches!(descriptor_type, DescriptorType::Sampler));
|
||||
DescriptorWriteInfo::Image(
|
||||
elements
|
||||
.iter()
|
||||
.map(|sampler| ash::vk::DescriptorImageInfo {
|
||||
sampler: sampler.internal_object(),
|
||||
image_view: ash::vk::ImageView::null(),
|
||||
image_layout: ash::vk::ImageLayout::UNDEFINED,
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_vulkan(
|
||||
&self,
|
||||
dst_set: ash::vk::DescriptorSet,
|
||||
descriptor_type: DescriptorType,
|
||||
) -> ash::vk::WriteDescriptorSet {
|
||||
ash::vk::WriteDescriptorSet {
|
||||
dst_set,
|
||||
dst_binding: self.binding_num,
|
||||
dst_array_element: self.first_array_element,
|
||||
descriptor_count: 0,
|
||||
descriptor_type: descriptor_type.into(),
|
||||
p_image_info: ptr::null(),
|
||||
p_buffer_info: ptr::null(),
|
||||
p_texel_buffer_view: ptr::null(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The elements held by a descriptor write.
|
||||
pub enum DescriptorWriteElements {
|
||||
Buffer(SmallVec<[Arc<dyn BufferAccess>; 1]>),
|
||||
BufferView(SmallVec<[Arc<dyn BufferViewAbstract>; 1]>),
|
||||
ImageView(SmallVec<[Arc<dyn ImageViewAbstract>; 1]>),
|
||||
ImageViewSampler(SmallVec<[(Arc<dyn ImageViewAbstract>, Arc<Sampler>); 1]>),
|
||||
Sampler(SmallVec<[Arc<Sampler>; 1]>),
|
||||
}
|
||||
|
||||
impl DescriptorWriteElements {
|
||||
/// Returns the number of elements.
|
||||
#[inline]
|
||||
pub fn len(&self) -> u32 {
|
||||
match self {
|
||||
DescriptorWriteElements::Buffer(elements) => elements.len() as u32,
|
||||
DescriptorWriteElements::BufferView(elements) => elements.len() as u32,
|
||||
DescriptorWriteElements::ImageView(elements) => elements.len() as u32,
|
||||
DescriptorWriteElements::ImageViewSampler(elements) => elements.len() as u32,
|
||||
DescriptorWriteElements::Sampler(elements) => elements.len() as u32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) enum DescriptorWriteInfo {
|
||||
Image(SmallVec<[ash::vk::DescriptorImageInfo; 1]>),
|
||||
Buffer(SmallVec<[ash::vk::DescriptorBufferInfo; 1]>),
|
||||
BufferView(SmallVec<[ash::vk::BufferView; 1]>),
|
||||
}
|
||||
|
||||
impl DescriptorWriteInfo {
|
||||
fn set_info(&self, write: &mut ash::vk::WriteDescriptorSet) {
|
||||
match self {
|
||||
DescriptorWriteInfo::Image(info) => {
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_image_info = info.as_ptr();
|
||||
}
|
||||
DescriptorWriteInfo::Buffer(info) => {
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_buffer_info = info.as_ptr();
|
||||
}
|
||||
DescriptorWriteInfo::BufferView(info) => {
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_texel_buffer_view = info.as_ptr();
|
||||
}
|
||||
}
|
||||
|
||||
debug_assert!(write.descriptor_count != 0);
|
||||
}
|
||||
}
|
||||
|
822
vulkano/src/descriptor_set/update.rs
Normal file
822
vulkano/src/descriptor_set/update.rs
Normal file
@ -0,0 +1,822 @@
|
||||
// Copyright (c) 2017 The vulkano developers
|
||||
// Licensed under the Apache License, Version 2.0
|
||||
// <LICENSE-APACHE or
|
||||
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
|
||||
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
|
||||
// at your option. All files in the project carrying such
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use crate::buffer::{BufferAccess, BufferInner, BufferViewAbstract};
|
||||
use crate::descriptor_set::layout::{DescriptorDesc, DescriptorType};
|
||||
use crate::descriptor_set::DescriptorSetLayout;
|
||||
use crate::device::DeviceOwned;
|
||||
use crate::image::ImageViewAbstract;
|
||||
use crate::sampler::Sampler;
|
||||
use crate::DeviceSize;
|
||||
use crate::VulkanObject;
|
||||
use smallvec::SmallVec;
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Represents a single write operation to the binding of a descriptor set.
|
||||
///
|
||||
/// `WriteDescriptorSet` specifies the binding number and target array index, and includes one or
|
||||
/// more resources of a given type that need to be written to that location. Two constructors are
|
||||
/// provided for each resource type:
|
||||
/// - The basic constructor variant writes a single element to array index 0. It is intended for
|
||||
/// non-arrayed bindings, where `descriptor_count` in the descriptor set layout is 1.
|
||||
/// - The `_array` variant writes several elements and allows specifying the target array index.
|
||||
/// At least one element must be provided; a panic results if the provided iterator is empty.
|
||||
pub struct WriteDescriptorSet {
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
elements: WriteDescriptorSetElements,
|
||||
}
|
||||
|
||||
impl WriteDescriptorSet {
|
||||
/// Write an empty element to array element 0.
|
||||
///
|
||||
/// See `none_array` for more information.
|
||||
#[inline]
|
||||
pub fn none(binding: u32) -> Self {
|
||||
Self::none_array(binding, 0, 1)
|
||||
}
|
||||
|
||||
/// Write a number of consecutive empty elements.
|
||||
///
|
||||
/// This is used for push descriptors in combination with `Sampler` descriptors that have
|
||||
/// immutable samplers in the layout. The Vulkan spec requires these elements to be explicitly
|
||||
/// written, but since there is no data to write, a dummy write is provided instead.
|
||||
///
|
||||
/// For regular descriptor sets, the data for such descriptors is automatically valid, and dummy
|
||||
/// writes are not allowed.
|
||||
#[inline]
|
||||
pub fn none_array(binding: u32, first_array_element: u32, num_elements: u32) -> Self {
|
||||
assert!(num_elements != 0);
|
||||
Self {
|
||||
binding,
|
||||
first_array_element,
|
||||
elements: WriteDescriptorSetElements::None(num_elements),
|
||||
}
|
||||
}
|
||||
|
||||
/// Write a single buffer to array element 0.
|
||||
#[inline]
|
||||
pub fn buffer(binding: u32, buffer: Arc<dyn BufferAccess>) -> Self {
|
||||
Self::buffer_array(binding, 0, [buffer])
|
||||
}
|
||||
|
||||
/// Write a number of consecutive buffer elements.
|
||||
#[inline]
|
||||
pub fn buffer_array(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
elements: impl IntoIterator<Item = Arc<dyn BufferAccess>>,
|
||||
) -> Self {
|
||||
let elements: SmallVec<_> = elements.into_iter().collect();
|
||||
assert!(!elements.is_empty());
|
||||
Self {
|
||||
binding,
|
||||
first_array_element,
|
||||
elements: WriteDescriptorSetElements::Buffer(elements),
|
||||
}
|
||||
}
|
||||
|
||||
/// Write a single buffer view to array element 0.
|
||||
#[inline]
|
||||
pub fn buffer_view(binding: u32, buffer_view: Arc<dyn BufferViewAbstract>) -> Self {
|
||||
Self::buffer_view_array(binding, 0, [buffer_view])
|
||||
}
|
||||
|
||||
/// Write a number of consecutive buffer view elements.
|
||||
#[inline]
|
||||
pub fn buffer_view_array(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
elements: impl IntoIterator<Item = Arc<dyn BufferViewAbstract>>,
|
||||
) -> Self {
|
||||
let elements: SmallVec<_> = elements.into_iter().collect();
|
||||
assert!(!elements.is_empty());
|
||||
Self {
|
||||
binding,
|
||||
first_array_element,
|
||||
elements: WriteDescriptorSetElements::BufferView(elements),
|
||||
}
|
||||
}
|
||||
|
||||
/// Write a single image view to array element 0.
|
||||
#[inline]
|
||||
pub fn image_view(binding: u32, image_view: Arc<dyn ImageViewAbstract>) -> Self {
|
||||
Self::image_view_array(binding, 0, [image_view])
|
||||
}
|
||||
|
||||
/// Write a number of consecutive image view elements.
|
||||
#[inline]
|
||||
pub fn image_view_array(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
elements: impl IntoIterator<Item = Arc<dyn ImageViewAbstract>>,
|
||||
) -> Self {
|
||||
let elements: SmallVec<_> = elements.into_iter().collect();
|
||||
assert!(!elements.is_empty());
|
||||
Self {
|
||||
binding,
|
||||
first_array_element,
|
||||
elements: WriteDescriptorSetElements::ImageView(elements),
|
||||
}
|
||||
}
|
||||
|
||||
/// Write a single image view and sampler to array element 0.
|
||||
#[inline]
|
||||
pub fn image_view_sampler(
|
||||
binding: u32,
|
||||
image_view: Arc<dyn ImageViewAbstract>,
|
||||
sampler: Arc<Sampler>,
|
||||
) -> Self {
|
||||
Self::image_view_sampler_array(binding, 0, [(image_view, sampler)])
|
||||
}
|
||||
|
||||
/// Write a number of consecutive image view and sampler elements.
|
||||
#[inline]
|
||||
pub fn image_view_sampler_array(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
elements: impl IntoIterator<Item = (Arc<dyn ImageViewAbstract>, Arc<Sampler>)>,
|
||||
) -> Self {
|
||||
let elements: SmallVec<_> = elements.into_iter().collect();
|
||||
assert!(!elements.is_empty());
|
||||
Self {
|
||||
binding,
|
||||
first_array_element,
|
||||
elements: WriteDescriptorSetElements::ImageViewSampler(elements),
|
||||
}
|
||||
}
|
||||
|
||||
/// Write a single sampler to array element 0.
|
||||
#[inline]
|
||||
pub fn sampler(binding: u32, sampler: Arc<Sampler>) -> Self {
|
||||
Self::sampler_array(binding, 0, [sampler])
|
||||
}
|
||||
|
||||
/// Write a number of consecutive sampler elements.
|
||||
#[inline]
|
||||
pub fn sampler_array(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
elements: impl IntoIterator<Item = Arc<Sampler>>,
|
||||
) -> Self {
|
||||
let elements: SmallVec<_> = elements.into_iter().collect();
|
||||
assert!(!elements.is_empty());
|
||||
Self {
|
||||
binding,
|
||||
first_array_element,
|
||||
elements: WriteDescriptorSetElements::Sampler(elements),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the binding number that is updated by this descriptor write.
|
||||
#[inline]
|
||||
pub fn binding(&self) -> u32 {
|
||||
self.binding
|
||||
}
|
||||
|
||||
/// Returns the first array element in the binding that is updated by this descriptor write.
|
||||
#[inline]
|
||||
pub fn first_array_element(&self) -> u32 {
|
||||
self.first_array_element
|
||||
}
|
||||
|
||||
/// Returns a reference to the elements held by this descriptor write.
|
||||
#[inline]
|
||||
pub fn elements(&self) -> &WriteDescriptorSetElements {
|
||||
&self.elements
|
||||
}
|
||||
|
||||
pub(crate) fn to_vulkan_info(&self, descriptor_type: DescriptorType) -> DescriptorWriteInfo {
|
||||
match &self.elements {
|
||||
WriteDescriptorSetElements::None(num_elements) => {
|
||||
debug_assert!(matches!(descriptor_type, DescriptorType::Sampler));
|
||||
DescriptorWriteInfo::Image(
|
||||
std::iter::repeat_with(|| ash::vk::DescriptorImageInfo {
|
||||
sampler: ash::vk::Sampler::null(),
|
||||
image_view: ash::vk::ImageView::null(),
|
||||
image_layout: ash::vk::ImageLayout::UNDEFINED,
|
||||
})
|
||||
.take(*num_elements as usize)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
WriteDescriptorSetElements::Buffer(elements) => {
|
||||
debug_assert!(matches!(
|
||||
descriptor_type,
|
||||
DescriptorType::UniformBuffer
|
||||
| DescriptorType::StorageBuffer
|
||||
| DescriptorType::UniformBufferDynamic
|
||||
| DescriptorType::StorageBufferDynamic
|
||||
));
|
||||
DescriptorWriteInfo::Buffer(
|
||||
elements
|
||||
.iter()
|
||||
.map(|buffer| {
|
||||
let size = buffer.size();
|
||||
let BufferInner { buffer, offset } = buffer.inner();
|
||||
|
||||
debug_assert_eq!(
|
||||
offset
|
||||
% buffer
|
||||
.device()
|
||||
.physical_device()
|
||||
.properties()
|
||||
.min_storage_buffer_offset_alignment,
|
||||
0
|
||||
);
|
||||
debug_assert!(
|
||||
size <= buffer
|
||||
.device()
|
||||
.physical_device()
|
||||
.properties()
|
||||
.max_storage_buffer_range
|
||||
as DeviceSize
|
||||
);
|
||||
ash::vk::DescriptorBufferInfo {
|
||||
buffer: buffer.internal_object(),
|
||||
offset,
|
||||
range: size,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
WriteDescriptorSetElements::BufferView(elements) => {
|
||||
debug_assert!(matches!(
|
||||
descriptor_type,
|
||||
DescriptorType::UniformTexelBuffer | DescriptorType::StorageTexelBuffer
|
||||
));
|
||||
DescriptorWriteInfo::BufferView(
|
||||
elements
|
||||
.iter()
|
||||
.map(|buffer_view| buffer_view.inner())
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
WriteDescriptorSetElements::ImageView(elements) => {
|
||||
// Note: combined image sampler can occur with immutable samplers
|
||||
debug_assert!(matches!(
|
||||
descriptor_type,
|
||||
DescriptorType::CombinedImageSampler
|
||||
| DescriptorType::SampledImage
|
||||
| DescriptorType::StorageImage
|
||||
| DescriptorType::InputAttachment
|
||||
));
|
||||
DescriptorWriteInfo::Image(
|
||||
elements
|
||||
.iter()
|
||||
.map(|image_view| {
|
||||
let layouts = image_view.image().descriptor_layouts().expect(
|
||||
"descriptor_layouts must return Some when used in an image view",
|
||||
);
|
||||
ash::vk::DescriptorImageInfo {
|
||||
sampler: ash::vk::Sampler::null(),
|
||||
image_view: image_view.inner().internal_object(),
|
||||
image_layout: layouts.layout_for(descriptor_type).into(),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
WriteDescriptorSetElements::ImageViewSampler(elements) => {
|
||||
debug_assert!(matches!(
|
||||
descriptor_type,
|
||||
DescriptorType::CombinedImageSampler
|
||||
));
|
||||
DescriptorWriteInfo::Image(
|
||||
elements
|
||||
.iter()
|
||||
.map(|(image_view, sampler)| {
|
||||
let layouts = image_view.image().descriptor_layouts().expect(
|
||||
"descriptor_layouts must return Some when used in an image view",
|
||||
);
|
||||
ash::vk::DescriptorImageInfo {
|
||||
sampler: sampler.internal_object(),
|
||||
image_view: image_view.inner().internal_object(),
|
||||
image_layout: layouts.layout_for(descriptor_type).into(),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
WriteDescriptorSetElements::Sampler(elements) => {
|
||||
debug_assert!(matches!(descriptor_type, DescriptorType::Sampler));
|
||||
DescriptorWriteInfo::Image(
|
||||
elements
|
||||
.iter()
|
||||
.map(|sampler| ash::vk::DescriptorImageInfo {
|
||||
sampler: sampler.internal_object(),
|
||||
image_view: ash::vk::ImageView::null(),
|
||||
image_layout: ash::vk::ImageLayout::UNDEFINED,
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_vulkan(
|
||||
&self,
|
||||
dst_set: ash::vk::DescriptorSet,
|
||||
descriptor_type: DescriptorType,
|
||||
) -> ash::vk::WriteDescriptorSet {
|
||||
ash::vk::WriteDescriptorSet {
|
||||
dst_set,
|
||||
dst_binding: self.binding,
|
||||
dst_array_element: self.first_array_element,
|
||||
descriptor_count: 0,
|
||||
descriptor_type: descriptor_type.into(),
|
||||
p_image_info: ptr::null(),
|
||||
p_buffer_info: ptr::null(),
|
||||
p_texel_buffer_view: ptr::null(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The elements held by a `WriteDescriptorSet`.
|
||||
pub enum WriteDescriptorSetElements {
|
||||
None(u32),
|
||||
Buffer(SmallVec<[Arc<dyn BufferAccess>; 1]>),
|
||||
BufferView(SmallVec<[Arc<dyn BufferViewAbstract>; 1]>),
|
||||
ImageView(SmallVec<[Arc<dyn ImageViewAbstract>; 1]>),
|
||||
ImageViewSampler(SmallVec<[(Arc<dyn ImageViewAbstract>, Arc<Sampler>); 1]>),
|
||||
Sampler(SmallVec<[Arc<Sampler>; 1]>),
|
||||
}
|
||||
|
||||
impl WriteDescriptorSetElements {
|
||||
/// Returns the number of elements.
|
||||
#[inline]
|
||||
pub fn len(&self) -> u32 {
|
||||
match self {
|
||||
Self::None(num_elements) => *num_elements,
|
||||
Self::Buffer(elements) => elements.len() as u32,
|
||||
Self::BufferView(elements) => elements.len() as u32,
|
||||
Self::ImageView(elements) => elements.len() as u32,
|
||||
Self::ImageViewSampler(elements) => elements.len() as u32,
|
||||
Self::Sampler(elements) => elements.len() as u32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) enum DescriptorWriteInfo {
|
||||
Image(SmallVec<[ash::vk::DescriptorImageInfo; 1]>),
|
||||
Buffer(SmallVec<[ash::vk::DescriptorBufferInfo; 1]>),
|
||||
BufferView(SmallVec<[ash::vk::BufferView; 1]>),
|
||||
}
|
||||
|
||||
impl DescriptorWriteInfo {
|
||||
fn set_info(&self, write: &mut ash::vk::WriteDescriptorSet) {
|
||||
match self {
|
||||
DescriptorWriteInfo::Image(info) => {
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_image_info = info.as_ptr();
|
||||
}
|
||||
DescriptorWriteInfo::Buffer(info) => {
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_buffer_info = info.as_ptr();
|
||||
}
|
||||
DescriptorWriteInfo::BufferView(info) => {
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_texel_buffer_view = info.as_ptr();
|
||||
}
|
||||
}
|
||||
|
||||
debug_assert!(write.descriptor_count != 0);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn check_descriptor_write<'a>(
|
||||
write: &WriteDescriptorSet,
|
||||
layout: &'a DescriptorSetLayout,
|
||||
variable_descriptor_count: u32,
|
||||
) -> Result<&'a DescriptorDesc, DescriptorSetUpdateError> {
|
||||
let layout_binding = match layout.desc().descriptor(write.binding()) {
|
||||
Some(binding) => binding,
|
||||
None => {
|
||||
return Err(DescriptorSetUpdateError::InvalidBinding {
|
||||
binding: write.binding(),
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
let max_descriptor_count = if layout_binding.variable_count {
|
||||
variable_descriptor_count
|
||||
} else {
|
||||
layout_binding.descriptor_count
|
||||
};
|
||||
|
||||
let elements = write.elements();
|
||||
let num_elements = elements.len();
|
||||
debug_assert!(num_elements != 0);
|
||||
|
||||
let descriptor_range_start = write.first_array_element();
|
||||
let descriptor_range_end = descriptor_range_start + num_elements;
|
||||
|
||||
if descriptor_range_end > max_descriptor_count {
|
||||
return Err(DescriptorSetUpdateError::ArrayIndexOutOfBounds {
|
||||
binding: write.binding(),
|
||||
available_count: max_descriptor_count,
|
||||
written_count: descriptor_range_end,
|
||||
});
|
||||
}
|
||||
|
||||
match elements {
|
||||
WriteDescriptorSetElements::None(num_elements) => match layout_binding.ty {
|
||||
DescriptorType::Sampler
|
||||
if layout.desc().is_push_descriptor()
|
||||
&& !layout_binding.immutable_samplers.is_empty() => {}
|
||||
_ => {
|
||||
return Err(DescriptorSetUpdateError::IncompatibleDescriptorType {
|
||||
binding: write.binding(),
|
||||
})
|
||||
}
|
||||
},
|
||||
WriteDescriptorSetElements::Buffer(elements) => {
|
||||
match layout_binding.ty {
|
||||
DescriptorType::StorageBuffer | DescriptorType::StorageBufferDynamic => {
|
||||
for (index, buffer) in elements.iter().enumerate() {
|
||||
assert_eq!(
|
||||
buffer.device().internal_object(),
|
||||
layout.device().internal_object(),
|
||||
);
|
||||
|
||||
if !buffer.inner().buffer.usage().storage_buffer {
|
||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||
binding: write.binding(),
|
||||
index: descriptor_range_start + index as u32,
|
||||
usage: "storage_buffer",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
DescriptorType::UniformBuffer | DescriptorType::UniformBufferDynamic => {
|
||||
for (index, buffer) in elements.iter().enumerate() {
|
||||
assert_eq!(
|
||||
buffer.device().internal_object(),
|
||||
layout.device().internal_object(),
|
||||
);
|
||||
|
||||
if !buffer.inner().buffer.usage().uniform_buffer {
|
||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||
binding: write.binding(),
|
||||
index: descriptor_range_start + index as u32,
|
||||
usage: "uniform_buffer",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(DescriptorSetUpdateError::IncompatibleDescriptorType {
|
||||
binding: write.binding(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Note that the buffer content is not checked. This is technically not unsafe as
|
||||
// long as the data in the buffer has no invalid memory representation (ie. no
|
||||
// bool, no enum, no pointer, no str) and as long as the robust buffer access
|
||||
// feature is enabled.
|
||||
// TODO: this is not checked ^
|
||||
|
||||
// TODO: eventually shouldn't be an assert ; for now robust_buffer_access is always
|
||||
// enabled so this assert should never fail in practice, but we put it anyway
|
||||
// in case we forget to adjust this code
|
||||
assert!(layout.device().enabled_features().robust_buffer_access);
|
||||
}
|
||||
WriteDescriptorSetElements::BufferView(elements) => {
|
||||
match layout_binding.ty {
|
||||
DescriptorType::StorageTexelBuffer => {
|
||||
for (index, buffer_view) in elements.iter().enumerate() {
|
||||
assert_eq!(
|
||||
buffer_view.device().internal_object(),
|
||||
layout.device().internal_object(),
|
||||
);
|
||||
|
||||
// TODO: storage_texel_buffer_atomic
|
||||
if !buffer_view
|
||||
.buffer()
|
||||
.inner()
|
||||
.buffer
|
||||
.usage()
|
||||
.storage_texel_buffer
|
||||
{
|
||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||
binding: write.binding(),
|
||||
index: descriptor_range_start + index as u32,
|
||||
usage: "storage_texel_buffer",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
DescriptorType::UniformTexelBuffer => {
|
||||
for (index, buffer_view) in elements.iter().enumerate() {
|
||||
assert_eq!(
|
||||
buffer_view.device().internal_object(),
|
||||
layout.device().internal_object(),
|
||||
);
|
||||
|
||||
if !buffer_view
|
||||
.buffer()
|
||||
.inner()
|
||||
.buffer
|
||||
.usage()
|
||||
.uniform_texel_buffer
|
||||
{
|
||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||
binding: write.binding(),
|
||||
index: descriptor_range_start + index as u32,
|
||||
usage: "uniform_texel_buffer",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(DescriptorSetUpdateError::IncompatibleDescriptorType {
|
||||
binding: write.binding(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
WriteDescriptorSetElements::ImageView(elements) => match layout_binding.ty {
|
||||
DescriptorType::CombinedImageSampler
|
||||
if !layout_binding.immutable_samplers.is_empty() =>
|
||||
{
|
||||
let immutable_samplers = &layout_binding.immutable_samplers
|
||||
[descriptor_range_start as usize..descriptor_range_end as usize];
|
||||
|
||||
for (index, (image_view, sampler)) in
|
||||
elements.iter().zip(immutable_samplers).enumerate()
|
||||
{
|
||||
assert_eq!(
|
||||
image_view.device().internal_object(),
|
||||
layout.device().internal_object(),
|
||||
);
|
||||
|
||||
if !image_view.image().inner().image.usage().sampled {
|
||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||
binding: write.binding(),
|
||||
index: descriptor_range_start + index as u32,
|
||||
usage: "sampled",
|
||||
});
|
||||
}
|
||||
|
||||
if !image_view.can_be_sampled(sampler) {
|
||||
return Err(DescriptorSetUpdateError::ImageViewIncompatibleSampler {
|
||||
binding: write.binding(),
|
||||
index: descriptor_range_start + index as u32,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
DescriptorType::SampledImage => {
|
||||
for (index, image_view) in elements.iter().enumerate() {
|
||||
assert_eq!(
|
||||
image_view.device().internal_object(),
|
||||
layout.device().internal_object(),
|
||||
);
|
||||
|
||||
if !image_view.image().inner().image.usage().sampled {
|
||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||
binding: write.binding(),
|
||||
index: descriptor_range_start + index as u32,
|
||||
usage: "sampled",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
DescriptorType::StorageImage => {
|
||||
for (index, image_view) in elements.iter().enumerate() {
|
||||
assert_eq!(
|
||||
image_view.device().internal_object(),
|
||||
layout.device().internal_object(),
|
||||
);
|
||||
|
||||
if !image_view.image().inner().image.usage().storage {
|
||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||
binding: write.binding(),
|
||||
index: descriptor_range_start + index as u32,
|
||||
usage: "storage",
|
||||
});
|
||||
}
|
||||
|
||||
if !image_view.component_mapping().is_identity() {
|
||||
return Err(DescriptorSetUpdateError::ImageViewNotIdentitySwizzled {
|
||||
binding: write.binding(),
|
||||
index: descriptor_range_start + index as u32,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
DescriptorType::InputAttachment => {
|
||||
for (index, image_view) in elements.iter().enumerate() {
|
||||
assert_eq!(
|
||||
image_view.device().internal_object(),
|
||||
layout.device().internal_object(),
|
||||
);
|
||||
|
||||
if !image_view.image().inner().image.usage().input_attachment {
|
||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||
binding: write.binding(),
|
||||
index: descriptor_range_start + index as u32,
|
||||
usage: "input_attachment",
|
||||
});
|
||||
}
|
||||
|
||||
if !image_view.component_mapping().is_identity() {
|
||||
return Err(DescriptorSetUpdateError::ImageViewNotIdentitySwizzled {
|
||||
binding: write.binding(),
|
||||
index: descriptor_range_start + index as u32,
|
||||
});
|
||||
}
|
||||
|
||||
let image_layers = image_view.array_layers();
|
||||
let num_layers = image_layers.end - image_layers.start;
|
||||
|
||||
if image_view.ty().is_arrayed() {
|
||||
return Err(DescriptorSetUpdateError::ImageViewIsArrayed {
|
||||
binding: write.binding(),
|
||||
index: descriptor_range_start + index as u32,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(DescriptorSetUpdateError::IncompatibleDescriptorType {
|
||||
binding: write.binding(),
|
||||
})
|
||||
}
|
||||
},
|
||||
WriteDescriptorSetElements::ImageViewSampler(elements) => match layout_binding.ty {
|
||||
DescriptorType::CombinedImageSampler => {
|
||||
if !layout_binding.immutable_samplers.is_empty() {
|
||||
return Err(DescriptorSetUpdateError::SamplerIsImmutable {
|
||||
binding: write.binding(),
|
||||
});
|
||||
}
|
||||
|
||||
for (index, (image_view, sampler)) in elements.iter().enumerate() {
|
||||
assert_eq!(
|
||||
image_view.device().internal_object(),
|
||||
layout.device().internal_object(),
|
||||
);
|
||||
assert_eq!(
|
||||
sampler.device().internal_object(),
|
||||
layout.device().internal_object(),
|
||||
);
|
||||
|
||||
if !image_view.image().inner().image.usage().sampled {
|
||||
return Err(DescriptorSetUpdateError::MissingUsage {
|
||||
binding: write.binding(),
|
||||
index: descriptor_range_start + index as u32,
|
||||
usage: "sampled",
|
||||
});
|
||||
}
|
||||
|
||||
if !image_view.can_be_sampled(&sampler) {
|
||||
return Err(DescriptorSetUpdateError::ImageViewIncompatibleSampler {
|
||||
binding: write.binding(),
|
||||
index: descriptor_range_start + index as u32,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(DescriptorSetUpdateError::IncompatibleDescriptorType {
|
||||
binding: write.binding(),
|
||||
})
|
||||
}
|
||||
},
|
||||
WriteDescriptorSetElements::Sampler(elements) => match layout_binding.ty {
|
||||
DescriptorType::Sampler => {
|
||||
if !layout_binding.immutable_samplers.is_empty() {
|
||||
return Err(DescriptorSetUpdateError::SamplerIsImmutable {
|
||||
binding: write.binding(),
|
||||
});
|
||||
}
|
||||
|
||||
for sampler in elements {
|
||||
assert_eq!(
|
||||
sampler.device().internal_object(),
|
||||
layout.device().internal_object(),
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(DescriptorSetUpdateError::IncompatibleDescriptorType {
|
||||
binding: write.binding(),
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Ok(layout_binding)
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum DescriptorSetUpdateError {
|
||||
/// Tried to write more elements than were available in a binding.
|
||||
ArrayIndexOutOfBounds {
|
||||
/// Binding that is affected.
|
||||
binding: u32,
|
||||
/// Number of available descriptors in the binding.
|
||||
available_count: u32,
|
||||
/// The number of descriptors that were in the update.
|
||||
written_count: u32,
|
||||
},
|
||||
|
||||
/// Tried to write an image view of an arrayed type to a descriptor type that does not support
|
||||
/// it.
|
||||
ImageViewIsArrayed { binding: u32, index: u32 },
|
||||
|
||||
/// Tried to write an image view that was not compatible with the sampler that was provided as
|
||||
/// part of the update or immutably in the layout.
|
||||
ImageViewIncompatibleSampler { binding: u32, index: u32 },
|
||||
|
||||
/// Tried to write an image view to a descriptor type that requires it to be identity swizzled,
|
||||
/// but it was not.
|
||||
ImageViewNotIdentitySwizzled { binding: u32, index: u32 },
|
||||
|
||||
/// Tried to write an element type that was not compatible with the descriptor type in the
|
||||
/// layout.
|
||||
IncompatibleDescriptorType { binding: u32 },
|
||||
|
||||
/// Tried to write to a nonexistent binding.
|
||||
InvalidBinding { binding: u32 },
|
||||
|
||||
/// A resource was missing a usage flag that was required.
|
||||
MissingUsage {
|
||||
binding: u32,
|
||||
index: u32,
|
||||
usage: &'static str,
|
||||
},
|
||||
|
||||
/// Tried to write a sampler to a binding with immutable samplers.
|
||||
SamplerIsImmutable { binding: u32 },
|
||||
}
|
||||
|
||||
impl std::error::Error for DescriptorSetUpdateError {}
|
||||
|
||||
impl std::fmt::Display for DescriptorSetUpdateError {
|
||||
#[inline]
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
match self {
|
||||
Self::ArrayIndexOutOfBounds {
|
||||
binding,
|
||||
available_count,
|
||||
written_count,
|
||||
} => write!(
|
||||
fmt,
|
||||
"tried to write up to element {} to binding {}, but only {} descriptors are available",
|
||||
written_count, binding, available_count,
|
||||
),
|
||||
Self::ImageViewIsArrayed { binding, index } => write!(
|
||||
fmt,
|
||||
"tried to write an image view of an arrayed type to binding {} index {}, but this binding has a descriptor type that does not support arrayed image views",
|
||||
binding, index,
|
||||
),
|
||||
Self::ImageViewIncompatibleSampler { binding, index } => write!(
|
||||
fmt,
|
||||
"tried to write an image view to binding {} index {}, that was not compatible with the sampler that was provided as part of the update or immutably in the layout",
|
||||
binding, index,
|
||||
),
|
||||
Self::ImageViewNotIdentitySwizzled { binding, index } => write!(
|
||||
fmt,
|
||||
"tried to write an image view with non-identity swizzling to binding {} index {}, but this binding has a descriptor type that requires it to be identity swizzled",
|
||||
binding, index,
|
||||
),
|
||||
Self::IncompatibleDescriptorType { binding } => write!(
|
||||
fmt,
|
||||
"tried to write a resource to binding {} whose type was not compatible with the descriptor type",
|
||||
binding,
|
||||
),
|
||||
Self::InvalidBinding { binding } => write!(
|
||||
fmt,
|
||||
"tried to write to a nonexistent binding {}",
|
||||
binding,
|
||||
),
|
||||
Self::MissingUsage {
|
||||
binding,
|
||||
index,
|
||||
usage,
|
||||
} => write!(
|
||||
fmt,
|
||||
"tried to write a resource to binding {} index {} that did not have the required usage {} enabled",
|
||||
binding, index, usage,
|
||||
),
|
||||
Self::SamplerIsImmutable { binding } => write!(
|
||||
fmt,
|
||||
"tried to write a sampler to binding {}, which already contains immutable samplers in the descriptor set layout",
|
||||
binding,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@
|
||||
|
||||
use crate::check_errors;
|
||||
use crate::device::Device;
|
||||
use crate::device::DeviceOwned;
|
||||
use crate::format::Format;
|
||||
use crate::image::sys::UnsafeImage;
|
||||
use crate::image::ImageAccess;
|
||||
@ -89,6 +90,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<I> DeviceOwned for ImageView<I>
|
||||
where
|
||||
I: ImageAccess,
|
||||
{
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.inner.device()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ImageViewBuilder<I> {
|
||||
array_layers: Range<u32>,
|
||||
@ -436,6 +446,12 @@ unsafe impl VulkanObject for UnsafeImageView {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl DeviceOwned for UnsafeImageView {
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
&self.device
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for UnsafeImageView {
|
||||
#[inline]
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
@ -581,7 +597,7 @@ impl Default for ComponentSwizzle {
|
||||
}
|
||||
|
||||
/// Trait for types that represent the GPU can access an image view.
|
||||
pub unsafe trait ImageViewAbstract: Send + Sync {
|
||||
pub unsafe trait ImageViewAbstract: DeviceOwned + Send + Sync {
|
||||
/// Returns the wrapped image that this image view was created from.
|
||||
fn image(&self) -> Arc<dyn ImageAccess>;
|
||||
|
||||
|
@ -393,6 +393,7 @@ mod tests {
|
||||
use crate::command_buffer::AutoCommandBufferBuilder;
|
||||
use crate::command_buffer::CommandBufferUsage;
|
||||
use crate::descriptor_set::PersistentDescriptorSet;
|
||||
use crate::descriptor_set::WriteDescriptorSet;
|
||||
use crate::pipeline::ComputePipeline;
|
||||
use crate::pipeline::Pipeline;
|
||||
use crate::pipeline::PipelineBindPoint;
|
||||
@ -481,12 +482,17 @@ mod tests {
|
||||
|
||||
let data_buffer =
|
||||
CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), false, 0).unwrap();
|
||||
let layout = pipeline.layout().descriptor_set_layouts().get(0).unwrap();
|
||||
let mut builder = PersistentDescriptorSet::start(layout.clone());
|
||||
|
||||
builder.add_buffer(data_buffer.clone()).unwrap();
|
||||
|
||||
let set = builder.build().unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
pipeline
|
||||
.layout()
|
||||
.descriptor_set_layouts()
|
||||
.get(0)
|
||||
.unwrap()
|
||||
.clone(),
|
||||
[WriteDescriptorSet::buffer(0, data_buffer.clone())],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
|
Loading…
Reference in New Issue
Block a user