j2k_cuda_runtime/execution/
queued.rs1use crate::{
4 error::CudaError,
5 memory::{
6 CudaBufferPoolReuseGuard, CudaDeviceBuffer, CudaDeviceBufferRange, CudaPooledDeviceBuffer,
7 },
8};
9
10#[doc(hidden)]
11#[derive(Debug)]
13pub struct CudaKernelOutput {
14 pub(crate) buffer: CudaDeviceBuffer,
15 pub(crate) execution: CudaExecutionStats,
16}
17
18#[doc(hidden)]
19#[derive(Debug)]
21pub struct CudaKernelBatchOutput {
22 pub(crate) outputs: Vec<CudaDeviceBuffer>,
23 pub(crate) execution: CudaExecutionStats,
24}
25
26#[doc(hidden)]
27#[derive(Debug)]
29pub struct CudaKernelContiguousBatchOutput {
30 pub(crate) output: CudaDeviceBuffer,
31 pub(crate) ranges: Vec<CudaDeviceBufferRange>,
32 pub(crate) execution: CudaExecutionStats,
33}
34
35#[doc(hidden)]
36#[derive(Debug)]
38pub struct CudaPooledKernelOutput {
39 pub(crate) buffer: CudaPooledDeviceBuffer,
40 pub(crate) execution: CudaExecutionStats,
41}
42
43#[doc(hidden)]
47#[derive(Debug)]
48#[must_use = "queued CUDA work must be finished or retained until Drop synchronizes it"]
49pub struct CudaQueuedExecution {
50 pub(crate) resources: Vec<CudaPooledDeviceBuffer>,
51 pub(crate) execution: CudaExecutionStats,
52 pub(crate) pool_reuse_guard: Option<CudaBufferPoolReuseGuard>,
53}
54
55impl CudaQueuedExecution {
56 pub fn execution(&self) -> CudaExecutionStats {
58 self.execution
59 }
60
61 pub fn resource_count(&self) -> usize {
63 self.resources.len()
64 }
65
66 pub fn finish(mut self) -> Result<CudaExecutionStats, CudaError> {
69 let completion_result = self
70 .pool_reuse_guard
71 .take()
72 .map_or(Ok(()), CudaBufferPoolReuseGuard::synchronize_and_release);
73 self.resources.clear();
74 completion_result?;
75 Ok(self.execution)
76 }
77
78 #[doc(hidden)]
87 pub unsafe fn release_pool_reuse_after_completion(&mut self) -> Result<(), CudaError> {
88 self.resources.clear();
89 if let Some(guard) = self.pool_reuse_guard.take() {
90 guard.release()?;
91 }
92 Ok(())
93 }
94}
95
96impl Drop for CudaQueuedExecution {
97 fn drop(&mut self) {
98 let Some(guard) = self.pool_reuse_guard.take() else {
99 return;
100 };
101
102 let outcome = guard.synchronize_pool_context();
106 self.resources.clear();
107 if outcome.completion_established() {
108 let _ = guard.release();
109 } else {
110 guard.abandon();
111 }
112 }
113}
114
115impl CudaKernelOutput {
116 pub fn buffer(&self) -> &CudaDeviceBuffer {
118 &self.buffer
119 }
120
121 pub fn execution(&self) -> CudaExecutionStats {
123 self.execution
124 }
125
126 pub fn into_parts(self) -> (CudaDeviceBuffer, CudaExecutionStats) {
128 (self.buffer, self.execution)
129 }
130}
131
132impl CudaKernelBatchOutput {
133 pub fn outputs(&self) -> &[CudaDeviceBuffer] {
135 &self.outputs
136 }
137
138 pub fn execution(&self) -> CudaExecutionStats {
140 self.execution
141 }
142
143 pub fn into_parts(self) -> (Vec<CudaDeviceBuffer>, CudaExecutionStats) {
145 (self.outputs, self.execution)
146 }
147}
148
149impl CudaKernelContiguousBatchOutput {
150 pub fn output(&self) -> &CudaDeviceBuffer {
152 &self.output
153 }
154
155 pub fn ranges(&self) -> &[CudaDeviceBufferRange] {
157 &self.ranges
158 }
159
160 pub fn execution(&self) -> CudaExecutionStats {
162 self.execution
163 }
164
165 pub fn into_parts(
167 self,
168 ) -> (
169 CudaDeviceBuffer,
170 Vec<CudaDeviceBufferRange>,
171 CudaExecutionStats,
172 ) {
173 (self.output, self.ranges, self.execution)
174 }
175}
176
177impl CudaPooledKernelOutput {
178 pub fn buffer(&self) -> Option<&CudaDeviceBuffer> {
180 self.buffer.as_device_buffer()
181 }
182
183 pub fn execution(&self) -> CudaExecutionStats {
185 self.execution
186 }
187
188 pub fn into_parts(self) -> (CudaPooledDeviceBuffer, CudaExecutionStats) {
190 (self.buffer, self.execution)
191 }
192}
193
194#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
196pub struct CudaExecutionStats {
197 pub(crate) kernel_dispatches: usize,
198 pub(crate) copy_kernel_dispatches: usize,
199 pub(crate) decode_kernel_dispatches: usize,
200 pub(crate) hardware_decode: bool,
201}
202
203impl CudaExecutionStats {
204 pub fn kernel_dispatches(self) -> usize {
206 self.kernel_dispatches
207 }
208
209 pub fn copy_kernel_dispatches(self) -> usize {
211 self.copy_kernel_dispatches
212 }
213
214 pub fn decode_kernel_dispatches(self) -> usize {
216 self.decode_kernel_dispatches
217 }
218
219 pub fn used_hardware_decode(self) -> bool {
221 self.hardware_decode
222 }
223}