use super::*;
use rafx_api::{RafxExtents3D, RafxFormat, RafxResourceType, RafxSampleCount, RafxTextureBindType};
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct RenderGraphImageUsageId(pub(super) usize);
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct VirtualImageId(pub(super) usize);
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct PhysicalImageId(pub(super) usize);
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct PhysicalImageViewId(pub(super) usize);
#[derive(Debug, Copy, Clone)]
pub struct RenderGraphExternalImageId(pub(super) usize);
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct RenderGraphImageVersionId {
pub(super) index: usize,
pub(super) version: usize,
}
#[derive(Debug)]
pub struct RenderGraphImageResource {
pub(super) name: Option<RenderGraphResourceName>,
pub(super) versions: Vec<RenderGraphImageResourceVersionInfo>,
}
impl RenderGraphImageResource {
pub(super) fn new() -> Self {
RenderGraphImageResource {
name: None,
versions: Default::default(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct RenderGraphImageView {
pub(super) physical_image: PhysicalImageId,
pub(super) format: RafxFormat,
pub(super) view_options: RenderGraphImageViewOptions,
}
#[derive(Debug, Clone, Copy)]
pub enum RenderGraphImageUser {
Node(RenderGraphNodeId),
Input(RenderGraphExternalImageId),
Output(RenderGraphExternalImageId),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum RenderGraphImageExtents {
MatchSurface,
Custom(RafxExtents3D),
}
impl RenderGraphImageExtents {
pub fn into_rafx_extents(
self,
swapchain_surface_info: &SwapchainSurfaceInfo,
) -> RafxExtents3D {
match self {
RenderGraphImageExtents::MatchSurface => RafxExtents3D {
width: swapchain_surface_info.extents.width,
height: swapchain_surface_info.extents.height,
depth: 1,
},
RenderGraphImageExtents::Custom(extents) => extents,
}
}
}
impl Default for RenderGraphImageExtents {
fn default() -> Self {
RenderGraphImageExtents::MatchSurface
}
}
#[derive(Default, Clone, Debug, PartialEq, Eq, Hash)]
pub struct RenderGraphImageViewOptions {
pub texture_bind_type: Option<RafxTextureBindType>,
pub array_slice: Option<u16>,
pub mip_slice: Option<u8>,
}
impl RenderGraphImageViewOptions {
pub fn array_slice(array_slice: u16) -> Self {
RenderGraphImageViewOptions {
texture_bind_type: None,
array_slice: Some(array_slice),
mip_slice: None,
}
}
pub fn mip_slice(mip_slice: u8) -> Self {
RenderGraphImageViewOptions {
texture_bind_type: None,
array_slice: None,
mip_slice: Some(mip_slice),
}
}
}
#[derive(Debug)]
pub struct RenderGraphImageUsage {
pub(super) user: RenderGraphImageUser,
pub(super) usage_type: RenderGraphImageUsageType,
pub(super) version: RenderGraphImageVersionId,
pub(super) view_options: RenderGraphImageViewOptions,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct RenderGraphImageSpecification {
pub samples: RafxSampleCount,
pub format: RafxFormat,
pub resource_type: RafxResourceType,
pub extents: RafxExtents3D,
pub layer_count: u32,
pub mip_count: u32,
}
impl RenderGraphImageSpecification {
pub fn can_merge(
&self,
other: &RenderGraphImageSpecification,
) -> bool {
if self.samples != other.samples {
return false;
}
if self.format != other.format {
return false;
}
if self.mip_count != other.mip_count {
return false;
}
if self.layer_count != other.layer_count {
return false;
}
if self.extents != other.extents {
return false;
}
true
}
pub fn try_merge(
&mut self,
other: &RenderGraphImageSpecification,
) -> bool {
if !self.can_merge(other) {
return false;
}
self.resource_type |= other.resource_type;
true
}
pub fn specifications_are_compatible(
written: &RenderGraphImageSpecification,
read: &RenderGraphImageSpecification,
) -> bool {
if written.samples != read.samples {
return false;
}
if written.format != read.format {
return false;
}
if written.mip_count != read.mip_count {
return false;
}
if written.layer_count != read.layer_count {
return false;
}
if written.extents != read.extents {
return false;
}
if (written.resource_type | read.resource_type) != written.resource_type {
return false;
}
return true;
}
}
#[derive(Default, Clone, Debug)]
pub struct RenderGraphImageConstraint {
pub samples: Option<RafxSampleCount>,
pub format: Option<RafxFormat>,
pub resource_type: RafxResourceType,
pub extents: Option<RenderGraphImageExtents>,
pub layer_count: Option<u32>,
pub mip_count: Option<u32>,
}
impl From<RenderGraphImageSpecification> for RenderGraphImageConstraint {
fn from(specification: RenderGraphImageSpecification) -> Self {
RenderGraphImageConstraint {
samples: Some(specification.samples),
format: Some(specification.format),
resource_type: specification.resource_type,
layer_count: Some(specification.layer_count),
mip_count: Some(specification.mip_count),
extents: Some(RenderGraphImageExtents::Custom(specification.extents)),
}
}
}
impl RenderGraphImageConstraint {
pub fn try_convert_to_specification(
self,
swapchain_surface_info: &SwapchainSurfaceInfo,
) -> Option<RenderGraphImageSpecification> {
if self.format.is_none() {
None
} else {
Some(RenderGraphImageSpecification {
samples: self.samples.unwrap_or(RafxSampleCount::SampleCount1),
format: self.format.unwrap(),
layer_count: self.layer_count.unwrap_or(1),
mip_count: self.mip_count.unwrap_or(1),
extents: self
.extents
.unwrap_or(RenderGraphImageExtents::MatchSurface)
.into_rafx_extents(swapchain_surface_info),
resource_type: self.resource_type,
})
}
}
}
impl RenderGraphImageConstraint {
pub fn can_merge(
&self,
other: &RenderGraphImageConstraint,
) -> bool {
if self.samples.is_some() && other.samples.is_some() && self.samples != other.samples {
return false;
}
if self.format.is_some() && other.format.is_some() && self.format != other.format {
return false;
}
if self.layer_count.is_some()
&& other.layer_count.is_some()
&& self.layer_count != other.layer_count
{
return false;
}
if self.mip_count.is_some()
&& other.mip_count.is_some()
&& self.mip_count != other.mip_count
{
return false;
}
if self.extents.is_some() && other.extents.is_some() && self.extents != other.extents {
return false;
}
true
}
pub fn try_merge(
&mut self,
other: &RenderGraphImageConstraint,
) -> bool {
if !self.can_merge(other) {
return false;
}
if self.samples.is_none() && other.samples.is_some() {
self.samples = other.samples;
}
if self.format.is_none() && other.format.is_some() {
self.format = other.format;
}
if self.layer_count.is_none() && other.layer_count.is_some() {
self.layer_count = other.layer_count;
}
if self.mip_count.is_none() && other.mip_count.is_some() {
self.mip_count = other.mip_count;
}
if self.extents.is_none() && other.extents.is_some() {
self.extents = other.extents;
}
self.resource_type |= other.resource_type;
true
}
pub fn partial_merge(
&mut self,
other: &RenderGraphImageConstraint,
) -> bool {
let mut complete_merge = true;
if self.samples.is_some() && other.samples.is_some() && self.samples != other.samples {
complete_merge = false;
} else if other.samples.is_some() {
self.samples = other.samples;
}
if self.format.is_some() && other.format.is_some() && self.format != other.format {
complete_merge = false;
} else if other.format.is_some() {
self.format = other.format;
}
if self.layer_count.is_some()
&& other.layer_count.is_some()
&& self.layer_count != other.layer_count
{
complete_merge = false;
} else if other.layer_count.is_some() {
self.layer_count = other.layer_count;
}
if self.mip_count.is_some()
&& other.mip_count.is_some()
&& self.mip_count != other.mip_count
{
complete_merge = false;
} else if other.mip_count.is_some() {
self.mip_count = other.mip_count;
}
if self.extents.is_some() && other.extents.is_some() && self.extents != other.extents {
complete_merge = false;
} else if other.extents.is_some() {
self.extents = other.extents;
}
self.resource_type |= other.resource_type;
complete_merge
}
pub fn set(
&mut self,
other: &RenderGraphImageSpecification,
) {
*self = other.clone().into();
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum RenderGraphImageUsageType {
Create,
Input,
Read,
ModifyRead,
ModifyWrite,
Output,
}
impl RenderGraphImageUsageType {
pub fn is_read_only(&self) -> bool {
match self {
RenderGraphImageUsageType::Read => true,
RenderGraphImageUsageType::Output => true,
RenderGraphImageUsageType::ModifyRead => false,
RenderGraphImageUsageType::Create => false,
RenderGraphImageUsageType::Input => false,
RenderGraphImageUsageType::ModifyWrite => false,
}
}
}
#[derive(Debug)]
pub struct RenderGraphImageResourceVersionInfo {
pub(super) creator_node: RenderGraphNodeId,
pub(super) create_usage: RenderGraphImageUsageId,
pub(super) read_usages: Vec<RenderGraphImageUsageId>,
}
impl RenderGraphImageResourceVersionInfo {
pub(super) fn new(
creator: RenderGraphNodeId,
create_usage: RenderGraphImageUsageId,
) -> Self {
RenderGraphImageResourceVersionInfo {
creator_node: creator,
create_usage,
read_usages: Default::default(),
}
}
pub(super) fn remove_read_usage(
&mut self,
usage: RenderGraphImageUsageId,
) {
if let Some(position) = self.read_usages.iter().position(|x| *x == usage) {
self.read_usages.swap_remove(position);
}
}
pub(super) fn add_read_usage(
&mut self,
usage: RenderGraphImageUsageId,
) {
self.read_usages.push(usage);
}
}