mod cmd_ref;
mod compute;
mod graphics;
mod pipeline;
mod ray_tracing;
pub use {
self::{
cmd_ref::{
BuildAccelerationStructureIndirectInfo, BuildAccelerationStructureInfo, CommandRef,
UpdateAccelerationStructureIndirectInfo, UpdateAccelerationStructureInfo,
},
compute::ComputeCommandRef,
graphics::{ClearColorValue, GraphicsCommandRef},
pipeline::{Pipeline, PipelineCommand},
ray_tracing::RayTracingCommandRef,
},
super::{LoadOp, StoreOp},
};
use {
super::{
AccelerationStructureLeaseNode, AccelerationStructureNode, AnyAccelerationStructureNode,
AnyBufferNode, AnyImageNode, AnyResource, BufferLeaseNode, BufferNode, CommandData,
CommandExecution, CommandFunction, Execution, Graph, ImageLeaseNode, ImageNode, Node,
Resource, SwapchainImageNode, TimestampQuery, TimestampQueryPlacement,
},
crate::{
NodeIndex,
driver::{
buffer::BufferSubresourceRange, format_texel_block_extent, format_texel_block_size,
image::ImageViewInfo, image_subresource_range_from_layers,
},
stream::{AccelerationStructureArg, BufferArg, ImageArg},
},
ash::vk,
std::{ops::Range, sync::Arc},
vk_sync::AccessType,
};
pub(crate) type AttachmentIndex = u32;
pub(crate) type BindingIndex = u32;
pub(crate) type BindingOffset = u32;
pub(crate) type DescriptorSetIndex = u32;
pub struct Command<'a> {
pub(super) cmd_idx: usize,
pub(super) exec_idx: usize,
pub(super) graph: &'a mut Graph,
}
pub struct CommandBuilder<'a> {
cmd: Command<'a>,
}
impl<'a> CommandBuilder<'a> {
pub fn new(graph: &'a mut Graph) -> Self {
Self {
cmd: graph.begin_cmd(),
}
}
pub fn build(self) -> Command<'a> {
self.cmd
}
pub fn push_cmd(self) -> &'a mut Graph {
self.cmd.end_cmd()
}
#[allow(deprecated)]
pub fn blit_image(
mut self,
src: impl Into<AnyImageNode>,
dst: impl Into<AnyImageNode>,
filter: vk::Filter,
regions: impl AsRef<[vk::ImageBlit]> + 'static + Send,
) -> Self {
self.cmd = self.cmd.blit_image(src, dst, filter, regions);
self
}
#[allow(deprecated)]
pub fn clear_color_image(
mut self,
image: impl Into<AnyImageNode>,
color: impl Into<ClearColorValue>,
) -> Self {
self.cmd = self.cmd.clear_color_image(image, color);
self
}
#[allow(deprecated)]
pub fn clear_depth_stencil_image(
mut self,
image: impl Into<AnyImageNode>,
depth: f32,
stencil: u32,
) -> Self {
self.cmd = self.cmd.clear_depth_stencil_image(image, depth, stencil);
self
}
#[allow(deprecated)]
pub fn copy_buffer(
mut self,
src: impl Into<AnyBufferNode>,
dst: impl Into<AnyBufferNode>,
regions: impl AsRef<[vk::BufferCopy]> + 'static + Send,
) -> Self {
self.cmd = self.cmd.copy_buffer(src, dst, regions);
self
}
#[allow(deprecated)]
pub fn copy_buffer_to_image(
mut self,
src: impl Into<AnyBufferNode>,
dst: impl Into<AnyImageNode>,
regions: impl AsRef<[vk::BufferImageCopy]> + 'static + Send,
) -> Self {
self.cmd = self.cmd.copy_buffer_to_image(src, dst, regions);
self
}
#[allow(deprecated)]
pub fn copy_image(
mut self,
src: impl Into<AnyImageNode>,
dst: impl Into<AnyImageNode>,
regions: impl AsRef<[vk::ImageCopy]> + 'static + Send,
) -> Self {
self.cmd = self.cmd.copy_image(src, dst, regions);
self
}
#[allow(deprecated)]
pub fn copy_image_to_buffer(
mut self,
src: impl Into<AnyImageNode>,
dst: impl Into<AnyBufferNode>,
regions: impl AsRef<[vk::BufferImageCopy]> + 'static + Send,
) -> Self {
self.cmd = self.cmd.copy_image_to_buffer(src, dst, regions);
self
}
#[allow(deprecated)]
pub fn fill_buffer(
mut self,
buffer: impl Into<AnyBufferNode>,
region: Range<vk::DeviceSize>,
data: u32,
) -> Self {
self.cmd = self.cmd.fill_buffer(buffer, region, data);
self
}
pub fn update_buffer(
mut self,
buffer: impl Into<AnyBufferNode>,
offset: vk::DeviceSize,
data: impl AsRef<[u8]> + 'static + Send,
) -> Self {
self.cmd = self.cmd.update_buffer(buffer, offset, data);
self
}
}
#[allow(private_bounds)]
impl<'a> Command<'a> {
pub(super) fn new(graph: &'a mut Graph) -> Self {
let cmd_idx = graph.cmds.len();
graph.cmds.push(CommandData {
execs: vec![Default::default()], #[cfg(debug_assertions)]
name: None,
stream_scope_id: None,
tracking: Default::default(),
});
Self {
cmd_idx,
exec_idx: 0,
graph,
}
}
pub fn builder(graph: &'a mut Graph) -> CommandBuilder<'a> {
CommandBuilder::new(graph)
}
pub fn into_builder(self) -> CommandBuilder<'a> {
CommandBuilder { cmd: self }
}
pub fn track_execution(&mut self) -> CommandExecution {
self.cmd_mut().tracking.track()
}
pub fn write_timestamp(&mut self) -> TimestampQuery {
let (exec_idx, placement) = if self.exec_idx == 0 {
(0, TimestampQueryPlacement::BeforeExec)
} else {
(self.exec_idx - 1, TimestampQueryPlacement::AfterExec)
};
self.graph
.write_timestamp_at(self.cmd_idx, exec_idx, placement)
}
fn cmd(&self) -> &CommandData {
&self.graph.cmds[self.cmd_idx]
}
fn cmd_mut(&mut self) -> &mut CommandData {
&mut self.graph.cmds[self.cmd_idx]
}
pub fn bind_resource<R>(&mut self, resource: R) -> R::Node
where
R: Resource,
{
self.graph.bind_resource(resource)
}
pub fn bind_pipeline<P>(self, pipeline: P) -> P::Command
where
P: Pipeline<'a>,
{
pipeline.bind_cmd(self)
}
pub fn debug_name(mut self, name: impl Into<String>) -> Self {
self.set_debug_name(name);
self
}
pub fn end_cmd(self) -> &'a mut Graph {
if self.exec_idx == 0 {
self.graph.cmds.pop();
}
self.graph
}
fn push_exec(&mut self, func: impl FnOnce(CommandRef) + Send + 'static) {
let cmd = self.cmd_mut();
let exec = {
let last_exec = cmd.expect_last_exec_mut();
last_exec.func = Some(CommandFunction::Once(Box::new(func)));
Execution {
pipeline: last_exec.pipeline.clone(),
..Default::default()
}
};
cmd.execs.push(exec);
self.exec_idx += 1;
}
pub(crate) fn push_reusable_exec(
&mut self,
func: impl for<'r> Fn(CommandRef<'r>) + Send + Sync + 'static,
) {
let cmd = self.cmd_mut();
let exec = {
let last_exec = cmd.expect_last_exec_mut();
last_exec.func = Some(CommandFunction::Reusable(Arc::new(func)));
Execution {
pipeline: last_exec.pipeline.clone(),
..Default::default()
}
};
cmd.execs.push(exec);
self.exec_idx += 1;
}
fn push_subresource_access(
&mut self,
resource_node: impl Node,
subresource: SubresourceRange,
access: AccessType,
) {
self.graph.assert_node_owner(&resource_node);
let node_idx = resource_node.index();
self.push_subresource_access_index(node_idx, subresource, access);
}
pub(crate) fn push_subresource_access_index(
&mut self,
node_idx: NodeIndex,
subresource: SubresourceRange,
access: AccessType,
) {
debug_assert!(self.graph.resources.get(node_idx).is_some());
self.cmd_mut().expect_last_exec_mut().accesses.push(
node_idx,
SubresourceAccess {
access,
subresource,
},
);
}
pub fn record_cmd(mut self, func: impl FnOnce(CommandRef<'_>) + Send + 'static) -> Self {
self.record_cmd_mut(func);
self
}
pub fn record_cmd_mut(&mut self, func: impl FnOnce(CommandRef<'_>) + Send + 'static) {
self.push_exec(move |cmd| {
func(cmd);
});
}
pub fn blit_image(
mut self,
src: impl Into<AnyImageNode>,
dst: impl Into<AnyImageNode>,
filter: vk::Filter,
regions: impl AsRef<[vk::ImageBlit]> + 'static + Send,
) -> Self {
let src = src.into();
let dst = dst.into();
let regions = Arc::<[vk::ImageBlit]>::from(regions.as_ref());
for region in regions.as_ref() {
self.set_subresource_access(
src,
image_subresource_range_from_layers(region.src_subresource),
AccessType::TransferRead,
);
self.set_subresource_access(
dst,
image_subresource_range_from_layers(region.dst_subresource),
AccessType::TransferWrite,
);
}
self.record_stream_mut(move |cmd| {
let src_image = cmd.resource(src).handle;
let dst_image = cmd.resource(dst).handle;
unsafe {
cmd.device.cmd_blit_image(
cmd.handle,
src_image,
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
dst_image,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
regions.as_ref(),
filter,
);
}
});
self
}
pub fn clear_color_image(
mut self,
image: impl Into<AnyImageNode>,
color: impl Into<ClearColorValue>,
) -> Self {
let color = color.into().into();
let image = image.into();
let image_view = self.graph.resources[image.index()]
.expect_image_info()
.into();
self.set_subresource_access(image, image_view, AccessType::TransferWrite);
self.record_stream_mut(move |cmd| {
let image = cmd.resource(image);
unsafe {
cmd.device.cmd_clear_color_image(
cmd.handle,
image.handle,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
&color,
&[image_view],
);
}
});
self
}
pub fn clear_depth_stencil_image(
mut self,
image: impl Into<AnyImageNode>,
depth: f32,
stencil: u32,
) -> Self {
let image = image.into();
let image_view = self.graph.resources[image.index()]
.expect_image_info()
.into();
self.set_subresource_access(image, image_view, AccessType::TransferWrite);
self.record_stream_mut(move |cmd| {
let image = cmd.resource(image);
unsafe {
cmd.device.cmd_clear_depth_stencil_image(
cmd.handle,
image.handle,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
&vk::ClearDepthStencilValue { depth, stencil },
&[image_view],
);
}
});
self
}
pub fn copy_buffer(
mut self,
src: impl Into<AnyBufferNode>,
dst: impl Into<AnyBufferNode>,
regions: impl AsRef<[vk::BufferCopy]> + 'static + Send,
) -> Self {
let src = src.into();
let dst = dst.into();
let regions = Arc::<[vk::BufferCopy]>::from(regions.as_ref());
#[cfg(feature = "checked")]
let src_size = self.graph.resources[src.index()].expect_buffer_info().size;
#[cfg(feature = "checked")]
let dst_size = self.graph.resources[dst.index()].expect_buffer_info().size;
for region in regions.iter() {
#[cfg(feature = "checked")]
{
assert!(
region.src_offset + region.size <= src_size,
"source range end ({}) exceeds source size ({src_size})",
region.src_offset + region.size
);
assert!(
region.dst_offset + region.size <= dst_size,
"destination range end ({}) exceeds destination size ({dst_size})",
region.dst_offset + region.size
);
};
self.set_subresource_access(
src,
region.src_offset..region.src_offset + region.size,
AccessType::TransferRead,
);
self.set_subresource_access(
dst,
region.dst_offset..region.dst_offset + region.size,
AccessType::TransferWrite,
);
}
self.record_stream_mut(move |cmd| {
let src = cmd.resource(src);
let dst = cmd.resource(dst);
unsafe {
cmd.device
.cmd_copy_buffer(cmd.handle, src.handle, dst.handle, ®ions);
}
});
self
}
pub fn copy_buffer_to_image(
mut self,
src: impl Into<AnyBufferNode>,
dst: impl Into<AnyImageNode>,
regions: impl AsRef<[vk::BufferImageCopy]> + 'static + Send,
) -> Self {
let src = src.into();
let dst = dst.into();
let dst_info = self.graph.resources[dst.index()].expect_image_info();
let regions = Arc::<[vk::BufferImageCopy]>::from(regions.as_ref());
for region in regions.iter() {
let block_bytes_size = format_texel_block_size(dst_info.format);
let (block_height, block_width) = format_texel_block_extent(dst_info.format);
let data_size = block_bytes_size
* (region.buffer_row_length / block_width)
* (region.buffer_image_height / block_height);
self.set_subresource_access(
src,
region.buffer_offset..region.buffer_offset + data_size as vk::DeviceSize,
AccessType::TransferRead,
);
self.set_subresource_access(
dst,
image_subresource_range_from_layers(region.image_subresource),
AccessType::TransferWrite,
);
}
self.record_stream_mut(move |cmd| {
let src = cmd.resource(src);
let dst = cmd.resource(dst);
unsafe {
cmd.device.cmd_copy_buffer_to_image(
cmd.handle,
src.handle,
dst.handle,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
®ions,
);
}
});
self
}
pub fn copy_image(
mut self,
src: impl Into<AnyImageNode>,
dst: impl Into<AnyImageNode>,
regions: impl AsRef<[vk::ImageCopy]> + 'static + Send,
) -> Self {
let src = src.into();
let dst = dst.into();
let regions = Arc::<[vk::ImageCopy]>::from(regions.as_ref());
for region in regions.iter() {
self.set_subresource_access(
src,
image_subresource_range_from_layers(region.src_subresource),
AccessType::TransferRead,
);
self.set_subresource_access(
dst,
image_subresource_range_from_layers(region.dst_subresource),
AccessType::TransferWrite,
);
}
self.record_stream_mut(move |cmd| {
let src = cmd.resource(src);
let dst = cmd.resource(dst);
unsafe {
cmd.device.cmd_copy_image(
cmd.handle,
src.handle,
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
dst.handle,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
®ions,
);
}
});
self
}
pub fn copy_image_to_buffer(
mut self,
src: impl Into<AnyImageNode>,
dst: impl Into<AnyBufferNode>,
regions: impl AsRef<[vk::BufferImageCopy]> + 'static + Send,
) -> Self {
let src = src.into();
let src_info = self.graph.resources[src.index()].expect_image_info();
let dst = dst.into();
let regions = Arc::<[vk::BufferImageCopy]>::from(regions.as_ref());
for region in regions.iter() {
let block_bytes_size = format_texel_block_size(src_info.format);
let (block_height, block_width) = format_texel_block_extent(src_info.format);
let data_size = block_bytes_size
* (region.buffer_row_length / block_width)
* (region.buffer_image_height / block_height);
self.set_subresource_access(
src,
image_subresource_range_from_layers(region.image_subresource),
AccessType::TransferRead,
);
self.set_subresource_access(
dst,
region.buffer_offset..region.buffer_offset + data_size as vk::DeviceSize,
AccessType::TransferWrite,
);
}
self.record_stream_mut(move |cmd| {
let src = cmd.resource(src);
let dst = cmd.resource(dst);
unsafe {
cmd.device.cmd_copy_image_to_buffer(
cmd.handle,
src.handle,
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
dst.handle,
®ions,
);
}
});
self
}
pub fn fill_buffer(
mut self,
buffer: impl Into<AnyBufferNode>,
region: Range<vk::DeviceSize>,
data: u32,
) -> Self {
let buffer = buffer.into();
self.set_subresource_access(buffer, region.clone(), AccessType::TransferWrite);
self.record_stream_mut(move |cmd| {
let buffer = cmd.resource(buffer);
unsafe {
cmd.device.cmd_fill_buffer(
cmd.handle,
buffer.handle,
region.start,
region.end - region.start,
data,
);
}
});
self
}
pub(crate) fn record_stream(
mut self,
func: impl for<'r> Fn(CommandRef<'r>) + Send + Sync + 'static,
) -> Self {
self.record_stream_mut(func);
self
}
pub(crate) fn record_stream_mut(
&mut self,
func: impl for<'r> Fn(CommandRef<'r>) + Send + Sync + 'static,
) {
self.push_reusable_exec(func);
}
pub fn resource<N>(&self, resource_node: N) -> &N::Resource
where
N: Node,
{
self.graph.resource(resource_node)
}
pub fn resource_access<N>(mut self, resource_node: N, access: AccessType) -> Self
where
N: Node + Subresource,
SubresourceRange: From<N::Range>,
{
self.set_resource_access(resource_node, access);
self
}
pub fn set_debug_name(&mut self, name: impl Into<String>) -> &mut Self {
#[cfg(debug_assertions)]
{
self.cmd_mut().name = Some(name.into());
}
#[cfg(not(debug_assertions))]
{
let _ = name;
}
self
}
pub fn set_resource_access<N>(&mut self, resource_node: N, access: AccessType)
where
N: Node + Subresource,
SubresourceRange: From<N::Range>,
{
let whole_resource = resource_node.range(&self.graph.resources);
let subresource = SubresourceRange::from(whole_resource);
self.push_subresource_access(resource_node, subresource, access);
}
pub(crate) fn set_stream_scope_id(&mut self, stream_scope_id: u64) {
self.cmd_mut().stream_scope_id = Some(stream_scope_id);
}
pub fn set_subresource_access<N>(
&mut self,
resource_node: N,
subresource: impl Into<N::Range>,
access: AccessType,
) where
N: Node + Subresource,
SubresourceRange: From<N::Range>,
{
let subresource = subresource.into();
let subresource = SubresourceRange::from(subresource);
self.push_subresource_access(resource_node, subresource, access);
}
pub fn subresource_access<N>(
mut self,
resource_node: N,
subresource: impl Into<N::Range>,
access: AccessType,
) -> Self
where
N: Node + Subresource,
SubresourceRange: From<N::Range>,
{
self.set_subresource_access(resource_node, subresource, access);
self
}
#[profiling::function]
pub fn update_buffer(
mut self,
buffer: impl Into<AnyBufferNode>,
offset: vk::DeviceSize,
data: impl AsRef<[u8]> + 'static + Send,
) -> Self {
debug_assert!(data.as_ref().len() <= 64 * 1024);
let buffer = buffer.into();
let data_end = offset + data.as_ref().len() as vk::DeviceSize;
#[cfg(feature = "checked")]
{
assert!(
data.as_ref().len() <= 64 * 1024,
"data length ({}) exceeds vkCmdUpdateBuffer limit (65536)",
data.as_ref().len()
);
let buffer_info = self.graph.resources[buffer.index()].expect_buffer_info();
assert!(
data_end <= buffer_info.size,
"data range end ({data_end}) exceeds buffer size ({})",
buffer_info.size
);
}
let data = Arc::<[u8]>::from(data.as_ref());
self.set_subresource_access(buffer, offset..data_end, AccessType::TransferWrite);
self.record_stream_mut(move |cmd| {
let buffer = cmd.resource(buffer);
unsafe {
cmd.device
.cmd_update_buffer(cmd.handle, buffer.handle, offset, &data);
}
});
self
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Binding {
pub binding: u32,
pub offset: u32,
pub set: u32,
}
impl Binding {
pub(super) fn into_tuple(self) -> (DescriptorSetIndex, BindingIndex, BindingOffset) {
(self.set, self.binding, self.offset)
}
pub(super) fn set(self) -> DescriptorSetIndex {
let (res, _, _) = self.into_tuple();
res
}
}
impl From<BindingIndex> for Binding {
fn from(binding: BindingIndex) -> Self {
Self {
binding,
offset: 0,
set: 0,
}
}
}
impl From<(DescriptorSetIndex, BindingIndex)> for Binding {
fn from((set, binding): (DescriptorSetIndex, BindingIndex)) -> Self {
Self {
binding,
offset: 0,
set,
}
}
}
impl From<(BindingIndex, [BindingOffset; 1])> for Binding {
fn from((binding, [offset]): (BindingIndex, [BindingOffset; 1])) -> Self {
Self {
binding,
offset,
set: 0,
}
}
}
impl From<(DescriptorSetIndex, BindingIndex, [BindingOffset; 1])> for Binding {
fn from(
(set, binding, [offset]): (DescriptorSetIndex, BindingIndex, [BindingOffset; 1]),
) -> Self {
Self {
binding,
offset,
set,
}
}
}
#[allow(private_bounds)]
pub trait Subresource: private::SubresourceSealed {
type Info;
type Range;
}
macro_rules! view_accel_struct {
($name:ty) => {
impl Subresource for $name {
type Info = Self::Range;
type Range = ();
}
impl private::SubresourceSealed for $name {
fn info(&self, _: &[AnyResource]) -> <Self as Subresource>::Info
where
Self: Node + Subresource,
{
}
fn range(&self, resources: &[AnyResource]) -> <Self as Subresource>::Range
where
Self: Node + Subresource,
{
resources[self.index()].expect_accel_struct_info();
}
}
};
}
view_accel_struct!(AnyAccelerationStructureNode);
view_accel_struct!(AccelerationStructureArg);
view_accel_struct!(AccelerationStructureLeaseNode);
view_accel_struct!(AccelerationStructureNode);
macro_rules! view_buffer {
($name:ty) => {
impl Subresource for $name {
type Info = Self::Range;
type Range = BufferSubresourceRange;
}
impl private::SubresourceSealed for $name {
fn info(&self, resources: &[AnyResource]) -> <Self as Subresource>::Info
where
Self: Node + Subresource,
{
self.range(resources)
}
fn range(&self, resources: &[AnyResource]) -> <Self as Subresource>::Range
where
Self: Node + Subresource,
{
let idx = self.index();
resources[idx].expect_buffer_info().into()
}
}
};
}
view_buffer!(AnyBufferNode);
view_buffer!(BufferArg);
view_buffer!(BufferLeaseNode);
view_buffer!(BufferNode);
macro_rules! view_image {
($name:ty) => {
impl Subresource for $name {
type Info = ImageViewInfo;
type Range = vk::ImageSubresourceRange;
}
impl private::SubresourceSealed for $name {
fn info(&self, resources: &[AnyResource]) -> <Self as Subresource>::Info
where
Self: Node + Subresource,
{
let idx = self.index();
resources[idx].expect_image_info().into()
}
fn range(&self, resources: &[AnyResource]) -> <Self as Subresource>::Range
where
Self: Node + Subresource,
{
self.info(resources).into()
}
}
};
}
view_image!(AnyImageNode);
view_image!(ImageArg);
view_image!(ImageLeaseNode);
view_image!(ImageNode);
view_image!(SwapchainImageNode);
#[derive(Clone, Copy, Debug)]
pub(crate) enum SubresourceRange {
AccelerationStructure,
Image(vk::ImageSubresourceRange),
Buffer(BufferSubresourceRange),
}
impl SubresourceRange {
pub(super) fn as_image(&self) -> Option<&vk::ImageSubresourceRange> {
if let Self::Image(subresource) = self {
Some(subresource)
} else {
None
}
}
pub(super) fn expect_image(&self) -> &vk::ImageSubresourceRange {
self.as_image().expect("missing image subresource")
}
}
impl From<BufferSubresourceRange> for SubresourceRange {
fn from(subresource: BufferSubresourceRange) -> Self {
Self::Buffer(subresource)
}
}
impl From<()> for SubresourceRange {
fn from(_: ()) -> Self {
Self::AccelerationStructure
}
}
impl From<ImageViewInfo> for SubresourceRange {
fn from(subresource: ImageViewInfo) -> Self {
Self::Image(subresource.into())
}
}
impl From<vk::ImageSubresourceRange> for SubresourceRange {
fn from(subresource: vk::ImageSubresourceRange) -> Self {
Self::Image(subresource)
}
}
#[derive(Clone, Copy, Debug)]
pub(super) struct SubresourceAccess {
pub access: AccessType,
pub subresource: SubresourceRange,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum ViewInfo {
AccelerationStructure,
Image(ImageViewInfo),
Buffer(BufferSubresourceRange),
}
impl ViewInfo {
pub(crate) fn as_buffer(&self) -> Option<&BufferSubresourceRange> {
match self {
Self::Buffer(info) => Some(info),
_ => None,
}
}
pub(crate) fn as_image(&self) -> Option<&ImageViewInfo> {
match self {
Self::Image(info) => Some(info),
_ => None,
}
}
pub(crate) fn expect_buffer(&self) -> &BufferSubresourceRange {
self.as_buffer().expect("missing buffer view info")
}
pub(crate) fn expect_image(&self) -> &ImageViewInfo {
self.as_image().expect("missing image view info")
}
}
impl From<()> for ViewInfo {
fn from(_: ()) -> Self {
Self::AccelerationStructure
}
}
impl From<BufferSubresourceRange> for ViewInfo {
fn from(info: BufferSubresourceRange) -> Self {
Self::Buffer(info)
}
}
impl From<ImageViewInfo> for ViewInfo {
fn from(info: ImageViewInfo) -> Self {
Self::Image(info)
}
}
impl From<Range<vk::DeviceSize>> for ViewInfo {
fn from(range: Range<vk::DeviceSize>) -> Self {
Self::Buffer(BufferSubresourceRange {
start: range.start,
end: range.end,
})
}
}
mod private {
use crate::{AnyResource, Node};
pub(crate) trait SubresourceSealed: Sized {
fn info(&self, resources: &[AnyResource]) -> <Self as super::Subresource>::Info
where
Self: Node + super::Subresource;
fn range(&self, resources: &[AnyResource]) -> <Self as super::Subresource>::Range
where
Self: Node + super::Subresource;
}
}