diff options
Diffstat (limited to 'src/buffer/view.rs')
-rw-r--r-- | src/buffer/view.rs | 708 |
1 files changed, 413 insertions, 295 deletions
diff --git a/src/buffer/view.rs b/src/buffer/view.rs index bf885c2..3b1f4f4 100644 --- a/src/buffer/view.rs +++ b/src/buffer/view.rs @@ -15,269 +15,315 @@ //! In order to create a view from a buffer, the buffer must have been created with either the //! `uniform_texel_buffer` or the `storage_texel_buffer` usage. //! -//! # Example +//! # Examples //! //! ``` //! # use std::sync::Arc; -//! use vulkano::buffer::immutable::ImmutableBuffer; -//! use vulkano::buffer::BufferUsage; -//! use vulkano::buffer::BufferView; +//! use vulkano::buffer::{Buffer, BufferCreateInfo, BufferUsage}; +//! use vulkano::buffer::view::{BufferView, BufferViewCreateInfo}; //! use vulkano::format::Format; +//! use vulkano::memory::allocator::AllocationCreateInfo; //! -//! # let device: Arc<vulkano::device::Device> = return; //! # let queue: Arc<vulkano::device::Queue> = return; -//! let usage = BufferUsage { -//! storage_texel_buffer: true, -//! .. BufferUsage::none() -//! }; +//! # let memory_allocator: vulkano::memory::allocator::StandardMemoryAllocator = return; +//! let buffer = Buffer::new_slice::<u32>( +//! &memory_allocator, +//! BufferCreateInfo { +//! usage: BufferUsage::STORAGE_TEXEL_BUFFER, +//! ..Default::default() +//! }, +//! AllocationCreateInfo::default(), +//! 128, +//! ) +//! .unwrap(); //! -//! let (buffer, _future) = ImmutableBuffer::<[u32]>::from_iter((0..128).map(|n| n), usage, -//! queue.clone()).unwrap(); -//! let _view = BufferView::new(buffer, Format::R32Uint).unwrap(); +//! let view = BufferView::new( +//! buffer, +//! BufferViewCreateInfo { +//! format: Some(Format::R32_UINT), +//! ..Default::default() +//! }, +//! ) +//! .unwrap(); //! ``` -use crate::buffer::BufferAccess; -use crate::buffer::BufferInner; -use crate::buffer::TypedBufferAccess; -use crate::check_errors; -use crate::device::Device; -use crate::device::DeviceOwned; -use crate::format::Format; -use crate::format::Pixel; -use crate::Error; -use crate::OomError; -use crate::SafeDeref; -use crate::VulkanObject; -use std::error; -use std::fmt; -use std::mem::MaybeUninit; -use std::ptr; -use std::sync::Arc; +use super::{BufferUsage, Subbuffer}; +use crate::{ + device::{Device, DeviceOwned}, + format::{Format, FormatFeatures}, + macros::impl_id_counter, + memory::{is_aligned, DeviceAlignment}, + DeviceSize, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, +}; +use std::{ + error::Error, + fmt::{Display, Error as FmtError, Formatter}, + mem::MaybeUninit, + num::NonZeroU64, + ops::Range, + ptr, + sync::Arc, +}; /// Represents a way for the GPU to interpret buffer data. See the documentation of the /// `view` module. -pub struct BufferView<B> -where - B: BufferAccess, -{ - view: ash::vk::BufferView, - buffer: B, - atomic_accesses: bool, +#[derive(Debug)] +pub struct BufferView { + handle: ash::vk::BufferView, + subbuffer: Subbuffer<[u8]>, + id: NonZeroU64, + + format: Option<Format>, + format_features: FormatFeatures, + range: Range<DeviceSize>, } -impl<B> BufferView<B> -where - B: BufferAccess, -{ - /// Builds a new buffer view. +impl BufferView { + /// Creates a new `BufferView`. #[inline] - pub fn new<Px>(buffer: B, format: Format) -> Result<BufferView<B>, BufferViewCreationError> - where - B: TypedBufferAccess<Content = [Px]>, - Px: Pixel, - { - unsafe { BufferView::unchecked(buffer, format) } + pub fn new( + subbuffer: Subbuffer<impl ?Sized>, + create_info: BufferViewCreateInfo, + ) -> Result<Arc<BufferView>, BufferViewCreationError> { + Self::new_inner(subbuffer.into_bytes(), create_info) } - /// Builds a new buffer view without checking that the format is correct. - pub unsafe fn unchecked( - org_buffer: B, - format: Format, - ) -> Result<BufferView<B>, BufferViewCreationError> - where - B: BufferAccess, - { - let (view, format_props) = { - let size = org_buffer.size(); - let BufferInner { buffer, offset } = org_buffer.inner(); - - let device = buffer.device(); - - if (offset - % device - .physical_device() - .properties() - .min_texel_buffer_offset_alignment) - != 0 - { - return Err(BufferViewCreationError::WrongBufferAlignment); - } + fn new_inner( + subbuffer: Subbuffer<[u8]>, + create_info: BufferViewCreateInfo, + ) -> Result<Arc<BufferView>, BufferViewCreationError> { + let BufferViewCreateInfo { format, _ne: _ } = create_info; + + let buffer = subbuffer.buffer(); + let device = buffer.device(); + let properties = device.physical_device().properties(); + let size = subbuffer.size(); + let offset = subbuffer.offset(); + + // No VUID, but seems sensible? + let format = format.unwrap(); + + // VUID-VkBufferViewCreateInfo-format-parameter + format.validate_device(device)?; + + // VUID-VkBufferViewCreateInfo-buffer-00932 + if !buffer + .usage() + .intersects(BufferUsage::UNIFORM_TEXEL_BUFFER | BufferUsage::STORAGE_TEXEL_BUFFER) + { + return Err(BufferViewCreationError::BufferMissingUsage); + } - if !buffer.usage().uniform_texel_buffer && !buffer.usage().storage_texel_buffer { - return Err(BufferViewCreationError::WrongBufferUsage); - } + // Use unchecked, because all validation has been done above. + let format_features = unsafe { + device + .physical_device() + .format_properties_unchecked(format) + .buffer_features + }; + + // VUID-VkBufferViewCreateInfo-buffer-00933 + if buffer.usage().intersects(BufferUsage::UNIFORM_TEXEL_BUFFER) + && !format_features.intersects(FormatFeatures::UNIFORM_TEXEL_BUFFER) + { + return Err(BufferViewCreationError::UnsupportedFormat); + } + + // VUID-VkBufferViewCreateInfo-buffer-00934 + if buffer.usage().intersects(BufferUsage::STORAGE_TEXEL_BUFFER) + && !format_features.intersects(FormatFeatures::STORAGE_TEXEL_BUFFER) + { + return Err(BufferViewCreationError::UnsupportedFormat); + } + + let block_size = format.block_size().unwrap(); + let texels_per_block = format.texels_per_block(); + + // VUID-VkBufferViewCreateInfo-range-00929 + if size % block_size != 0 { + return Err(BufferViewCreationError::RangeNotAligned { + range: size, + required_alignment: block_size, + }); + } - { - let nb = size - / format - .size() - .expect("Can't use a compressed format for buffer views"); - let l = device - .physical_device() - .properties() - .max_texel_buffer_elements; - - if nb as u32 > l { - return Err(BufferViewCreationError::MaxTexelBufferElementsExceeded); + // VUID-VkBufferViewCreateInfo-range-00930 + if ((size / block_size) * texels_per_block as DeviceSize) as u32 + > properties.max_texel_buffer_elements + { + return Err(BufferViewCreationError::MaxTexelBufferElementsExceeded); + } + + if device.api_version() >= Version::V1_3 || device.enabled_features().texel_buffer_alignment + { + let element_size = DeviceAlignment::new(if block_size % 3 == 0 { + block_size / 3 + } else { + block_size + }) + .unwrap(); + + if buffer.usage().intersects(BufferUsage::STORAGE_TEXEL_BUFFER) { + let mut required_alignment = properties + .storage_texel_buffer_offset_alignment_bytes + .unwrap(); + + if properties + .storage_texel_buffer_offset_single_texel_alignment + .unwrap() + { + required_alignment = required_alignment.min(element_size); } - } - let format_props = { - let fns_i = device.instance().fns(); - let mut output = MaybeUninit::uninit(); - fns_i.v1_0.get_physical_device_format_properties( - device.physical_device().internal_object(), - format.into(), - output.as_mut_ptr(), - ); - output.assume_init().buffer_features - }; - - if buffer.usage().uniform_texel_buffer { - if (format_props & ash::vk::FormatFeatureFlags::UNIFORM_TEXEL_BUFFER).is_empty() { - return Err(BufferViewCreationError::UnsupportedFormat); + // VUID-VkBufferViewCreateInfo-buffer-02750 + if !is_aligned(offset, required_alignment) { + return Err(BufferViewCreationError::OffsetNotAligned { + offset, + required_alignment, + }); } } - if buffer.usage().storage_texel_buffer { - if (format_props & ash::vk::FormatFeatureFlags::STORAGE_TEXEL_BUFFER).is_empty() { - return Err(BufferViewCreationError::UnsupportedFormat); + if buffer.usage().intersects(BufferUsage::UNIFORM_TEXEL_BUFFER) { + let mut required_alignment = properties + .uniform_texel_buffer_offset_alignment_bytes + .unwrap(); + + if properties + .uniform_texel_buffer_offset_single_texel_alignment + .unwrap() + { + required_alignment = required_alignment.min(element_size); + } + + // VUID-VkBufferViewCreateInfo-buffer-02751 + if !is_aligned(offset, required_alignment) { + return Err(BufferViewCreationError::OffsetNotAligned { + offset, + required_alignment, + }); } } + } else { + let required_alignment = properties.min_texel_buffer_offset_alignment; + + // VUID-VkBufferViewCreateInfo-offset-02749 + if !is_aligned(offset, required_alignment) { + return Err(BufferViewCreationError::OffsetNotAligned { + offset, + required_alignment, + }); + } + } - let infos = ash::vk::BufferViewCreateInfo { - flags: ash::vk::BufferViewCreateFlags::empty(), - buffer: buffer.internal_object(), - format: format.into(), - offset, - range: size, - ..Default::default() - }; + let create_info = ash::vk::BufferViewCreateInfo { + flags: ash::vk::BufferViewCreateFlags::empty(), + buffer: buffer.handle(), + format: format.into(), + offset, + range: size, + ..Default::default() + }; + let handle = unsafe { let fns = device.fns(); let mut output = MaybeUninit::uninit(); - check_errors(fns.v1_0.create_buffer_view( - device.internal_object(), - &infos, + (fns.v1_0.create_buffer_view)( + device.handle(), + &create_info, ptr::null(), output.as_mut_ptr(), - ))?; - (output.assume_init(), format_props) + ) + .result() + .map_err(VulkanError::from)?; + output.assume_init() }; - Ok(BufferView { - view, - buffer: org_buffer, - atomic_accesses: !(format_props - & ash::vk::FormatFeatureFlags::STORAGE_TEXEL_BUFFER_ATOMIC) - .is_empty(), - }) + Ok(Arc::new(BufferView { + handle, + subbuffer, + id: Self::next_id(), + format: Some(format), + format_features, + range: 0..size, + })) } /// Returns the buffer associated to this view. #[inline] - pub fn buffer(&self) -> &B { - &self.buffer - } - - /// Returns true if the buffer view can be used as a uniform texel buffer. - #[inline] - pub fn uniform_texel_buffer(&self) -> bool { - self.buffer.inner().buffer.usage().uniform_texel_buffer - } - - /// Returns true if the buffer view can be used as a storage texel buffer. - #[inline] - pub fn storage_texel_buffer(&self) -> bool { - self.buffer.inner().buffer.usage().storage_texel_buffer + pub fn buffer(&self) -> &Subbuffer<[u8]> { + &self.subbuffer } - /// Returns true if the buffer view can be used as a storage texel buffer with atomic accesses. + /// Returns the format of this view. #[inline] - pub fn storage_texel_buffer_atomic(&self) -> bool { - self.atomic_accesses && self.storage_texel_buffer() + pub fn format(&self) -> Option<Format> { + self.format } -} - -unsafe impl<B> VulkanObject for BufferView<B> -where - B: BufferAccess, -{ - type Object = ash::vk::BufferView; + /// Returns the features supported by this view’s format. #[inline] - fn internal_object(&self) -> ash::vk::BufferView { - self.view + pub fn format_features(&self) -> FormatFeatures { + self.format_features } -} -unsafe impl<B> DeviceOwned for BufferView<B> -where - B: BufferAccess, -{ + /// Returns the byte range of the wrapped buffer that this view exposes. #[inline] - fn device(&self) -> &Arc<Device> { - self.buffer.device() - } -} - -impl<B> fmt::Debug for BufferView<B> -where - B: BufferAccess + fmt::Debug, -{ - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - fmt.debug_struct("BufferView") - .field("raw", &self.view) - .field("buffer", &self.buffer) - .finish() + pub fn range(&self) -> Range<DeviceSize> { + self.range.clone() } } -impl<B> Drop for BufferView<B> -where - B: BufferAccess, -{ +impl Drop for BufferView { #[inline] fn drop(&mut self) { unsafe { - let fns = self.buffer.inner().buffer.device().fns(); - fns.v1_0.destroy_buffer_view( - self.buffer.inner().buffer.device().internal_object(), - self.view, + let fns = self.subbuffer.device().fns(); + (fns.v1_0.destroy_buffer_view)( + self.subbuffer.device().handle(), + self.handle, ptr::null(), ); } } } -pub unsafe trait BufferViewRef { - type BufferAccess: BufferAccess; +unsafe impl VulkanObject for BufferView { + type Handle = ash::vk::BufferView; - fn view(&self) -> &BufferView<Self::BufferAccess>; + #[inline] + fn handle(&self) -> Self::Handle { + self.handle + } } -unsafe impl<B> BufferViewRef for BufferView<B> -where - B: BufferAccess, -{ - type BufferAccess = B; - +unsafe impl DeviceOwned for BufferView { #[inline] - fn view(&self) -> &BufferView<B> { - self + fn device(&self) -> &Arc<Device> { + self.subbuffer.device() } } -unsafe impl<T, B> BufferViewRef for T -where - T: SafeDeref<Target = BufferView<B>>, - B: BufferAccess, -{ - type BufferAccess = B; +impl_id_counter!(BufferView); + +/// Parameters to create a new `BufferView`. +#[derive(Clone, Debug)] +pub struct BufferViewCreateInfo { + /// The format of the buffer view. + /// + /// The default value is `None`, which must be overridden. + pub format: Option<Format>, + + pub _ne: crate::NonExhaustive, +} +impl Default for BufferViewCreateInfo { #[inline] - fn view(&self) -> &BufferView<B> { - &**self + fn default() -> Self { + Self { + format: None, + _ne: crate::NonExhaustive(()), + } } } @@ -287,170 +333,242 @@ pub enum BufferViewCreationError { /// Out of memory. OomError(OomError), - /// The buffer was not creating with one of the `storage_texel_buffer` or + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, + }, + + /// The buffer was not created with one of the `storage_texel_buffer` or /// `uniform_texel_buffer` usages. - WrongBufferUsage, + BufferMissingUsage, - /// The offset within the buffer is not a multiple of the `min_texel_buffer_offset_alignment` - /// limit. - WrongBufferAlignment, + /// The offset within the buffer is not a multiple of the required alignment. + OffsetNotAligned { + offset: DeviceSize, + required_alignment: DeviceAlignment, + }, + + /// The range within the buffer is not a multiple of the required alignment. + RangeNotAligned { + range: DeviceSize, + required_alignment: DeviceSize, + }, /// The requested format is not supported for this usage. UnsupportedFormat, - /// The maximum number of elements in the buffer view has been exceeded. + /// The `max_texel_buffer_elements` limit has been exceeded. MaxTexelBufferElementsExceeded, } -impl error::Error for BufferViewCreationError { - #[inline] - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - match *self { - BufferViewCreationError::OomError(ref err) => Some(err), +impl Error for BufferViewCreationError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + match self { + BufferViewCreationError::OomError(err) => Some(err), _ => None, } } } -impl fmt::Display for BufferViewCreationError { - #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!( - fmt, - "{}", - match *self { - BufferViewCreationError::OomError(_) => "out of memory when creating buffer view", - BufferViewCreationError::WrongBufferUsage => { - "the buffer is missing correct usage flags" - } - BufferViewCreationError::WrongBufferAlignment => { - "the offset within the buffer is not a multiple of the - `min_texel_buffer_offset_alignment` limit" - } - BufferViewCreationError::UnsupportedFormat => { - "the requested format is not supported for this usage" - } - BufferViewCreationError::MaxTexelBufferElementsExceeded => { - "the maximum number of texel elements is exceeded" - } +impl Display for BufferViewCreationError { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + match self { + Self::OomError(_) => write!(f, "out of memory when creating buffer view"), + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), + Self::BufferMissingUsage => write!( + f, + "the buffer was not created with one of the `storage_texel_buffer` or \ + `uniform_texel_buffer` usages", + ), + Self::OffsetNotAligned { .. } => write!( + f, + "the offset within the buffer is not a multiple of the required alignment", + ), + Self::RangeNotAligned { .. } => write!( + f, + "the range within the buffer is not a multiple of the required alignment", + ), + Self::UnsupportedFormat => { + write!(f, "the requested format is not supported for this usage") } - ) + Self::MaxTexelBufferElementsExceeded => { + write!(f, "the `max_texel_buffer_elements` limit has been exceeded") + } + } } } impl From<OomError> for BufferViewCreationError { - #[inline] - fn from(err: OomError) -> BufferViewCreationError { - BufferViewCreationError::OomError(err) + fn from(err: OomError) -> Self { + Self::OomError(err) } } -impl From<Error> for BufferViewCreationError { - #[inline] - fn from(err: Error) -> BufferViewCreationError { +impl From<VulkanError> for BufferViewCreationError { + fn from(err: VulkanError) -> Self { OomError::from(err).into() } } +impl From<RequirementNotMet> for BufferViewCreationError { + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, + } + } +} + #[cfg(test)] mod tests { - use crate::buffer::immutable::ImmutableBuffer; - use crate::buffer::view::BufferViewCreationError; - use crate::buffer::BufferUsage; - use crate::buffer::BufferView; - use crate::format::Format; + use super::{BufferView, BufferViewCreateInfo, BufferViewCreationError}; + use crate::{ + buffer::{Buffer, BufferCreateInfo, BufferUsage}, + format::Format, + memory::allocator::{AllocationCreateInfo, MemoryUsage, StandardMemoryAllocator}, + }; #[test] fn create_uniform() { // `VK_FORMAT_R8G8B8A8_UNORM` guaranteed to be a supported format - let (device, queue) = gfx_dev_and_queue!(); - - let usage = BufferUsage { - uniform_texel_buffer: true, - ..BufferUsage::none() - }; + let (device, _) = gfx_dev_and_queue!(); + let memory_allocator = StandardMemoryAllocator::new_default(device); - let (buffer, _) = - ImmutableBuffer::<[[u8; 4]]>::from_iter((0..128).map(|_| [0; 4]), usage, queue.clone()) - .unwrap(); - let view = BufferView::new(buffer, Format::R8G8B8A8Unorm).unwrap(); - - assert!(view.uniform_texel_buffer()); + let buffer = Buffer::new_slice::<[u8; 4]>( + &memory_allocator, + BufferCreateInfo { + usage: BufferUsage::UNIFORM_TEXEL_BUFFER, + ..Default::default() + }, + AllocationCreateInfo { + usage: MemoryUsage::Upload, + ..Default::default() + }, + 128, + ) + .unwrap(); + BufferView::new( + buffer, + BufferViewCreateInfo { + format: Some(Format::R8G8B8A8_UNORM), + ..Default::default() + }, + ) + .unwrap(); } #[test] fn create_storage() { // `VK_FORMAT_R8G8B8A8_UNORM` guaranteed to be a supported format - let (device, queue) = gfx_dev_and_queue!(); + let (device, _) = gfx_dev_and_queue!(); + let memory_allocator = StandardMemoryAllocator::new_default(device); - let usage = BufferUsage { - storage_texel_buffer: true, - ..BufferUsage::none() - }; - - let (buffer, _) = - ImmutableBuffer::<[[u8; 4]]>::from_iter((0..128).map(|_| [0; 4]), usage, queue.clone()) - .unwrap(); - let view = BufferView::new(buffer, Format::R8G8B8A8Unorm).unwrap(); - - assert!(view.storage_texel_buffer()); + let buffer = Buffer::new_slice::<[u8; 4]>( + &memory_allocator, + BufferCreateInfo { + usage: BufferUsage::STORAGE_TEXEL_BUFFER, + ..Default::default() + }, + AllocationCreateInfo::default(), + 128, + ) + .unwrap(); + BufferView::new( + buffer, + BufferViewCreateInfo { + format: Some(Format::R8G8B8A8_UNORM), + ..Default::default() + }, + ) + .unwrap(); } #[test] fn create_storage_atomic() { // `VK_FORMAT_R32_UINT` guaranteed to be a supported format for atomics - let (device, queue) = gfx_dev_and_queue!(); - - let usage = BufferUsage { - storage_texel_buffer: true, - ..BufferUsage::none() - }; - - let (buffer, _) = - ImmutableBuffer::<[u32]>::from_iter((0..128).map(|_| 0), usage, queue.clone()).unwrap(); - let view = BufferView::new(buffer, Format::R32Uint).unwrap(); + let (device, _) = gfx_dev_and_queue!(); + let memory_allocator = StandardMemoryAllocator::new_default(device); - assert!(view.storage_texel_buffer()); - assert!(view.storage_texel_buffer_atomic()); + let buffer = Buffer::new_slice::<u32>( + &memory_allocator, + BufferCreateInfo { + usage: BufferUsage::STORAGE_TEXEL_BUFFER, + ..Default::default() + }, + AllocationCreateInfo::default(), + 128, + ) + .unwrap(); + BufferView::new( + buffer, + BufferViewCreateInfo { + format: Some(Format::R32_UINT), + ..Default::default() + }, + ) + .unwrap(); } #[test] fn wrong_usage() { // `VK_FORMAT_R8G8B8A8_UNORM` guaranteed to be a supported format - let (device, queue) = gfx_dev_and_queue!(); + let (device, _) = gfx_dev_and_queue!(); + let memory_allocator = StandardMemoryAllocator::new_default(device); - let (buffer, _) = ImmutableBuffer::<[[u8; 4]]>::from_iter( - (0..128).map(|_| [0; 4]), - BufferUsage::none(), - queue.clone(), + let buffer = Buffer::new_slice::<[u8; 4]>( + &memory_allocator, + BufferCreateInfo { + usage: BufferUsage::TRANSFER_DST, // Dummy value + ..Default::default() + }, + AllocationCreateInfo::default(), + 128, ) .unwrap(); - match BufferView::new(buffer, Format::R8G8B8A8Unorm) { - Err(BufferViewCreationError::WrongBufferUsage) => (), + match BufferView::new( + buffer, + BufferViewCreateInfo { + format: Some(Format::R8G8B8A8_UNORM), + ..Default::default() + }, + ) { + Err(BufferViewCreationError::BufferMissingUsage) => (), _ => panic!(), } } #[test] fn unsupported_format() { - let (device, queue) = gfx_dev_and_queue!(); - - let usage = BufferUsage { - uniform_texel_buffer: true, - storage_texel_buffer: true, - ..BufferUsage::none() - }; + let (device, _) = gfx_dev_and_queue!(); + let memory_allocator = StandardMemoryAllocator::new_default(device); - let (buffer, _) = ImmutableBuffer::<[[f64; 4]]>::from_iter( - (0..128).map(|_| [0.0; 4]), - usage, - queue.clone(), + let buffer = Buffer::new_slice::<[f64; 4]>( + &memory_allocator, + BufferCreateInfo { + usage: BufferUsage::UNIFORM_TEXEL_BUFFER | BufferUsage::STORAGE_TEXEL_BUFFER, + ..Default::default() + }, + AllocationCreateInfo::default(), + 128, ) .unwrap(); - // TODO: what if R64G64B64A64Sfloat is supported? - match BufferView::new(buffer, Format::R64G64B64A64Sfloat) { + // TODO: what if R64G64B64A64_SFLOAT is supported? + match BufferView::new( + buffer, + BufferViewCreateInfo { + format: Some(Format::R64G64B64A64_SFLOAT), + ..Default::default() + }, + ) { Err(BufferViewCreationError::UnsupportedFormat) => (), _ => panic!(), } |