1use phaneron_plugin::InterlaceMode;
20
21use crate::{
22 compute::AsKernalParamU32,
23 io::{Packer, Unpacker},
24};
25
26const PIXELS_PER_WORK_ITEM: usize = 64;
27
28fn get_pitch(width: usize) -> usize {
29 width
30}
31
32fn get_pitch_bytes(width: usize) -> usize {
33 get_pitch(width) * 4
34}
35
36pub struct RGBA8Reader {
37 width: usize,
38 height: usize,
39 num_bytes: Vec<usize>,
40 work_items_per_group: usize,
41 global_work_items: usize,
42}
43
44impl RGBA8Reader {
45 pub fn new(width: usize, height: usize) -> Self {
46 let num_bytes = vec![get_pitch_bytes(width) * height];
47 let work_items_per_group = get_pitch(width) / PIXELS_PER_WORK_ITEM;
48 let global_work_items = work_items_per_group * height;
49
50 Self {
51 width,
52 height,
53 num_bytes,
54 work_items_per_group,
55 global_work_items,
56 }
57 }
58}
59
60impl Packer for RGBA8Reader {
61 fn get_name(&self) -> &str {
62 "RGBA8 Reader"
63 }
64
65 fn get_kernel(&self) -> &str {
66 include_str!("../../shaders/video_process/load/rgba8.cl")
67 }
68
69 fn get_width(&self) -> usize {
70 self.width
71 }
72
73 fn get_height(&self) -> usize {
74 self.height
75 }
76
77 fn get_num_bits(&self) -> usize {
78 8
79 }
80
81 fn get_luma_black(&self) -> f32 {
82 64.0
83 }
84
85 fn get_luma_white(&self) -> f32 {
86 940.0
87 }
88
89 fn get_chroma_range(&self) -> f32 {
90 896.0
91 }
92
93 fn get_num_bytes(&self) -> Vec<usize> {
94 self.num_bytes.clone()
95 }
96
97 fn get_num_bytes_rgba(&self) -> usize {
98 self.width * self.height * 4 * 4
99 }
100
101 fn get_is_rgb(&self) -> bool {
102 true
103 }
104
105 fn get_total_bytes(&self) -> usize {
106 self.num_bytes.iter().sum()
107 }
108
109 fn get_work_items_per_group(&self) -> usize {
110 self.work_items_per_group
111 }
112
113 fn get_global_work_items(&self) -> usize {
114 self.global_work_items
115 }
116
117 fn get_kernel_params(
118 &self,
119 kernel: &mut opencl3::kernel::ExecuteKernel,
120 inputs: &[&opencl3::memory::Buffer<opencl3::types::cl_uchar>],
121 output: &mut opencl3::memory::Buffer<opencl3::types::cl_uchar>,
122 ) {
123 if inputs.len() != 1 {
124 panic!(
125 "Reader for {} requires exactly 1 input, received {}",
126 self.get_name(),
127 inputs.len()
128 );
129 }
130
131 let width = self.width as u32;
132
133 unsafe { kernel.set_arg(inputs[0]).set_arg(output).set_arg(&width) };
134 }
135}
136
137pub struct RGBA8Writer {
138 width: usize,
139 height: usize,
140 interlace: InterlaceMode,
141 num_bytes: Vec<usize>,
142 work_items_per_group: usize,
143 global_work_items: usize,
144}
145
146impl RGBA8Writer {
147 pub fn new(width: usize, height: usize, interlace: InterlaceMode) -> Self {
148 let num_bytes = vec![get_pitch_bytes(width) * height];
149 let work_items_per_group = get_pitch(width) / PIXELS_PER_WORK_ITEM;
150 let global_work_items = (work_items_per_group * height)
151 / (match interlace {
152 InterlaceMode::Progressive => 1,
153 _ => 2,
154 });
155
156 Self {
157 width,
158 height,
159 interlace,
160 num_bytes,
161 work_items_per_group,
162 global_work_items,
163 }
164 }
165}
166
167impl Unpacker for RGBA8Writer {
168 fn get_name(&self) -> &str {
169 "RGBA8 Writer"
170 }
171
172 fn get_kernel(&self) -> &str {
173 include_str!("../../shaders/video_process/consume/rgba8.cl")
174 }
175
176 fn get_width(&self) -> usize {
177 self.width
178 }
179
180 fn get_height(&self) -> usize {
181 self.height
182 }
183
184 fn get_num_bits(&self) -> usize {
185 8
186 }
187
188 fn get_luma_black(&self) -> f32 {
189 64.0
190 }
191
192 fn get_luma_white(&self) -> f32 {
193 940.0
194 }
195
196 fn get_chroma_range(&self) -> f32 {
197 896.0
198 }
199
200 fn get_num_bytes(&self) -> Vec<usize> {
201 self.num_bytes.clone()
202 }
203
204 fn get_num_bytes_rgba(&self) -> usize {
205 self.width * self.height * 4 * 4
206 }
207
208 fn get_is_rgb(&self) -> bool {
209 true
210 }
211
212 fn get_total_bytes(&self) -> usize {
213 self.num_bytes.iter().sum()
214 }
215
216 fn get_work_items_per_group(&self) -> usize {
217 self.work_items_per_group
218 }
219
220 fn get_global_work_items(&self) -> usize {
221 self.global_work_items
222 }
223
224 fn get_kernel_params(
225 &self,
226 kernel: &mut opencl3::kernel::ExecuteKernel,
227 input: &opencl3::memory::Buffer<opencl3::types::cl_uchar>,
228 outputs: &mut Vec<opencl3::memory::Buffer<opencl3::types::cl_uchar>>,
229 ) {
230 if outputs.len() != 1 {
231 panic!(
232 "Writer for {} requires exactly 1 output, received {}",
233 self.get_name(),
234 outputs.len()
235 );
236 }
237
238 let width = self.width as u32;
239
240 unsafe {
241 kernel
242 .set_arg(input)
243 .set_arg(&outputs[0])
244 .set_arg(&width)
245 .set_arg(&self.interlace.as_kernel_param())
246 };
247 }
248}