Skip to content

Commit

Permalink
WIP upload instances in RenderBackend
Browse files Browse the repository at this point in the history
  • Loading branch information
Zakor Gyula committed Dec 19, 2019
1 parent ec3ec2f commit e0fc277
Show file tree
Hide file tree
Showing 12 changed files with 945 additions and 112 deletions.
99 changes: 95 additions & 4 deletions webrender/src/batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use api::{YuvColorSpace, YuvFormat, ColorDepth, ColorRange, PremultipliedColorF,
use api::units::*;
use crate::clip::{ClipDataStore, ClipNodeFlags, ClipNodeRange, ClipItemKind, ClipStore};
use crate::clip_scroll_tree::{ClipScrollTree, ROOT_SPATIAL_NODE_INDEX, SpatialNodeIndex, CoordinateSystemId};
#[cfg(not(feature = "gl"))]
use crate::device::{InstanceBufferManager, InstanceLocation, PrimitiveType};
use crate::composite::{CompositeState, CompositeTile, CompositeTileSurface};
use crate::glyph_rasterizer::GlyphFormat;
use crate::gpu_cache::{GpuBlockData, GpuCache, GpuCacheHandle, GpuCacheAddress};
Expand All @@ -27,8 +29,11 @@ use crate::render_task::RenderTaskAddress;
use crate::renderer::{BlendMode, ImageBufferKind, ShaderColorMode};
use crate::renderer::{BLOCKS_PER_UV_RECT, MAX_VERTEX_TEXTURE_WIDTH};
use crate::resource_cache::{CacheItem, GlyphFetchResult, ImageRequest, ResourceCache, ImageProperties};
#[cfg(not(feature = "gl"))]
use rendy_memory::Heaps;
use smallvec::SmallVec;
use std::{f32, i32, usize};
use std::sync::{Arc, Mutex};
use crate::util::{project_rect, TransformedRectKind};

// Special sentinel value recognized by the shader. It is considered to be
Expand Down Expand Up @@ -337,6 +342,7 @@ impl OpaqueBatchList {
pub struct PrimitiveBatch {
pub key: BatchKey,
pub instances: Vec<PrimitiveInstanceData>,
pub instance_locations: Vec<InstanceLocation>,
pub features: BatchFeatures,
}

Expand All @@ -363,6 +369,7 @@ impl PrimitiveBatch {
PrimitiveBatch {
key,
instances: Vec::new(),
instance_locations: Vec::new(),
features: BatchFeatures::empty(),
}
}
Expand All @@ -371,6 +378,20 @@ impl PrimitiveBatch {
self.instances.extend(other.instances);
self.features |= other.features;
}

fn build<B: hal::Backend>(
&mut self,
buffer_manager: &mut InstanceBufferManager<B>,
device: &B::Device,
heaps: Arc<Mutex<Heaps<B>>>,
) {
let instances = self.instances.drain(..).map(|i| i.to_primitive_type()).collect::<Vec<_>>();
self.instance_locations = buffer_manager.add(
device,
&instances,
&mut heaps.lock().unwrap(),
);
}
}

#[cfg_attr(feature = "capture", derive(Serialize))]
Expand Down Expand Up @@ -439,6 +460,17 @@ impl AlphaBatchContainer {
min_batch_index = self.alpha_batches.len();
}
}
}
}

pub fn build<B: hal::Backend>(
&mut self,
buffer_manager: &mut InstanceBufferManager<B>,
device: &B::Device,
heaps: Arc<Mutex<Heaps<B>>>,
) {
for batch in self.opaque_batches.iter_mut().chain(self.alpha_batches.iter_mut()) {
batch.build(buffer_manager, device, heaps.clone());
}
}
}
Expand Down Expand Up @@ -2793,28 +2825,76 @@ pub fn resolve_image(
pub struct ClipBatchList {
/// Rectangle draws fill up the rectangles with rounded corners.
pub slow_rectangles: Vec<ClipMaskInstance>,
pub slow_rectangle_locations: Vec<InstanceLocation>,
pub fast_rectangles: Vec<ClipMaskInstance>,
pub fast_rectangle_locations: Vec<InstanceLocation>,
/// Image draws apply the image masking.
pub images: FastHashMap<TextureSource, Vec<ClipMaskInstance>>,
pub image_locations: FastHashMap<TextureSource, Vec<InstanceLocation>>,
pub box_shadows: FastHashMap<TextureSource, Vec<ClipMaskInstance>>,
pub box_shadow_locations: FastHashMap<TextureSource, Vec<InstanceLocation>>,
}

impl ClipBatchList {
fn new() -> Self {
ClipBatchList {
slow_rectangles: Vec::new(),
slow_rectangle_locations: Vec::new(),
fast_rectangles: Vec::new(),
fast_rectangle_locations: Vec::new(),
images: FastHashMap::default(),
image_locations: FastHashMap::default(),
box_shadows: FastHashMap::default(),
box_shadow_locations: FastHashMap::default(),
}
}

#[cfg(not(feature = "gl"))]
fn build<B: hal::Backend>(
&mut self,
buffer_manager: &mut InstanceBufferManager<B>,
device: &B::Device,
heaps: Arc<Mutex<Heaps<B>>>,
) {
let slow_rects = self.slow_rectangles.drain(..).map(|i| i.to_primitive_type()).collect::<Vec<_>>();
self.slow_rectangle_locations = buffer_manager.add(
device,
&slow_rects,
&mut heaps.lock().unwrap(),
);

let fast_rects = self.fast_rectangles.drain(..).map(|i| i.to_primitive_type()).collect::<Vec<_>>();
self.fast_rectangle_locations = buffer_manager.add(
device,
&fast_rects,
&mut heaps.lock().unwrap(),
);

for (source, instances) in self.images.drain() {
let locations = buffer_manager.add(
device,
&instances.iter().map(|i| i.to_primitive_type()).collect::<Vec<_>>(),
&mut heaps.lock().unwrap(),
);
self.image_locations.insert(source, locations);
}

for (source, instances) in self.box_shadows.drain() {
let locations = buffer_manager.add(
device,
&instances.iter().map(|i| i.to_primitive_type()).collect::<Vec<_>>(),
&mut heaps.lock().unwrap(),
);
self.box_shadow_locations.insert(source, locations);
}
}

#[cfg(not(feature = "gl"))]
pub fn is_empty(&self) -> bool {
self.slow_rectangles.is_empty()
&& self.fast_rectangles.is_empty()
&& self.images.is_empty()
&& self.box_shadows.is_empty()
self.slow_rectangle_locations.is_empty()
&& self.fast_rectangle_locations.is_empty()
&& self.image_locations.is_empty()
&& self.box_shadow_locations.is_empty()
}
}

Expand Down Expand Up @@ -2850,6 +2930,17 @@ impl ClipBatcher {
self.primary_clips.is_empty() && self.secondary_clips.is_empty()
}

#[cfg(not(feature = "gl"))]
pub fn build<B: hal::Backend>(
&mut self,
buffer_manager: &mut InstanceBufferManager<B>,
device: &B::Device,
heaps: Arc<Mutex<Heaps<B>>>,
) {
self.primary_clips.build(buffer_manager, device, heaps.clone());
self.secondary_clips.build(buffer_manager, device, heaps.clone());
}

pub fn add_clip_region(
&mut self,
clip_data_address: GpuCacheAddress,
Expand Down
143 changes: 141 additions & 2 deletions webrender/src/device/gfx/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ use rendy_memory::{Block, Heaps, Kind, MappedRange, MemoryBlock, MemoryUsage, Me
use std::cell::Cell;
use std::sync::Arc;
use std::mem;
use super::super::GpuFrameId;

use crate::internal_types::FastHashMap;

pub const DOWNLOAD_BUFFER_SIZE: usize = 10 << 20; // 10MB
pub const INVALID_BUFFER_ID: BufferId = BufferId(0);

#[derive(MallocSizeOf)]
pub struct BufferMemorySlice {
Expand Down Expand Up @@ -236,7 +240,7 @@ impl<B: hal::Backend> PersistentlyMappedBuffer<B> {
}
}

pub(super) struct Buffer<B: hal::Backend> {
pub struct Buffer<B: hal::Backend> {
pub(super) memory_block: MemoryBlock<B>,
pub(super) buffer: B::Buffer,
pub(super) buffer_size: usize,
Expand Down Expand Up @@ -445,11 +449,12 @@ impl<B: hal::Backend> BufferPool<B> {
}
}

pub(super) struct InstancePoolBuffer<B: hal::Backend> {
pub struct InstancePoolBuffer<B: hal::Backend> {
pub(super) buffer: Buffer<B>,
pub(super) offset: usize,
pub(super) last_update_size: usize,
pub(super) last_data_stride: usize,
pub(super) bound_in_frame: GpuFrameId,
non_coherent_atom_size_mask: usize,
}

Expand Down Expand Up @@ -477,6 +482,7 @@ impl<B: hal::Backend> InstancePoolBuffer<B> {
last_update_size: 0,
last_data_stride: 0,
non_coherent_atom_size_mask,
bound_in_frame: GpuFrameId(0),
}
}

Expand Down Expand Up @@ -521,6 +527,15 @@ impl<B: hal::Backend> InstancePoolBuffer<B> {
_ => self.offset + stride - remainder,
}
}

pub(super) fn still_in_flight(&self, frame_id: GpuFrameId, frame_count: usize) -> bool {
for i in 0..frame_count {
if self.bound_in_frame == GpuFrameId(frame_id.0 - i) {
return true;
}
}
false
}
}

pub(super) struct InstanceBufferHandler<B: hal::Backend> {
Expand Down Expand Up @@ -756,3 +771,127 @@ impl<B: hal::Backend> UniformBufferHandler<B> {
}
}
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct BufferId(i32);

#[derive(Debug)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct InstanceLocation {
pub buffer_id: BufferId,
pub range: std::ops::Range<u32>,
}

impl Default for InstanceLocation {
fn default() -> InstanceLocation {
InstanceLocation {
buffer_id: INVALID_BUFFER_ID,
range: 0..0,
}
}
}

impl InstanceLocation {
pub fn is_valid(&self) -> bool {
self.buffer_id != INVALID_BUFFER_ID
}
}

pub struct InstanceBufferManager<B: hal::Backend> {
pub(super) buffers: FastHashMap<BufferId, InstancePoolBuffer<B>>,
alignment_mask: usize,
non_coherent_atom_size_mask: usize,
buffer_size: usize,
next_id: BufferId,
}

impl<B: hal::Backend> InstanceBufferManager<B> {
pub fn new(
non_coherent_atom_size_mask: usize,
alignment_mask: usize,
buffer_size: usize,
) -> Self {
InstanceBufferManager {
buffers: FastHashMap::default(),
alignment_mask,
non_coherent_atom_size_mask,
buffer_size,
next_id: BufferId(1),
}
}

pub fn add<T: Copy>(
&mut self,
device: &B::Device,
mut instance_data: &[T],
heaps: &mut Heaps<B>,
) -> Vec<InstanceLocation> {
fn instance_data_to_u8_slice<T: Copy>(data: &[T]) -> &[u8] {
unsafe {
std::slice::from_raw_parts(
data.as_ptr() as *const u8,
data.len() * mem::size_of::<T>(),
)
}
}

let data_stride = mem::size_of::<T>();
let mut locations = Vec::new();
while !instance_data.is_empty() {
let need_new_buffer =
self.buffers.is_empty() || !self.current_buffer().can_store_data(data_stride);
if need_new_buffer {
let buffer = InstancePoolBuffer::new(
device,
heaps,
hal::buffer::Usage::VERTEX,
self.alignment_mask,
self.non_coherent_atom_size_mask,
self.buffer_size,
);
self.buffers.insert(self.next_id, buffer);
self.next_id = BufferId(self.next_id.0 + 1);
} else {
self.current_buffer_mut().align_offset_to(data_stride);
}
let update_size =
(self.current_buffer().space_left() / data_stride).min(instance_data.len());
self.current_buffer_mut().update(
device,
instance_data_to_u8_slice(&instance_data[0..update_size]),
data_stride,
);

// TODO(zakorgy): I don't think after this we still have to store last_update_size in the instance buffers
let end = self.current_buffer().offset / data_stride;
let start = end - self.current_buffer().last_update_size / data_stride;
locations.push(InstanceLocation {
buffer_id: BufferId(self.next_id.0 - 1),
range: start as u32 ..end as u32,
});
instance_data = &instance_data[update_size..];
}
locations
}

fn current_buffer(&self) -> &InstancePoolBuffer<B> {
&self.buffers[&BufferId(self.next_id.0 - 1)]
}

fn current_buffer_mut(&mut self) -> &mut InstancePoolBuffer<B> {
self.buffers.get_mut(&BufferId(self.next_id.0 - 1)).unwrap()
}

pub fn recorded_buffers(&mut self) -> FastHashMap<BufferId, InstancePoolBuffer<B>> {
mem::replace(&mut self.buffers, FastHashMap::default())
}

pub fn deinit(&mut self, device: &B::Device, heaps: &mut Heaps<B>) {
for (_, buffer) in self.buffers.drain() {
buffer.deinit(device, heaps);
}
}
}
Loading

0 comments on commit e0fc277

Please sign in to comment.