diff options
Diffstat (limited to 'gfx/wr/webrender/src/renderer/gpu_buffer.rs')
-rw-r--r-- | gfx/wr/webrender/src/renderer/gpu_buffer.rs | 173 |
1 files changed, 118 insertions, 55 deletions
diff --git a/gfx/wr/webrender/src/renderer/gpu_buffer.rs b/gfx/wr/webrender/src/renderer/gpu_buffer.rs index 58a8aa6cbd..c8a2b87b0c 100644 --- a/gfx/wr/webrender/src/renderer/gpu_buffer.rs +++ b/gfx/wr/webrender/src/renderer/gpu_buffer.rs @@ -13,21 +13,57 @@ use crate::renderer::MAX_VERTEX_TEXTURE_WIDTH; use api::units::{DeviceIntRect, DeviceIntSize, LayoutRect, PictureRect, DeviceRect}; -use api::{PremultipliedColorF}; +use api::{PremultipliedColorF, ImageFormat}; use crate::device::Texel; use crate::render_task_graph::{RenderTaskGraph, RenderTaskId}; +pub struct GpuBufferBuilder { + pub i32: GpuBufferBuilderI, + pub f32: GpuBufferBuilderF, +} + +pub type GpuBufferF = GpuBuffer<GpuBufferBlockF>; +pub type GpuBufferBuilderF = GpuBufferBuilderImpl<GpuBufferBlockF>; + +pub type GpuBufferI = GpuBuffer<GpuBufferBlockI>; +pub type GpuBufferBuilderI = GpuBufferBuilderImpl<GpuBufferBlockI>; + +unsafe impl Texel for GpuBufferBlockF { + fn image_format() -> ImageFormat { ImageFormat::RGBAF32 } +} + +unsafe impl Texel for GpuBufferBlockI { + fn image_format() -> ImageFormat { ImageFormat::RGBAI32 } +} -unsafe impl Texel for GpuBufferBlock {} +impl Default for GpuBufferBlockF { + fn default() -> Self { + GpuBufferBlockF::EMPTY + } +} + +impl Default for GpuBufferBlockI { + fn default() -> Self { + GpuBufferBlockI::EMPTY + } +} /// A single texel in RGBAF32 texture - 16 bytes. #[derive(Copy, Clone, Debug, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -pub struct GpuBufferBlock { +pub struct GpuBufferBlockF { data: [f32; 4], } +/// A single texel in RGBAI32 texture - 16 bytes. +#[derive(Copy, Clone, Debug, MallocSizeOf)] +#[cfg_attr(feature = "capture", derive(Serialize))] +#[cfg_attr(feature = "replay", derive(Deserialize))] +pub struct GpuBufferBlockI { + data: [i32; 4], +} + #[derive(Copy, Debug, Clone, MallocSizeOf, Eq, PartialEq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] @@ -48,13 +84,17 @@ impl GpuBufferAddress { pub const INVALID: GpuBufferAddress = GpuBufferAddress { u: !0, v: !0 }; } -impl GpuBufferBlock { - pub const EMPTY: Self = GpuBufferBlock { data: [0.0; 4] }; +impl GpuBufferBlockF { + pub const EMPTY: Self = GpuBufferBlockF { data: [0.0; 4] }; +} + +impl GpuBufferBlockI { + pub const EMPTY: Self = GpuBufferBlockI { data: [0; 4] }; } -impl Into<GpuBufferBlock> for LayoutRect { - fn into(self) -> GpuBufferBlock { - GpuBufferBlock { +impl Into<GpuBufferBlockF> for LayoutRect { + fn into(self) -> GpuBufferBlockF { + GpuBufferBlockF { data: [ self.min.x, self.min.y, @@ -65,9 +105,9 @@ impl Into<GpuBufferBlock> for LayoutRect { } } -impl Into<GpuBufferBlock> for PictureRect { - fn into(self) -> GpuBufferBlock { - GpuBufferBlock { +impl Into<GpuBufferBlockF> for PictureRect { + fn into(self) -> GpuBufferBlockF { + GpuBufferBlockF { data: [ self.min.x, self.min.y, @@ -78,9 +118,9 @@ impl Into<GpuBufferBlock> for PictureRect { } } -impl Into<GpuBufferBlock> for DeviceRect { - fn into(self) -> GpuBufferBlock { - GpuBufferBlock { +impl Into<GpuBufferBlockF> for DeviceRect { + fn into(self) -> GpuBufferBlockF { + GpuBufferBlockF { data: [ self.min.x, self.min.y, @@ -91,9 +131,9 @@ impl Into<GpuBufferBlock> for DeviceRect { } } -impl Into<GpuBufferBlock> for PremultipliedColorF { - fn into(self) -> GpuBufferBlock { - GpuBufferBlock { +impl Into<GpuBufferBlockF> for PremultipliedColorF { + fn into(self) -> GpuBufferBlockF { + GpuBufferBlockF { data: [ self.r, self.g, @@ -104,22 +144,43 @@ impl Into<GpuBufferBlock> for PremultipliedColorF { } } -impl Into<GpuBufferBlock> for DeviceIntRect { - fn into(self) -> GpuBufferBlock { - GpuBufferBlock { +impl From<DeviceIntRect> for GpuBufferBlockF { + fn from(rect: DeviceIntRect) -> Self { + GpuBufferBlockF { + data: [ + rect.min.x as f32, + rect.min.y as f32, + rect.max.x as f32, + rect.max.y as f32, + ], + } + } +} + +impl From<DeviceIntRect> for GpuBufferBlockI { + fn from(rect: DeviceIntRect) -> Self { + GpuBufferBlockI { data: [ - self.min.x as f32, - self.min.y as f32, - self.max.x as f32, - self.max.y as f32, + rect.min.x, + rect.min.y, + rect.max.x, + rect.max.y, ], } } } -impl Into<GpuBufferBlock> for [f32; 4] { - fn into(self) -> GpuBufferBlock { - GpuBufferBlock { +impl Into<GpuBufferBlockF> for [f32; 4] { + fn into(self) -> GpuBufferBlockF { + GpuBufferBlockF { + data: self, + } + } +} + +impl Into<GpuBufferBlockI> for [i32; 4] { + fn into(self) -> GpuBufferBlockI { + GpuBufferBlockI { data: self, } } @@ -132,16 +193,16 @@ struct DeferredBlock { } /// Interface to allow writing multiple GPU blocks, possibly of different types -pub struct GpuBufferWriter<'a> { - buffer: &'a mut Vec<GpuBufferBlock>, +pub struct GpuBufferWriter<'a, T> { + buffer: &'a mut Vec<T>, deferred: &'a mut Vec<DeferredBlock>, index: usize, block_count: usize, } -impl<'a> GpuBufferWriter<'a> { +impl<'a, T> GpuBufferWriter<'a, T> where T: Texel { fn new( - buffer: &'a mut Vec<GpuBufferBlock>, + buffer: &'a mut Vec<T>, deferred: &'a mut Vec<DeferredBlock>, index: usize, block_count: usize, @@ -155,7 +216,7 @@ impl<'a> GpuBufferWriter<'a> { } /// Push one (16 byte) block of data in to the writer - pub fn push_one<B>(&mut self, block: B) where B: Into<GpuBufferBlock> { + pub fn push_one<B>(&mut self, block: B) where B: Into<T> { self.buffer.push(block.into()); } @@ -166,7 +227,7 @@ impl<'a> GpuBufferWriter<'a> { task_id, index: self.buffer.len(), }); - self.buffer.push(GpuBufferBlock::EMPTY); + self.buffer.push(T::default()); } /// Close this writer, returning the GPU address of this set of block(s). @@ -180,20 +241,20 @@ impl<'a> GpuBufferWriter<'a> { } } -impl<'a> Drop for GpuBufferWriter<'a> { +impl<'a, T> Drop for GpuBufferWriter<'a, T> { fn drop(&mut self) { assert_eq!(self.buffer.len(), self.index + self.block_count, "Claimed block_count was not written"); } } -pub struct GpuBufferBuilder { - data: Vec<GpuBufferBlock>, +pub struct GpuBufferBuilderImpl<T> { + data: Vec<T>, deferred: Vec<DeferredBlock>, } -impl GpuBufferBuilder { +impl<T> GpuBufferBuilderImpl<T> where T: Texel + std::convert::From<DeviceIntRect> { pub fn new() -> Self { - GpuBufferBuilder { + GpuBufferBuilderImpl { data: Vec::new(), deferred: Vec::new(), } @@ -202,13 +263,13 @@ impl GpuBufferBuilder { #[allow(dead_code)] pub fn push( &mut self, - blocks: &[GpuBufferBlock], + blocks: &[T], ) -> GpuBufferAddress { assert!(blocks.len() <= MAX_VERTEX_TEXTURE_WIDTH); if (self.data.len() % MAX_VERTEX_TEXTURE_WIDTH) + blocks.len() > MAX_VERTEX_TEXTURE_WIDTH { while self.data.len() % MAX_VERTEX_TEXTURE_WIDTH != 0 { - self.data.push(GpuBufferBlock::EMPTY); + self.data.push(T::default()); } } @@ -226,12 +287,12 @@ impl GpuBufferBuilder { pub fn write_blocks( &mut self, block_count: usize, - ) -> GpuBufferWriter { + ) -> GpuBufferWriter<T> { assert!(block_count <= MAX_VERTEX_TEXTURE_WIDTH); if (self.data.len() % MAX_VERTEX_TEXTURE_WIDTH) + block_count > MAX_VERTEX_TEXTURE_WIDTH { while self.data.len() % MAX_VERTEX_TEXTURE_WIDTH != 0 { - self.data.push(GpuBufferBlock::EMPTY); + self.data.push(T::default()); } } @@ -248,11 +309,11 @@ impl GpuBufferBuilder { pub fn finalize( mut self, render_tasks: &RenderTaskGraph, - ) -> GpuBuffer { + ) -> GpuBuffer<T> { let required_len = (self.data.len() + MAX_VERTEX_TEXTURE_WIDTH-1) & !(MAX_VERTEX_TEXTURE_WIDTH-1); for _ in 0 .. required_len - self.data.len() { - self.data.push(GpuBufferBlock::EMPTY); + self.data.push(T::default()); } let len = self.data.len(); @@ -271,18 +332,20 @@ impl GpuBufferBuilder { GpuBuffer { data: self.data, size: DeviceIntSize::new(MAX_VERTEX_TEXTURE_WIDTH as i32, (len / MAX_VERTEX_TEXTURE_WIDTH) as i32), + format: T::image_format(), } } } #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -pub struct GpuBuffer { - pub data: Vec<GpuBufferBlock>, +pub struct GpuBuffer<T> { + pub data: Vec<T>, pub size: DeviceIntSize, + pub format: ImageFormat, } -impl GpuBuffer { +impl<T> GpuBuffer<T> { pub fn is_empty(&self) -> bool { self.data.is_empty() } @@ -292,13 +355,13 @@ impl GpuBuffer { #[test] fn test_gpu_buffer_sizing_push() { let render_task_graph = RenderTaskGraph::new_for_testing(); - let mut builder = GpuBufferBuilder::new(); + let mut builder = GpuBufferBuilderF::new(); - let row = vec![GpuBufferBlock::EMPTY; MAX_VERTEX_TEXTURE_WIDTH]; + let row = vec![GpuBufferBlockF::EMPTY; MAX_VERTEX_TEXTURE_WIDTH]; builder.push(&row); - builder.push(&[GpuBufferBlock::EMPTY]); - builder.push(&[GpuBufferBlock::EMPTY]); + builder.push(&[GpuBufferBlockF::EMPTY]); + builder.push(&[GpuBufferBlockF::EMPTY]); let buffer = builder.finalize(&render_task_graph); assert_eq!(buffer.data.len(), MAX_VERTEX_TEXTURE_WIDTH * 2); @@ -307,20 +370,20 @@ fn test_gpu_buffer_sizing_push() { #[test] fn test_gpu_buffer_sizing_writer() { let render_task_graph = RenderTaskGraph::new_for_testing(); - let mut builder = GpuBufferBuilder::new(); + let mut builder = GpuBufferBuilderF::new(); let mut writer = builder.write_blocks(MAX_VERTEX_TEXTURE_WIDTH); for _ in 0 .. MAX_VERTEX_TEXTURE_WIDTH { - writer.push_one(GpuBufferBlock::EMPTY); + writer.push_one(GpuBufferBlockF::EMPTY); } writer.finish(); let mut writer = builder.write_blocks(1); - writer.push_one(GpuBufferBlock::EMPTY); + writer.push_one(GpuBufferBlockF::EMPTY); writer.finish(); let mut writer = builder.write_blocks(1); - writer.push_one(GpuBufferBlock::EMPTY); + writer.push_one(GpuBufferBlockF::EMPTY); writer.finish(); let buffer = builder.finalize(&render_task_graph); |