1use crate::gpu_types::UvRectKind;
15use crate::internal_types::{FrameMemory, FrameVec};
16use crate::renderer::MAX_VERTEX_TEXTURE_WIDTH;
17use crate::util::ScaleOffset;
18use api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceRect, LayoutRect, PictureRect};
19use api::{PremultipliedColorF, ImageFormat};
20use crate::device::Texel;
21use crate::render_task_graph::{RenderTaskGraph, RenderTaskId};
22
23pub struct GpuBufferBuilder {
24 pub i32: GpuBufferBuilderI,
25 pub f32: GpuBufferBuilderF,
26}
27
28pub type GpuBufferF = GpuBuffer<GpuBufferBlockF>;
29pub type GpuBufferBuilderF = GpuBufferBuilderImpl<GpuBufferBlockF>;
30
31pub type GpuBufferI = GpuBuffer<GpuBufferBlockI>;
32pub type GpuBufferBuilderI = GpuBufferBuilderImpl<GpuBufferBlockI>;
33
34pub type GpuBufferWriterF<'l> = GpuBufferWriter<'l, GpuBufferBlockF>;
35unsafe impl Texel for GpuBufferBlockF {
38 fn image_format() -> ImageFormat { ImageFormat::RGBAF32 }
39}
40
41unsafe impl Texel for GpuBufferBlockI {
42 fn image_format() -> ImageFormat { ImageFormat::RGBAI32 }
43}
44
45impl Default for GpuBufferBlockF {
46 fn default() -> Self {
47 GpuBufferBlockF::EMPTY
48 }
49}
50
51impl Default for GpuBufferBlockI {
52 fn default() -> Self {
53 GpuBufferBlockI::EMPTY
54 }
55}
56
57#[derive(Copy, Clone, Debug, MallocSizeOf)]
59#[cfg_attr(feature = "capture", derive(Serialize))]
60#[cfg_attr(feature = "replay", derive(Deserialize))]
61pub struct GpuBufferBlockF {
62 data: [f32; 4],
63}
64
65#[derive(Copy, Clone, Debug, MallocSizeOf)]
67#[cfg_attr(feature = "capture", derive(Serialize))]
68#[cfg_attr(feature = "replay", derive(Deserialize))]
69pub struct GpuBufferBlockI {
70 data: [i32; 4],
71}
72
73#[derive(Copy, Debug, Clone, MallocSizeOf, Eq, PartialEq)]
74#[cfg_attr(feature = "capture", derive(Serialize))]
75#[cfg_attr(feature = "replay", derive(Deserialize))]
76pub struct GpuBufferAddress {
77 pub u: u16,
78 pub v: u16,
79}
80
81impl GpuBufferAddress {
82 #[allow(dead_code)]
83 pub fn as_int(self) -> i32 {
84 self.v as i32 * MAX_VERTEX_TEXTURE_WIDTH as i32 + self.u as i32
88 }
89
90 pub const INVALID: GpuBufferAddress = GpuBufferAddress { u: !0, v: !0 };
91}
92
93impl GpuBufferBlockF {
94 pub const EMPTY: Self = GpuBufferBlockF { data: [0.0; 4] };
95}
96
97impl GpuBufferBlockI {
98 pub const EMPTY: Self = GpuBufferBlockI { data: [0; 4] };
99}
100
101impl Into<GpuBufferBlockF> for LayoutRect {
102 fn into(self) -> GpuBufferBlockF {
103 GpuBufferBlockF {
104 data: [
105 self.min.x,
106 self.min.y,
107 self.max.x,
108 self.max.y,
109 ],
110 }
111 }
112}
113
114impl Into<GpuBufferBlockF> for ScaleOffset {
115 fn into(self) -> GpuBufferBlockF {
116 GpuBufferBlockF {
117 data: [
118 self.scale.x,
119 self.scale.y,
120 self.offset.x,
121 self.offset.y,
122 ],
123 }
124 }
125}
126
127impl Into<GpuBufferBlockF> for PictureRect {
128 fn into(self) -> GpuBufferBlockF {
129 GpuBufferBlockF {
130 data: [
131 self.min.x,
132 self.min.y,
133 self.max.x,
134 self.max.y,
135 ],
136 }
137 }
138}
139
140impl Into<GpuBufferBlockF> for DeviceRect {
141 fn into(self) -> GpuBufferBlockF {
142 GpuBufferBlockF {
143 data: [
144 self.min.x,
145 self.min.y,
146 self.max.x,
147 self.max.y,
148 ],
149 }
150 }
151}
152
153impl Into<GpuBufferBlockF> for PremultipliedColorF {
154 fn into(self) -> GpuBufferBlockF {
155 GpuBufferBlockF {
156 data: [
157 self.r,
158 self.g,
159 self.b,
160 self.a,
161 ],
162 }
163 }
164}
165
166impl From<DeviceIntRect> for GpuBufferBlockF {
167 fn from(rect: DeviceIntRect) -> Self {
168 GpuBufferBlockF {
169 data: [
170 rect.min.x as f32,
171 rect.min.y as f32,
172 rect.max.x as f32,
173 rect.max.y as f32,
174 ],
175 }
176 }
177}
178
179impl From<DeviceIntRect> for GpuBufferBlockI {
180 fn from(rect: DeviceIntRect) -> Self {
181 GpuBufferBlockI {
182 data: [
183 rect.min.x,
184 rect.min.y,
185 rect.max.x,
186 rect.max.y,
187 ],
188 }
189 }
190}
191
192impl Into<GpuBufferBlockF> for [f32; 4] {
193 fn into(self) -> GpuBufferBlockF {
194 GpuBufferBlockF {
195 data: self,
196 }
197 }
198}
199
200impl Into<GpuBufferBlockI> for [i32; 4] {
201 fn into(self) -> GpuBufferBlockI {
202 GpuBufferBlockI {
203 data: self,
204 }
205 }
206}
207
208struct DeferredBlock {
210 task_id: RenderTaskId,
211 index: usize,
212}
213
214pub struct GpuBufferWriter<'a, T> {
216 buffer: &'a mut FrameVec<T>,
217 deferred: &'a mut Vec<DeferredBlock>,
218 index: usize,
219 block_count: usize,
220}
221
222impl<'a, T> GpuBufferWriter<'a, T> where T: Texel {
223 fn new(
224 buffer: &'a mut FrameVec<T>,
225 deferred: &'a mut Vec<DeferredBlock>,
226 index: usize,
227 block_count: usize,
228 ) -> Self {
229 GpuBufferWriter {
230 buffer,
231 deferred,
232 index,
233 block_count,
234 }
235 }
236
237 pub fn push_one<B>(&mut self, block: B) where B: Into<T> {
239 self.buffer.push(block.into());
240 }
241
242 pub fn push_render_task(&mut self, task_id: RenderTaskId) {
245 match task_id {
246 RenderTaskId::INVALID => {
247 self.buffer.push(T::default());
248 }
249 task_id => {
250 self.deferred.push(DeferredBlock {
251 task_id,
252 index: self.buffer.len(),
253 });
254 self.buffer.push(T::default());
255 }
256 }
257 }
258
259 pub fn finish(self) -> GpuBufferAddress {
261 assert_eq!(self.buffer.len(), self.index + self.block_count);
262
263 GpuBufferAddress {
264 u: (self.index % MAX_VERTEX_TEXTURE_WIDTH) as u16,
265 v: (self.index / MAX_VERTEX_TEXTURE_WIDTH) as u16,
266 }
267 }
268}
269
270impl<'a, T> Drop for GpuBufferWriter<'a, T> {
271 fn drop(&mut self) {
272 assert_eq!(self.buffer.len(), self.index + self.block_count, "Claimed block_count was not written");
273 }
274}
275
276pub struct GpuBufferBuilderImpl<T> {
277 data: FrameVec<T>,
280 deferred: Vec<DeferredBlock>,
283}
284
285impl<T> GpuBufferBuilderImpl<T> where T: Texel + std::convert::From<DeviceIntRect> {
286 pub fn new(memory: &FrameMemory) -> Self {
287 GpuBufferBuilderImpl {
288 data: memory.new_vec(),
289 deferred: Vec::new(),
290 }
291 }
292
293 #[allow(dead_code)]
294 pub fn push(
295 &mut self,
296 blocks: &[T],
297 ) -> GpuBufferAddress {
298 assert!(blocks.len() <= MAX_VERTEX_TEXTURE_WIDTH);
299
300 if (self.data.len() % MAX_VERTEX_TEXTURE_WIDTH) + blocks.len() > MAX_VERTEX_TEXTURE_WIDTH {
301 while self.data.len() % MAX_VERTEX_TEXTURE_WIDTH != 0 {
302 self.data.push(T::default());
303 }
304 }
305
306 let index = self.data.len();
307
308 self.data.extend_from_slice(blocks);
309
310 GpuBufferAddress {
311 u: (index % MAX_VERTEX_TEXTURE_WIDTH) as u16,
312 v: (index / MAX_VERTEX_TEXTURE_WIDTH) as u16,
313 }
314 }
315
316 pub fn write_blocks(
318 &mut self,
319 block_count: usize,
320 ) -> GpuBufferWriter<T> {
321 assert!(block_count <= MAX_VERTEX_TEXTURE_WIDTH);
322
323 if (self.data.len() % MAX_VERTEX_TEXTURE_WIDTH) + block_count > MAX_VERTEX_TEXTURE_WIDTH {
324 while self.data.len() % MAX_VERTEX_TEXTURE_WIDTH != 0 {
325 self.data.push(T::default());
326 }
327 }
328
329 let index = self.data.len();
330
331 GpuBufferWriter::new(
332 &mut self.data,
333 &mut self.deferred,
334 index,
335 block_count,
336 )
337 }
338
339 pub fn finalize(
340 mut self,
341 render_tasks: &RenderTaskGraph,
342 ) -> GpuBuffer<T> {
343 let required_len = (self.data.len() + MAX_VERTEX_TEXTURE_WIDTH-1) & !(MAX_VERTEX_TEXTURE_WIDTH-1);
344
345 for _ in 0 .. required_len - self.data.len() {
346 self.data.push(T::default());
347 }
348
349 let len = self.data.len();
350 assert!(len % MAX_VERTEX_TEXTURE_WIDTH == 0);
351
352 for block in self.deferred.drain(..) {
357 let render_task = &render_tasks[block.task_id];
358 let target_rect = render_task.get_target_rect();
359
360 let uv_rect = match render_task.uv_rect_kind() {
361 UvRectKind::Rect => {
362 target_rect
363 }
364 UvRectKind::Quad { top_left, bottom_right, .. } => {
365 let size = target_rect.size();
366
367 DeviceIntRect::new(
368 DeviceIntPoint::new(
369 target_rect.min.x + (top_left.x * size.width as f32).round() as i32,
370 target_rect.min.y + (top_left.y * size.height as f32).round() as i32,
371 ),
372 DeviceIntPoint::new(
373 target_rect.min.x + (bottom_right.x * size.width as f32).round() as i32,
374 target_rect.min.y + (bottom_right.y * size.height as f32).round() as i32,
375 ),
376 )
377 }
378 };
379
380 self.data[block.index] = uv_rect.into();
381 }
382
383 GpuBuffer {
384 data: self.data,
385 size: DeviceIntSize::new(MAX_VERTEX_TEXTURE_WIDTH as i32, (len / MAX_VERTEX_TEXTURE_WIDTH) as i32),
386 format: T::image_format(),
387 }
388 }
389}
390
391#[cfg_attr(feature = "capture", derive(Serialize))]
392#[cfg_attr(feature = "replay", derive(Deserialize))]
393pub struct GpuBuffer<T> {
394 pub data: FrameVec<T>,
395 pub size: DeviceIntSize,
396 pub format: ImageFormat,
397}
398
399impl<T> GpuBuffer<T> {
400 pub fn is_empty(&self) -> bool {
401 self.data.is_empty()
402 }
403}
404
405#[test]
406fn test_gpu_buffer_sizing_push() {
407 let frame_memory = FrameMemory::fallback();
408 let render_task_graph = RenderTaskGraph::new_for_testing();
409 let mut builder = GpuBufferBuilderF::new(&frame_memory);
410
411 let row = vec![GpuBufferBlockF::EMPTY; MAX_VERTEX_TEXTURE_WIDTH];
412 builder.push(&row);
413
414 builder.push(&[GpuBufferBlockF::EMPTY]);
415 builder.push(&[GpuBufferBlockF::EMPTY]);
416
417 let buffer = builder.finalize(&render_task_graph);
418 assert_eq!(buffer.data.len(), MAX_VERTEX_TEXTURE_WIDTH * 2);
419}
420
421#[test]
422fn test_gpu_buffer_sizing_writer() {
423 let frame_memory = FrameMemory::fallback();
424 let render_task_graph = RenderTaskGraph::new_for_testing();
425 let mut builder = GpuBufferBuilderF::new(&frame_memory);
426
427 let mut writer = builder.write_blocks(MAX_VERTEX_TEXTURE_WIDTH);
428 for _ in 0 .. MAX_VERTEX_TEXTURE_WIDTH {
429 writer.push_one(GpuBufferBlockF::EMPTY);
430 }
431 writer.finish();
432
433 let mut writer = builder.write_blocks(1);
434 writer.push_one(GpuBufferBlockF::EMPTY);
435 writer.finish();
436
437 let mut writer = builder.write_blocks(1);
438 writer.push_one(GpuBufferBlockF::EMPTY);
439 writer.finish();
440
441 let buffer = builder.finalize(&render_task_graph);
442 assert_eq!(buffer.data.len(), MAX_VERTEX_TEXTURE_WIDTH * 2);
443}