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,
CommandFunction, Execution, Graph, ImageLeaseNode, ImageNode, Node, Resource,
SwapchainImageNode,
},
crate::{
NodeIndex,
driver::{buffer::BufferSubresourceRange, image::ImageViewInfo},
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,
}
#[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,
});
Self {
cmd_idx,
exec_idx: 0,
graph,
}
}
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(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
}
}
#[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;
}
}