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