1use {
4 super::{HotPipeline, compile_shaders_and_watch, create_watcher, pipeline, shader::HotShader},
5 log::info,
6 std::sync::{
7 Arc, RwLock,
8 atomic::{AtomicBool, Ordering},
9 },
10 vk_graph::{
11 cmd::{Command, Pipeline},
12 driver::{
13 DriverError,
14 device::Device,
15 graphics::{GraphicsPipeline, GraphicsPipelineInfo},
16 },
17 },
18};
19
20#[derive(Debug)]
22pub struct HotGraphicsPipeline {
23 cache: RwLock<HotPipeline<GraphicsPipeline>>,
24 device: Device,
25 has_changes: Arc<AtomicBool>,
26 shaders: Box<[HotShader]>,
27}
28
29impl HotGraphicsPipeline {
30 pub fn create<S>(
32 device: &Device,
33 info: impl Into<GraphicsPipelineInfo>,
34 shaders: impl IntoIterator<Item = S>,
35 ) -> Result<Self, DriverError>
36 where
37 S: Into<HotShader>,
38 {
39 let shaders = shaders.into_iter().map(Into::into).collect::<Box<_>>();
40
41 let has_changes = Default::default();
42 let mut watcher = create_watcher(&has_changes);
43
44 let pipeline = {
45 GraphicsPipeline::create(
46 device,
47 info,
48 compile_shaders_and_watch(&shaders, &mut watcher)?,
49 )
50 }?;
51
52 Ok(Self {
53 cache: RwLock::new(HotPipeline { pipeline, watcher }),
54 device: device.clone(),
55 has_changes,
56 shaders,
57 })
58 }
59
60 fn compile_shader_and_bind_cmd<'a>(
61 &self,
62 cmd: Command<'a>,
63 ) -> <GraphicsPipeline as Pipeline<'a>>::Command {
64 if self.has_changes.swap(false, Ordering::Relaxed) {
65 info!("Shader change detected");
66
67 let mut cache = self.cache_mut();
68
69 if let Ok(shaders) = compile_shaders_and_watch(&self.shaders, &mut cache.watcher)
70 && let Ok(pipeline) =
71 GraphicsPipeline::create(&self.device, cache.pipeline.info(), shaders)
72 {
73 cache.pipeline = pipeline;
74 }
75 }
76
77 self.cache().pipeline.clone().bind_cmd(cmd)
78 }
79}
80
81pipeline!(GraphicsPipeline);