wgpu_hal/vulkan/
semaphore_list.rs1use alloc::vec::Vec;
4use ash::vk;
5use core::mem::MaybeUninit;
6
7#[derive(Debug, PartialEq)]
8pub enum SemaphoreListMode {
9 Wait,
10 Signal,
11}
12
13#[derive(Debug)]
27pub struct SemaphoreList {
28 mode: SemaphoreListMode,
30
31 semaphores: Vec<vk::Semaphore>,
35
36 values: Vec<u64>,
46
47 pub stage_masks: Vec<vk::PipelineStageFlags>,
51}
52
53impl SemaphoreList {
54 pub fn new(mode: SemaphoreListMode) -> Self {
55 Self {
56 mode,
57 semaphores: Vec::new(),
58 values: Vec::new(),
59 stage_masks: Vec::new(),
60 }
61 }
62
63 pub fn is_empty(&self) -> bool {
64 self.semaphores.is_empty()
65 }
66
67 pub fn add_to_submit<'info, 'semaphores: 'info>(
78 wait_semaphores: &'semaphores mut Self,
79 signal_semaphores: &'semaphores mut Self,
80 submit_info: vk::SubmitInfo<'info>,
81 timeline_info: &'info mut MaybeUninit<vk::TimelineSemaphoreSubmitInfo<'info>>,
82 ) -> vk::SubmitInfo<'info> {
83 wait_semaphores.check();
84 signal_semaphores.check();
85
86 assert!(matches!(wait_semaphores.mode, SemaphoreListMode::Wait));
87 assert!(matches!(signal_semaphores.mode, SemaphoreListMode::Signal));
88
89 let timeline_info = timeline_info.write(vk::TimelineSemaphoreSubmitInfo::default());
90
91 let mut uses_timeline = false;
92
93 if !wait_semaphores.values.is_empty() {
94 *timeline_info = timeline_info.wait_semaphore_values(&wait_semaphores.values);
95 uses_timeline = true;
96 }
97
98 if !signal_semaphores.values.is_empty() {
99 *timeline_info = timeline_info.signal_semaphore_values(&signal_semaphores.values);
100 uses_timeline = true;
101 }
102
103 let mut submit_info = submit_info
104 .wait_semaphores(&wait_semaphores.semaphores)
105 .wait_dst_stage_mask(&wait_semaphores.stage_masks)
106 .signal_semaphores(&signal_semaphores.semaphores);
107
108 if uses_timeline {
109 submit_info = submit_info.push_next(timeline_info);
110 }
111
112 submit_info
113 }
114
115 pub fn push_signal(&mut self, semaphore: SemaphoreType) {
117 assert!(matches!(self.mode, SemaphoreListMode::Signal));
118 self.push_inner(semaphore);
119 }
120
121 pub fn push_wait(&mut self, semaphore: SemaphoreType, stage: vk::PipelineStageFlags) {
123 assert!(matches!(self.mode, SemaphoreListMode::Wait));
124
125 self.stage_masks.push(stage);
126 self.push_inner(semaphore);
127 }
128
129 fn push_inner(&mut self, semaphore: SemaphoreType) {
130 match semaphore {
131 SemaphoreType::Binary(semaphore) => {
132 self.semaphores.push(semaphore);
133 if !self.values.is_empty() {
135 self.values.push(!0);
136 }
137 }
138 SemaphoreType::Timeline(semaphore, value) => {
139 self.pad_values();
142 self.semaphores.push(semaphore);
143 self.values.push(value);
144 }
145 }
146
147 self.check();
148 }
149
150 pub fn append(&mut self, other: &mut Self) {
152 assert_eq!(self.mode, other.mode);
153
154 if !other.values.is_empty() {
156 self.pad_values();
157 }
158 self.semaphores.append(&mut other.semaphores);
159 self.values.append(&mut other.values);
160 if !self.values.is_empty() {
162 self.pad_values();
163 }
164 self.stage_masks.append(&mut other.stage_masks);
165 self.check();
166 }
167
168 fn pad_values(&mut self) {
173 self.values.resize(self.semaphores.len(), !0);
174 }
175
176 #[track_caller]
177 fn check(&self) {
178 debug_assert!(self.values.is_empty() || self.values.len() == self.semaphores.len());
179 match self.mode {
180 SemaphoreListMode::Wait => {
181 debug_assert!(
182 self.stage_masks.is_empty() || self.stage_masks.len() == self.semaphores.len()
183 );
184 }
185 SemaphoreListMode::Signal => {
186 debug_assert!(self.stage_masks.is_empty());
187 }
188 }
189 }
190}
191
192pub enum SemaphoreType {
193 Binary(vk::Semaphore),
194 Timeline(vk::Semaphore, u64),
195}