// Copyright 2018 Jacob Lifshay
// allow unneeded_field_pattern to ensure fields aren't accidently missed
-#![cfg_attr(
- feature = "cargo-clippy",
- allow(clippy::unneeded_field_pattern)
-)]
+#![cfg_attr(feature = "cargo-clippy", allow(clippy::unneeded_field_pattern))]
use api;
use buffer::{Buffer, BufferMemory};
use constants::*;
+use descriptor_set::{
+ Descriptor, DescriptorLayout, DescriptorPool, DescriptorSet, DescriptorSetLayout,
+ DescriptorWriteArg,
+};
use device_memory::{
DeviceMemory, DeviceMemoryAllocation, DeviceMemoryHeap, DeviceMemoryHeaps, DeviceMemoryLayout,
DeviceMemoryType, DeviceMemoryTypes,
};
use enum_map::EnumMap;
use handle::{Handle, MutHandle, OwnedHandle, SharedHandle};
-use image::{Image, ImageMemory, ImageMultisampleCount, ImageProperties, SupportedTilings};
+use image::{
+ ComponentMapping, Image, ImageMemory, ImageMultisampleCount, ImageProperties, ImageView,
+ ImageViewType, SupportedTilings,
+};
+use render_pass::RenderPass;
use sampler;
use sampler::Sampler;
use shader_module::ShaderModule;
} => {
$(let mut $name: *const $var_type = null();)*
parse_next_chain_const(
- $root as *const api::VkBaseInStructure,
+ $root as *const _ as *const api::VkBaseInStructure,
$root_type,
&[$(($struct_type, &mut $name as *mut *const $var_type as *mut *const api::VkBaseInStructure)),*]
);
} => {
$(let mut $name: *mut $var_type = null_mut();)*
parse_next_chain_mut(
- $root as *mut api::VkBaseOutStructure,
+ $root as *mut _ as *mut api::VkBaseOutStructure,
$root_type,
&[$(($struct_type, &mut $name as *mut *mut $var_type as *mut *mut api::VkBaseOutStructure)),*]
);
Device,
}
-#[cfg_attr(
- feature = "cargo-clippy",
- allow(clippy::cyclomatic_complexity)
-)]
+#[cfg_attr(feature = "cargo-clippy", allow(clippy::cyclomatic_complexity))]
fn get_proc_address(
name: *const c_char,
scope: GetProcAddressScope,
let mut queue_counts: Vec<_> = Vec::new();
for queue_create_info in queue_create_infos {
parse_next_chain_const!{
- queue_create_info as *const api::VkDeviceQueueCreateInfo,
+ queue_create_info,
root = api::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
}
let api::VkDeviceQueueCreateInfo {
queue_count: u32,
) {
parse_next_chain_mut!{
- queue_family_properties as *mut api::VkQueueFamilyProperties2,
+ queue_family_properties,
root = api::VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
}
queue_family_properties.queueFamilyProperties = api::VkQueueFamilyProperties {
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkCreateImageView(
_device: api::VkDevice,
- _pCreateInfo: *const api::VkImageViewCreateInfo,
- _pAllocator: *const api::VkAllocationCallbacks,
- _pView: *mut api::VkImageView,
+ create_info: *const api::VkImageViewCreateInfo,
+ _allocator: *const api::VkAllocationCallbacks,
+ view: *mut api::VkImageView,
) -> api::VkResult {
- unimplemented!()
+ parse_next_chain_const!{
+ create_info,
+ root = api::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ }
+ let create_info = &*create_info;
+ let new_view = OwnedHandle::<api::VkImageView>::new(ImageView {
+ image: SharedHandle::from(create_info.image).unwrap(),
+ view_type: ImageViewType::from(create_info.viewType),
+ format: create_info.format,
+ component_mapping: ComponentMapping::from(create_info.components).unwrap(),
+ subresource_range: create_info.subresourceRange,
+ });
+ *view = new_view.take();
+ api::VK_SUCCESS
}
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkDestroyImageView(
_device: api::VkDevice,
- _imageView: api::VkImageView,
- _pAllocator: *const api::VkAllocationCallbacks,
+ image_view: api::VkImageView,
+ _allocator: *const api::VkAllocationCallbacks,
) {
- unimplemented!()
+ OwnedHandle::from(image_view);
}
#[allow(non_snake_case)]
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkCreateDescriptorSetLayout(
_device: api::VkDevice,
- _pCreateInfo: *const api::VkDescriptorSetLayoutCreateInfo,
- _pAllocator: *const api::VkAllocationCallbacks,
- _pSetLayout: *mut api::VkDescriptorSetLayout,
+ create_info: *const api::VkDescriptorSetLayoutCreateInfo,
+ _allocator: *const api::VkAllocationCallbacks,
+ set_layout: *mut api::VkDescriptorSetLayout,
) -> api::VkResult {
- unimplemented!()
+ parse_next_chain_const!{
+ create_info,
+ root = api::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ }
+ let create_info = &*create_info;
+ let bindings = match create_info.bindingCount {
+ 0 => &[],
+ binding_count => slice::from_raw_parts(create_info.pBindings, binding_count as usize),
+ };
+ let max_binding = bindings.iter().map(|v| v.binding).max().unwrap_or(0) as usize;
+ let mut bindings_map: Vec<Option<DescriptorLayout>> = (0..=max_binding).map(|_| None).collect();
+ for binding in bindings {
+ let bindings_map_entry = &mut bindings_map[binding.binding as usize];
+ assert!(
+ bindings_map_entry.is_none(),
+ "duplicate binding: {}",
+ binding.binding
+ );
+ *bindings_map_entry = Some(DescriptorLayout::from(binding));
+ }
+ *set_layout = OwnedHandle::<api::VkDescriptorSetLayout>::new(DescriptorSetLayout {
+ bindings: bindings_map,
+ })
+ .take();
+ api::VK_SUCCESS
}
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkDestroyDescriptorSetLayout(
_device: api::VkDevice,
- _descriptorSetLayout: api::VkDescriptorSetLayout,
- _pAllocator: *const api::VkAllocationCallbacks,
+ descriptor_set_layout: api::VkDescriptorSetLayout,
+ _allocator: *const api::VkAllocationCallbacks,
) {
- unimplemented!()
+ OwnedHandle::from(descriptor_set_layout);
}
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkCreateDescriptorPool(
_device: api::VkDevice,
- _pCreateInfo: *const api::VkDescriptorPoolCreateInfo,
- _pAllocator: *const api::VkAllocationCallbacks,
- _pDescriptorPool: *mut api::VkDescriptorPool,
+ create_info: *const api::VkDescriptorPoolCreateInfo,
+ _allocator: *const api::VkAllocationCallbacks,
+ descriptor_pool: *mut api::VkDescriptorPool,
) -> api::VkResult {
- unimplemented!()
+ parse_next_chain_const!{
+ create_info,
+ root = api::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
+ }
+ *descriptor_pool = OwnedHandle::<api::VkDescriptorPool>::new(DescriptorPool::new()).take();
+ api::VK_SUCCESS
}
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkDestroyDescriptorPool(
_device: api::VkDevice,
- _descriptorPool: api::VkDescriptorPool,
- _pAllocator: *const api::VkAllocationCallbacks,
+ descriptor_pool: api::VkDescriptorPool,
+ _allocator: *const api::VkAllocationCallbacks,
) {
- unimplemented!()
+ OwnedHandle::from(descriptor_pool);
}
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkResetDescriptorPool(
_device: api::VkDevice,
- _descriptorPool: api::VkDescriptorPool,
+ descriptor_pool: api::VkDescriptorPool,
_flags: api::VkDescriptorPoolResetFlags,
) -> api::VkResult {
- unimplemented!()
+ MutHandle::from(descriptor_pool).unwrap().reset();
+ api::VK_SUCCESS
}
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkAllocateDescriptorSets(
_device: api::VkDevice,
- _pAllocateInfo: *const api::VkDescriptorSetAllocateInfo,
- _pDescriptorSets: *mut api::VkDescriptorSet,
+ allocate_info: *const api::VkDescriptorSetAllocateInfo,
+ descriptor_sets: *mut api::VkDescriptorSet,
) -> api::VkResult {
- unimplemented!()
+ parse_next_chain_const!{
+ allocate_info,
+ root = api::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ }
+ let allocate_info = &*allocate_info;
+ let mut descriptor_pool = MutHandle::from(allocate_info.descriptorPool).unwrap();
+ let descriptor_sets =
+ slice::from_raw_parts_mut(descriptor_sets, allocate_info.descriptorSetCount as usize);
+ let descriptor_set_layouts = slice::from_raw_parts(
+ allocate_info.pSetLayouts,
+ allocate_info.descriptorSetCount as usize,
+ );
+ descriptor_pool.allocate(
+ descriptor_set_layouts
+ .iter()
+ .map(|descriptor_set_layout| DescriptorSet {
+ bindings: SharedHandle::from(*descriptor_set_layout)
+ .unwrap()
+ .bindings
+ .iter()
+ .map(|layout| layout.as_ref().map(Descriptor::from))
+ .collect(),
+ }),
+ descriptor_sets,
+ );
+ api::VK_SUCCESS
}
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkFreeDescriptorSets(
_device: api::VkDevice,
- _descriptorPool: api::VkDescriptorPool,
- _descriptorSetCount: u32,
- _pDescriptorSets: *const api::VkDescriptorSet,
+ descriptor_pool: api::VkDescriptorPool,
+ descriptor_set_count: u32,
+ descriptor_sets: *const api::VkDescriptorSet,
) -> api::VkResult {
- unimplemented!()
+ let mut descriptor_pool = MutHandle::from(descriptor_pool).unwrap();
+ let descriptor_sets = slice::from_raw_parts(descriptor_sets, descriptor_set_count as usize);
+ descriptor_pool.free(descriptor_sets);
+ api::VK_SUCCESS
}
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkUpdateDescriptorSets(
_device: api::VkDevice,
- _descriptorWriteCount: u32,
- _pDescriptorWrites: *const api::VkWriteDescriptorSet,
- _descriptorCopyCount: u32,
- _pDescriptorCopies: *const api::VkCopyDescriptorSet,
-) {
- unimplemented!()
+ descriptor_write_count: u32,
+ descriptor_writes: *const api::VkWriteDescriptorSet,
+ descriptor_copy_count: u32,
+ descriptor_copies: *const api::VkCopyDescriptorSet,
+) {
+ let descriptor_writes =
+ slice::from_raw_parts(descriptor_writes, descriptor_write_count as usize);
+ let descriptor_copies =
+ slice::from_raw_parts(descriptor_copies, descriptor_copy_count as usize);
+ for descriptor_write in descriptor_writes {
+ parse_next_chain_const!{
+ descriptor_write,
+ root = api::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ }
+ let mut descriptor_set = MutHandle::from(descriptor_write.dstSet).unwrap();
+ let mut binding_index = descriptor_write.dstBinding as usize;
+ let mut elements = DescriptorWriteArg::from(descriptor_write);
+ let mut start_element = Some(descriptor_write.dstArrayElement as usize);
+ while elements.len() != 0 {
+ let binding = descriptor_set.bindings[binding_index].as_mut().unwrap();
+ binding_index += 1;
+ assert_eq!(binding.descriptor_type(), descriptor_write.descriptorType);
+ if binding.element_count() == 0 {
+ assert_eq!(start_element, None);
+ continue;
+ }
+ let start_element = start_element.take().unwrap_or(0);
+ let used_elements = elements
+ .len()
+ .min(binding.element_count().checked_sub(start_element).unwrap());
+ binding.write(start_element, elements.slice_to(..used_elements));
+ elements = elements.slice_from(used_elements..);
+ }
+ }
+ for descriptor_copy in descriptor_copies {
+ parse_next_chain_const!{
+ descriptor_copy,
+ root = api::VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET,
+ }
+ unimplemented!()
+ }
}
#[allow(non_snake_case)]
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkCreateRenderPass(
_device: api::VkDevice,
- _pCreateInfo: *const api::VkRenderPassCreateInfo,
- _pAllocator: *const api::VkAllocationCallbacks,
- _pRenderPass: *mut api::VkRenderPass,
+ create_info: *const api::VkRenderPassCreateInfo,
+ _allocator: *const api::VkAllocationCallbacks,
+ render_pass: *mut api::VkRenderPass,
) -> api::VkResult {
- unimplemented!()
+ parse_next_chain_const!{
+ create_info,
+ root = api::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+ }
+ // FIXME: finish implementing
+ *render_pass = OwnedHandle::<api::VkRenderPass>::new(RenderPass {}).take();
+ api::VK_SUCCESS
}
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkDestroyRenderPass(
_device: api::VkDevice,
- _renderPass: api::VkRenderPass,
- _pAllocator: *const api::VkAllocationCallbacks,
+ render_pass: api::VkRenderPass,
+ _allocator: *const api::VkAllocationCallbacks,
) {
- unimplemented!()
+ OwnedHandle::from(render_pass);
}
#[allow(non_snake_case)]
let bind_infos = slice::from_raw_parts(bind_infos, bind_info_count as usize);
for bind_info in bind_infos {
parse_next_chain_const!{
- bind_info as *const api::VkBindBufferMemoryInfo,
+ bind_info,
root = api::VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
device_group_info: api::VkBindBufferMemoryDeviceGroupInfo = api::VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO,
}
let bind_infos = slice::from_raw_parts(bind_infos, bind_info_count as usize);
for bind_info in bind_infos {
parse_next_chain_const!{
- bind_info as *const api::VkBindImageMemoryInfo,
+ bind_info,
root = api::VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
device_group_info: api::VkBindImageMemoryDeviceGroupInfo = api::VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO,
swapchain_info: api::VkBindImageMemorySwapchainInfoKHR = api::VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR,
iter::once(()),
|physical_device_group_properties, _| {
parse_next_chain_mut!{
- physical_device_group_properties as *mut api::VkPhysicalDeviceGroupProperties,
+ physical_device_group_properties,
root = api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES,
}
let mut physical_devices = [Handle::null(); api::VK_MAX_DEVICE_GROUP_SIZE as usize];
use api;
use handle::SharedHandle;
+#[derive(Debug)]
pub struct BufferMemory {
pub device_memory: SharedHandle<api::VkDeviceMemory>,
pub offset: usize,
}
+#[derive(Debug)]
pub struct Buffer {
pub size: usize,
pub memory: Option<BufferMemory>,
}
+
+#[derive(Debug)]
+pub struct BufferSlice {
+ pub buffer: SharedHandle<api::VkBuffer>,
+ pub offset: usize,
+ pub size: usize,
+}
+
+impl BufferSlice {
+ pub unsafe fn from(v: &api::VkDescriptorBufferInfo) -> Self {
+ let buffer = SharedHandle::from(v.buffer).unwrap();
+ assert!(v.offset < buffer.size as u64);
+ let offset = v.offset as usize;
+ let size = if v.range == api::VK_WHOLE_SIZE as u64 {
+ buffer.size - offset
+ } else {
+ assert!(v.range != 0);
+ assert!(v.range.checked_add(v.offset).unwrap() <= buffer.size as u64);
+ v.range as usize
+ };
+ Self {
+ buffer,
+ offset,
+ size,
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct BufferView {}
--- /dev/null
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// Copyright 2018 Jacob Lifshay
+
+use api;
+use buffer::BufferSlice;
+use handle::OwnedHandle;
+use handle::SharedHandle;
+use image;
+use std::ops;
+use std::slice;
+
+#[derive(Debug)]
+pub enum DescriptorLayout {
+ Sampler {
+ count: usize,
+ immutable_samplers: Option<Vec<SharedHandle<api::VkSampler>>>,
+ },
+ CombinedImageSampler {
+ count: usize,
+ immutable_samplers: Option<Vec<SharedHandle<api::VkSampler>>>,
+ },
+ SampledImage {
+ count: usize,
+ },
+ StorageImage {
+ count: usize,
+ },
+ UniformTexelBuffer {
+ count: usize,
+ },
+ StorageTexelBuffer {
+ count: usize,
+ },
+ UniformBuffer {
+ count: usize,
+ },
+ StorageBuffer {
+ count: usize,
+ },
+ UniformBufferDynamic {
+ count: usize,
+ },
+ StorageBufferDynamic {
+ count: usize,
+ },
+ InputAttachment {
+ count: usize,
+ },
+}
+
+impl DescriptorLayout {
+ #[allow(dead_code)]
+ pub fn count(&self) -> usize {
+ match *self {
+ DescriptorLayout::Sampler { count, .. } => count,
+ DescriptorLayout::CombinedImageSampler { count, .. } => count,
+ DescriptorLayout::SampledImage { count } => count,
+ DescriptorLayout::StorageImage { count } => count,
+ DescriptorLayout::UniformTexelBuffer { count } => count,
+ DescriptorLayout::StorageTexelBuffer { count } => count,
+ DescriptorLayout::UniformBuffer { count } => count,
+ DescriptorLayout::StorageBuffer { count } => count,
+ DescriptorLayout::UniformBufferDynamic { count } => count,
+ DescriptorLayout::StorageBufferDynamic { count } => count,
+ DescriptorLayout::InputAttachment { count } => count,
+ }
+ }
+ #[allow(dead_code)]
+ pub fn immutable_samplers(&self) -> Option<&[SharedHandle<api::VkSampler>]> {
+ match self {
+ DescriptorLayout::Sampler {
+ immutable_samplers: Some(immutable_samplers),
+ ..
+ } => Some(immutable_samplers),
+ DescriptorLayout::CombinedImageSampler {
+ immutable_samplers: Some(immutable_samplers),
+ ..
+ } => Some(immutable_samplers),
+ _ => None,
+ }
+ }
+ pub fn descriptor_type(&self) -> api::VkDescriptorType {
+ match self {
+ DescriptorLayout::Sampler { .. } => api::VK_DESCRIPTOR_TYPE_SAMPLER,
+ DescriptorLayout::CombinedImageSampler { .. } => {
+ api::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
+ }
+ DescriptorLayout::SampledImage { .. } => api::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
+ DescriptorLayout::StorageImage { .. } => api::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+ DescriptorLayout::UniformTexelBuffer { .. } => {
+ api::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
+ }
+ DescriptorLayout::StorageTexelBuffer { .. } => {
+ api::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
+ }
+ DescriptorLayout::UniformBuffer { .. } => api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ DescriptorLayout::StorageBuffer { .. } => api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+ DescriptorLayout::UniformBufferDynamic { .. } => {
+ api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
+ }
+ DescriptorLayout::StorageBufferDynamic { .. } => {
+ api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC
+ }
+ DescriptorLayout::InputAttachment { .. } => api::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
+ }
+ }
+ pub unsafe fn from(v: &api::VkDescriptorSetLayoutBinding) -> Self {
+ let get_immutable_samplers = || {
+ if v.pImmutableSamplers.is_null() {
+ None
+ } else {
+ let immutable_samplers =
+ slice::from_raw_parts(v.pImmutableSamplers, v.descriptorCount as usize);
+ Some(
+ immutable_samplers
+ .iter()
+ .map(|sampler| SharedHandle::from(*sampler).unwrap())
+ .collect(),
+ )
+ }
+ };
+ match v.descriptorType {
+ api::VK_DESCRIPTOR_TYPE_SAMPLER => DescriptorLayout::Sampler {
+ count: v.descriptorCount as usize,
+ immutable_samplers: get_immutable_samplers(),
+ },
+ api::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER => {
+ DescriptorLayout::CombinedImageSampler {
+ count: v.descriptorCount as usize,
+ immutable_samplers: get_immutable_samplers(),
+ }
+ }
+ api::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE => DescriptorLayout::SampledImage {
+ count: v.descriptorCount as usize,
+ },
+ api::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE => DescriptorLayout::StorageImage {
+ count: v.descriptorCount as usize,
+ },
+ api::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER => DescriptorLayout::UniformTexelBuffer {
+ count: v.descriptorCount as usize,
+ },
+ api::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER => DescriptorLayout::StorageTexelBuffer {
+ count: v.descriptorCount as usize,
+ },
+ api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER => DescriptorLayout::UniformBuffer {
+ count: v.descriptorCount as usize,
+ },
+ api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER => DescriptorLayout::StorageBuffer {
+ count: v.descriptorCount as usize,
+ },
+ api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC => {
+ DescriptorLayout::UniformBufferDynamic {
+ count: v.descriptorCount as usize,
+ }
+ }
+ api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC => {
+ DescriptorLayout::StorageBufferDynamic {
+ count: v.descriptorCount as usize,
+ }
+ }
+ api::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT => DescriptorLayout::InputAttachment {
+ count: v.descriptorCount as usize,
+ },
+ _ => unreachable!("invalid VkDescriptorType: {}", v.descriptorType),
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct DescriptorSetLayout {
+ pub bindings: Vec<Option<DescriptorLayout>>,
+}
+
+#[derive(Debug)]
+pub struct DescriptorPool {
+ descriptor_sets: Vec<OwnedHandle<api::VkDescriptorSet>>,
+}
+
+impl DescriptorPool {
+ pub fn new() -> Self {
+ Self {
+ descriptor_sets: Vec::new(),
+ }
+ }
+ pub fn reset(&mut self) {
+ self.descriptor_sets.clear()
+ }
+ pub unsafe fn allocate<I: IntoIterator<Item = DescriptorSet>>(
+ &mut self,
+ descriptor_sets: I,
+ output_descriptor_sets: &mut [api::VkDescriptorSet],
+ ) {
+ let start_index = self.descriptor_sets.len();
+ self.descriptor_sets
+ .extend(descriptor_sets.into_iter().map(OwnedHandle::new));
+ assert_eq!(
+ self.descriptor_sets[start_index..].len(),
+ output_descriptor_sets.len()
+ );
+ for (output_descriptor_set, descriptor_set) in output_descriptor_sets
+ .iter_mut()
+ .zip(self.descriptor_sets[start_index..].iter())
+ {
+ *output_descriptor_set = descriptor_set.get_handle();
+ }
+ }
+ pub unsafe fn free(&mut self, descriptor_sets: &[api::VkDescriptorSet]) {
+ self.descriptor_sets
+ .retain(|descriptor_set| !descriptor_sets.contains(&descriptor_set.get_handle()))
+ }
+}
+
+#[derive(Debug)]
+pub struct DescriptorImage(SharedHandle<api::VkImageView>, image::Tiling);
+
+impl DescriptorImage {
+ pub unsafe fn from(v: &api::VkDescriptorImageInfo) -> Self {
+ let image_view = SharedHandle::from(v.imageView).unwrap();
+ let tiling = image_view.image.properties.get_tiling(v.imageLayout);
+ DescriptorImage(image_view, tiling)
+ }
+}
+
+#[derive(Debug)]
+pub struct DescriptorCombinedImageSampler {
+ image: Option<DescriptorImage>,
+ sampler: Option<SharedHandle<api::VkSampler>>,
+}
+
+#[derive(Debug)]
+pub enum Descriptor {
+ Sampler {
+ elements: Vec<Option<SharedHandle<api::VkSampler>>>,
+ immutable_samplers: bool,
+ },
+ CombinedImageSampler {
+ elements: Vec<DescriptorCombinedImageSampler>,
+ immutable_samplers: bool,
+ },
+ SampledImage {
+ elements: Vec<Option<DescriptorImage>>,
+ },
+ StorageImage {
+ elements: Vec<Option<DescriptorImage>>,
+ },
+ UniformTexelBuffer {
+ elements: Vec<Option<SharedHandle<api::VkBufferView>>>,
+ },
+ StorageTexelBuffer {
+ elements: Vec<Option<SharedHandle<api::VkBufferView>>>,
+ },
+ UniformBuffer {
+ elements: Vec<Option<BufferSlice>>,
+ },
+ StorageBuffer {
+ elements: Vec<Option<BufferSlice>>,
+ },
+ UniformBufferDynamic {
+ elements: Vec<Option<BufferSlice>>,
+ },
+ StorageBufferDynamic {
+ elements: Vec<Option<BufferSlice>>,
+ },
+ InputAttachment {
+ elements: Vec<Option<DescriptorImage>>,
+ },
+}
+
+#[derive(Copy, Clone)]
+pub enum DescriptorWriteArg<'a> {
+ Image(&'a [api::VkDescriptorImageInfo]),
+ Buffer(&'a [api::VkDescriptorBufferInfo]),
+ TexelBuffer(&'a [api::VkBufferView]),
+}
+
+impl<'a> DescriptorWriteArg<'a> {
+ pub unsafe fn from(v: &'a api::VkWriteDescriptorSet) -> Self {
+ match v.descriptorType {
+ api::VK_DESCRIPTOR_TYPE_SAMPLER
+ | api::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
+ | api::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
+ | api::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
+ | api::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT => {
+ assert!(!v.pImageInfo.is_null());
+ DescriptorWriteArg::Image(slice::from_raw_parts(
+ v.pImageInfo,
+ v.descriptorCount as usize,
+ ))
+ }
+ api::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
+ | api::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER => {
+ assert!(!v.pTexelBufferView.is_null());
+ DescriptorWriteArg::TexelBuffer(slice::from_raw_parts(
+ v.pTexelBufferView,
+ v.descriptorCount as usize,
+ ))
+ }
+ api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
+ | api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
+ | api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
+ | api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC => {
+ assert!(!v.pBufferInfo.is_null());
+ DescriptorWriteArg::Buffer(slice::from_raw_parts(
+ v.pBufferInfo,
+ v.descriptorCount as usize,
+ ))
+ }
+ _ => unreachable!("invalid VkDescriptorType: {}", v.descriptorType),
+ }
+ }
+ pub fn len(self) -> usize {
+ match self {
+ DescriptorWriteArg::Image(v) => v.len(),
+ DescriptorWriteArg::Buffer(v) => v.len(),
+ DescriptorWriteArg::TexelBuffer(v) => v.len(),
+ }
+ }
+ pub fn slice(self, range: ops::Range<usize>) -> Self {
+ match self {
+ DescriptorWriteArg::Image(v) => DescriptorWriteArg::Image(&v[range]),
+ DescriptorWriteArg::Buffer(v) => DescriptorWriteArg::Buffer(&v[range]),
+ DescriptorWriteArg::TexelBuffer(v) => DescriptorWriteArg::TexelBuffer(&v[range]),
+ }
+ }
+ pub fn slice_from(self, range: ops::RangeFrom<usize>) -> Self {
+ match self {
+ DescriptorWriteArg::Image(v) => DescriptorWriteArg::Image(&v[range]),
+ DescriptorWriteArg::Buffer(v) => DescriptorWriteArg::Buffer(&v[range]),
+ DescriptorWriteArg::TexelBuffer(v) => DescriptorWriteArg::TexelBuffer(&v[range]),
+ }
+ }
+ pub fn slice_to(self, range: ops::RangeTo<usize>) -> Self {
+ match self {
+ DescriptorWriteArg::Image(v) => DescriptorWriteArg::Image(&v[range]),
+ DescriptorWriteArg::Buffer(v) => DescriptorWriteArg::Buffer(&v[range]),
+ DescriptorWriteArg::TexelBuffer(v) => DescriptorWriteArg::TexelBuffer(&v[range]),
+ }
+ }
+ pub fn image(self) -> Option<&'a [api::VkDescriptorImageInfo]> {
+ match self {
+ DescriptorWriteArg::Image(v) => Some(v),
+ _ => None,
+ }
+ }
+ pub fn buffer(self) -> Option<&'a [api::VkDescriptorBufferInfo]> {
+ match self {
+ DescriptorWriteArg::Buffer(v) => Some(v),
+ _ => None,
+ }
+ }
+ pub fn texel_buffer(self) -> Option<&'a [api::VkBufferView]> {
+ match self {
+ DescriptorWriteArg::TexelBuffer(v) => Some(v),
+ _ => None,
+ }
+ }
+}
+
+fn descriptor_write_helper<Element, T, F: FnMut(&mut Element, &T)>(
+ start_element: usize,
+ elements: &mut [Element],
+ args: &[T],
+ mut f: F,
+) {
+ for (element, arg) in elements[start_element..][..args.len()]
+ .iter_mut()
+ .zip(args.iter())
+ {
+ f(element, arg);
+ }
+}
+
+impl Descriptor {
+ pub fn element_count(&self) -> usize {
+ match self {
+ Descriptor::Sampler { elements, .. } => elements.len(),
+ Descriptor::CombinedImageSampler { elements, .. } => elements.len(),
+ Descriptor::SampledImage { elements, .. } => elements.len(),
+ Descriptor::StorageImage { elements, .. } => elements.len(),
+ Descriptor::UniformTexelBuffer { elements, .. } => elements.len(),
+ Descriptor::StorageTexelBuffer { elements, .. } => elements.len(),
+ Descriptor::UniformBuffer { elements, .. } => elements.len(),
+ Descriptor::StorageBuffer { elements, .. } => elements.len(),
+ Descriptor::UniformBufferDynamic { elements, .. } => elements.len(),
+ Descriptor::StorageBufferDynamic { elements, .. } => elements.len(),
+ Descriptor::InputAttachment { elements, .. } => elements.len(),
+ }
+ }
+ pub fn from(layout: &DescriptorLayout) -> Self {
+ match layout {
+ DescriptorLayout::Sampler {
+ count,
+ immutable_samplers,
+ } => {
+ let mut elements: Vec<_> = (0..*count).map(|_| None).collect();
+ let immutable_samplers = if let Some(immutable_samplers) = immutable_samplers {
+ assert_eq!(immutable_samplers.len(), *count);
+ for (element, sampler) in elements.iter_mut().zip(immutable_samplers.iter()) {
+ *element = Some(sampler.clone());
+ }
+ true
+ } else {
+ false
+ };
+ Descriptor::Sampler {
+ elements,
+ immutable_samplers,
+ }
+ }
+ DescriptorLayout::CombinedImageSampler {
+ count,
+ immutable_samplers,
+ } => {
+ let mut elements: Vec<_> = (0..*count)
+ .map(|_| DescriptorCombinedImageSampler {
+ image: None,
+ sampler: None,
+ })
+ .collect();
+ let immutable_samplers = if let Some(immutable_samplers) = immutable_samplers {
+ assert_eq!(immutable_samplers.len(), *count);
+ for (element, sampler) in elements.iter_mut().zip(immutable_samplers.iter()) {
+ element.sampler = Some(sampler.clone());
+ }
+ true
+ } else {
+ false
+ };
+ Descriptor::CombinedImageSampler {
+ elements,
+ immutable_samplers,
+ }
+ }
+ DescriptorLayout::SampledImage { count } => Descriptor::SampledImage {
+ elements: (0..*count).map(|_| None).collect(),
+ },
+ DescriptorLayout::StorageImage { count } => Descriptor::StorageImage {
+ elements: (0..*count).map(|_| None).collect(),
+ },
+ DescriptorLayout::UniformTexelBuffer { count } => Descriptor::UniformTexelBuffer {
+ elements: (0..*count).map(|_| None).collect(),
+ },
+ DescriptorLayout::StorageTexelBuffer { count } => Descriptor::StorageTexelBuffer {
+ elements: (0..*count).map(|_| None).collect(),
+ },
+ DescriptorLayout::UniformBuffer { count } => Descriptor::UniformBuffer {
+ elements: (0..*count).map(|_| None).collect(),
+ },
+ DescriptorLayout::StorageBuffer { count } => Descriptor::StorageBuffer {
+ elements: (0..*count).map(|_| None).collect(),
+ },
+ DescriptorLayout::UniformBufferDynamic { count } => Descriptor::UniformBufferDynamic {
+ elements: (0..*count).map(|_| None).collect(),
+ },
+ DescriptorLayout::StorageBufferDynamic { count } => Descriptor::StorageBufferDynamic {
+ elements: (0..*count).map(|_| None).collect(),
+ },
+ DescriptorLayout::InputAttachment { count } => Descriptor::InputAttachment {
+ elements: (0..*count).map(|_| None).collect(),
+ },
+ }
+ }
+ pub unsafe fn write(&mut self, start_element: usize, arg: DescriptorWriteArg) {
+ assert_eq!(arg.len() + start_element, self.element_count());
+ match self {
+ Descriptor::Sampler {
+ elements,
+ immutable_samplers,
+ } => descriptor_write_helper(
+ start_element,
+ elements,
+ arg.image().unwrap(),
+ |_element, _arg| assert!(!*immutable_samplers),
+ ),
+ Descriptor::CombinedImageSampler {
+ elements,
+ immutable_samplers,
+ } => descriptor_write_helper(
+ start_element,
+ elements,
+ arg.image().unwrap(),
+ |element, arg| {
+ if !*immutable_samplers {
+ element.sampler = Some(SharedHandle::from(arg.sampler).unwrap());
+ }
+ element.image = Some(DescriptorImage::from(arg));
+ },
+ ),
+ Descriptor::SampledImage { elements } => descriptor_write_helper(
+ start_element,
+ elements,
+ arg.image().unwrap(),
+ |element, arg| {
+ *element = Some(DescriptorImage::from(arg));
+ },
+ ),
+ Descriptor::StorageImage { elements } => descriptor_write_helper(
+ start_element,
+ elements,
+ arg.image().unwrap(),
+ |element, arg| {
+ *element = Some(DescriptorImage::from(arg));
+ },
+ ),
+ Descriptor::UniformTexelBuffer { elements } => unimplemented!(),
+ Descriptor::StorageTexelBuffer { elements } => unimplemented!(),
+ Descriptor::UniformBuffer { elements } => descriptor_write_helper(
+ start_element,
+ elements,
+ arg.buffer().unwrap(),
+ |element, arg| *element = Some(BufferSlice::from(arg)),
+ ),
+ Descriptor::StorageBuffer { elements } => descriptor_write_helper(
+ start_element,
+ elements,
+ arg.buffer().unwrap(),
+ |element, arg| *element = Some(BufferSlice::from(arg)),
+ ),
+ Descriptor::UniformBufferDynamic { elements } => unimplemented!(),
+ Descriptor::StorageBufferDynamic { elements } => unimplemented!(),
+ Descriptor::InputAttachment { elements } => descriptor_write_helper(
+ start_element,
+ elements,
+ arg.image().unwrap(),
+ |element, arg| {
+ *element = Some(DescriptorImage::from(arg));
+ },
+ ),
+ }
+ }
+ pub fn descriptor_type(&self) -> api::VkDescriptorType {
+ match self {
+ Descriptor::Sampler { .. } => api::VK_DESCRIPTOR_TYPE_SAMPLER,
+ Descriptor::CombinedImageSampler { .. } => {
+ api::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
+ }
+ Descriptor::SampledImage { .. } => api::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
+ Descriptor::StorageImage { .. } => api::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+ Descriptor::UniformTexelBuffer { .. } => api::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
+ Descriptor::StorageTexelBuffer { .. } => api::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
+ Descriptor::UniformBuffer { .. } => api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ Descriptor::StorageBuffer { .. } => api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+ Descriptor::UniformBufferDynamic { .. } => {
+ api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
+ }
+ Descriptor::StorageBufferDynamic { .. } => {
+ api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC
+ }
+ Descriptor::InputAttachment { .. } => api::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct DescriptorSet {
+ pub bindings: Vec<Option<Descriptor>>,
+}
// Copyright 2018 Jacob Lifshay
use api;
use api_impl::{Device, Instance, PhysicalDevice, Queue};
-use buffer::Buffer;
+use buffer::{Buffer, BufferView};
+use descriptor_set::{DescriptorPool, DescriptorSet, DescriptorSetLayout};
use device_memory::DeviceMemory;
-use image::Image;
+use image::{Image, ImageView};
+use render_pass::RenderPass;
use sampler::Sampler;
use sampler::SamplerYcbcrConversion;
use shader_module::ShaderModule;
}
}
-#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct SharedHandle<T: Handle>(NonNull<T::Value>);
+impl<T: Handle> Clone for SharedHandle<T> {
+ fn clone(&self) -> Self {
+ SharedHandle(self.0)
+ }
+}
+
impl<T: Handle> SharedHandle<T> {
pub unsafe fn from(v: T) -> Option<Self> {
v.get().map(SharedHandle)
impl HandleAllocFree for VkQueryPool {}
-pub struct BufferView {}
-
pub type VkBufferView = NondispatchableHandle<BufferView>;
impl HandleAllocFree for VkBufferView {}
-pub struct ImageView {}
-
pub type VkImageView = NondispatchableHandle<ImageView>;
impl HandleAllocFree for VkImageView {}
impl HandleAllocFree for VkPipelineLayout {}
-pub struct RenderPass {}
-
pub type VkRenderPass = NondispatchableHandle<RenderPass>;
impl HandleAllocFree for VkRenderPass {}
impl HandleAllocFree for VkPipeline {}
-pub struct DescriptorSetLayout {}
-
pub type VkDescriptorSetLayout = NondispatchableHandle<DescriptorSetLayout>;
impl HandleAllocFree for VkDescriptorSetLayout {}
impl HandleAllocFree for VkSampler {}
-pub struct DescriptorPool {}
-
pub type VkDescriptorPool = NondispatchableHandle<DescriptorPool>;
impl HandleAllocFree for VkDescriptorPool {}
-pub struct DescriptorSet {}
-
pub type VkDescriptorSet = NondispatchableHandle<DescriptorSet>;
impl HandleAllocFree for VkDescriptorSet {}
// SPDX-License-Identifier: LGPL-2.1-or-later
// Copyright 2018 Jacob Lifshay
-#![cfg_attr(
- feature = "cargo-clippy",
- allow(clippy::unneeded_field_pattern)
-)]
+#![cfg_attr(feature = "cargo-clippy", allow(clippy::unneeded_field_pattern))]
use api;
use constants::IMAGE_ALIGNMENT;
use device_memory::DeviceMemoryLayout;
use handle::SharedHandle;
+use std::error;
+use std::fmt;
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum SupportedTilings {
}
impl ImageProperties {
+ pub fn get_tiling(&self, image_layout: api::VkImageLayout) -> Tiling {
+ if image_layout == api::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR {
+ self.swapchain_present_tiling.unwrap()
+ } else {
+ match self.supported_tilings {
+ SupportedTilings::LinearOnly => Tiling::Linear,
+ SupportedTilings::Any => Tiling::Tiled,
+ }
+ }
+ }
pub fn computed_properties(&self) -> ImageComputedProperties {
match *self {
Self {
pub properties: ImageProperties,
pub memory: Option<ImageMemory>,
}
+
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum ImageViewType {
+ Type1D,
+ Type2D,
+ Type3D,
+ Cube,
+ Array1D,
+ Array2D,
+ CubeArray,
+}
+
+impl ImageViewType {
+ pub fn from(v: api::VkImageViewType) -> Self {
+ match v {
+ api::VK_IMAGE_VIEW_TYPE_1D => ImageViewType::Type1D,
+ api::VK_IMAGE_VIEW_TYPE_2D => ImageViewType::Type2D,
+ api::VK_IMAGE_VIEW_TYPE_3D => ImageViewType::Type3D,
+ api::VK_IMAGE_VIEW_TYPE_CUBE => ImageViewType::Cube,
+ api::VK_IMAGE_VIEW_TYPE_1D_ARRAY => ImageViewType::Array1D,
+ api::VK_IMAGE_VIEW_TYPE_2D_ARRAY => ImageViewType::Array2D,
+ api::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY => ImageViewType::CubeArray,
+ _ => unreachable!(),
+ }
+ }
+}
+
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum ComponentSwizzle {
+ Zero,
+ One,
+ X,
+ Y,
+ Z,
+ W,
+}
+
+#[derive(Debug)]
+pub struct InvalidVkComponentSwizzle;
+
+impl fmt::Display for InvalidVkComponentSwizzle {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "invalid VkComponentSwizzle")
+ }
+}
+
+impl error::Error for InvalidVkComponentSwizzle {}
+
+impl ComponentSwizzle {
+ pub fn from(
+ v: api::VkComponentSwizzle,
+ identity: Self,
+ ) -> Result<Self, InvalidVkComponentSwizzle> {
+ match v {
+ api::VK_COMPONENT_SWIZZLE_IDENTITY => Ok(identity),
+ api::VK_COMPONENT_SWIZZLE_ZERO => Ok(ComponentSwizzle::Zero),
+ api::VK_COMPONENT_SWIZZLE_ONE => Ok(ComponentSwizzle::One),
+ api::VK_COMPONENT_SWIZZLE_R => Ok(ComponentSwizzle::X),
+ api::VK_COMPONENT_SWIZZLE_G => Ok(ComponentSwizzle::Y),
+ api::VK_COMPONENT_SWIZZLE_B => Ok(ComponentSwizzle::Z),
+ api::VK_COMPONENT_SWIZZLE_A => Ok(ComponentSwizzle::W),
+ _ => Err(InvalidVkComponentSwizzle),
+ }
+ }
+}
+
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct ComponentMapping {
+ pub x: ComponentSwizzle,
+ pub y: ComponentSwizzle,
+ pub z: ComponentSwizzle,
+ pub w: ComponentSwizzle,
+}
+
+impl ComponentMapping {
+ pub const IDENTITY: ComponentMapping = ComponentMapping {
+ x: ComponentSwizzle::X,
+ y: ComponentSwizzle::Y,
+ z: ComponentSwizzle::Z,
+ w: ComponentSwizzle::W,
+ };
+ pub fn from(v: api::VkComponentMapping) -> Result<Self, InvalidVkComponentSwizzle> {
+ Ok(Self {
+ x: ComponentSwizzle::from(v.r, ComponentSwizzle::X)?,
+ y: ComponentSwizzle::from(v.g, ComponentSwizzle::Y)?,
+ z: ComponentSwizzle::from(v.b, ComponentSwizzle::Z)?,
+ w: ComponentSwizzle::from(v.a, ComponentSwizzle::W)?,
+ })
+ }
+}
+
+impl Default for ComponentMapping {
+ fn default() -> Self {
+ Self::IDENTITY
+ }
+}
+
+#[derive(Debug)]
+pub struct ImageView {
+ pub image: SharedHandle<api::VkImage>,
+ pub view_type: ImageViewType,
+ pub format: api::VkFormat,
+ pub component_mapping: ComponentMapping,
+ pub subresource_range: api::VkImageSubresourceRange,
+}
mod api;
mod api_impl;
mod buffer;
+mod descriptor_set;
mod device_memory;
mod handle;
mod image;
+mod render_pass;
mod sampler;
mod shader_module;
#[cfg(target_os = "linux")]
--- /dev/null
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// Copyright 2018 Jacob Lifshay
+
+#[derive(Debug)]
+pub struct RenderPass {}
use api;
use handle::SharedHandle;
+#[derive(Debug)]
pub struct AnisotropySettings {
pub max: f32,
}
+#[derive(Debug)]
pub struct Sampler {
pub mag_filter: api::VkFilter,
pub min_filter: api::VkFilter,
pub sampler_ycbcr_conversion: Option<SharedHandle<api::VkSamplerYcbcrConversion>>,
}
+#[derive(Debug)]
pub struct SamplerYcbcrConversion {}