primase_core/shader/
facts.rs1use iridia_interface::{D3dBinding, InstructionCount, Interface, ResourceId, Stage, Varying};
3use serde::Serialize;
4
5use super::roles::OutputBinding;
6use super::surface::Surface;
7use crate::{Component, Entity, Geometry, World};
8
9#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
11pub struct ProgramResourceFacts {
12 pub id: ResourceId,
14 pub name: String,
16 pub d3d: Option<D3dBinding>,
18}
19
20#[derive(Clone, Debug, PartialEq, Serialize)]
23pub struct ProgramFacts {
24 pub name: String,
26 pub hash: Option<String>,
29 pub stage: Stage,
31 pub shader: Option<Entity>,
33 pub instruction_count: Option<InstructionCount>,
35 pub inputs: Vec<Varying>,
37 pub resources: Vec<ProgramResourceFacts>,
39 pub outputs: Vec<OutputBinding>,
41 pub surface: Surface,
43 pub not_lifted: Option<String>,
45}
46impl ProgramFacts {
47 pub fn lifted(
51 name: impl Into<String>,
52 stage: Stage,
53 hash: Option<String>,
54 instruction_count: Option<InstructionCount>,
55 interface: &Interface,
56 ) -> Self {
57 Self {
58 name: name.into(),
59 hash,
60 stage,
61 shader: None,
62 instruction_count,
63 inputs: interface
64 .inputs
65 .iter()
66 .filter(|input| input.used)
67 .cloned()
68 .collect(),
69 resources: interface
70 .resources
71 .iter()
72 .map(|resource| ProgramResourceFacts {
73 id: resource.id,
74 name: resource.provenance.name.clone(),
75 d3d: resource.provenance.d3d,
76 })
77 .collect(),
78 outputs: Vec::new(),
79 surface: Surface::default(),
80 not_lifted: None,
81 }
82 }
83 pub fn unavailable(
86 name: impl Into<String>,
87 stage: Stage,
88 hash: Option<String>,
89 reason: impl Into<String>,
90 ) -> Self {
91 Self {
92 name: name.into(),
93 hash,
94 stage,
95 shader: None,
96 instruction_count: None,
97 inputs: Vec::new(),
98 resources: Vec::new(),
99 outputs: Vec::new(),
100 surface: Surface::default(),
101 not_lifted: Some(reason.into()),
102 }
103 }
104 pub fn bound(mut self, shader: Entity, outputs: &[OutputBinding]) -> Self {
106 self.shader = Some(shader);
107 self.outputs = outputs.to_vec();
108 self.surface = Surface::read(self.outputs.iter().map(|output| (output.lanes, &output.role)));
109 self
110 }
111}
112
113impl Component for ProgramFacts {
114 const NAME: &'static str = "core.program_facts";
115 const GEOMETRY: Geometry = Geometry::None;
116 fn to_json(&self) -> Result<Option<serde_json::Value>, crate::json::JsonError> {
117 crate::json::to_value(self).map(Some)
118 }
119 fn references(&self, out: &mut Vec<Entity>) {
120 out.extend(self.shader);
121 }
122 fn verify(&self, _e: Entity, _w: &World) -> Result<(), String> {
123 if self.not_lifted.is_some() && self.instruction_count.is_some() {
124 return Err("an unlifted program claims an instruction count".into());
125 }
126 Ok(())
127 }
128 fn apply_linear(&self, _l: &crate::Linear) -> crate::world::Linearity<Self> {
129 crate::world::Linearity::Invariant
130 }
131}
132#[derive(Clone, Debug, Default, PartialEq, Serialize)]
134pub struct MaterialPrograms(pub Vec<ProgramFacts>);
135impl Component for MaterialPrograms {
136 const NAME: &'static str = "core.material_programs";
137 const GEOMETRY: Geometry = Geometry::None;
138 fn to_json(&self) -> Result<Option<serde_json::Value>, crate::json::JsonError> {
139 crate::json::to_value(self).map(Some)
140 }
141 fn references(&self, out: &mut Vec<Entity>) {
142 for program in &self.0 {
143 program.references(out);
144 }
145 }
146 fn verify(&self, e: Entity, w: &World) -> Result<(), String> {
147 for program in &self.0 {
148 program.verify(e, w)?;
149 }
150 Ok(())
151 }
152 fn apply_linear(&self, _l: &crate::Linear) -> crate::world::Linearity<Self> {
153 crate::world::Linearity::Invariant
154 }
155}