Buffer transitions for a render pass

This commit is contained in:
Dzmitry Malyshau 2018-10-19 12:07:07 -04:00
parent f9cd55ed59
commit b27650bfcd
9 changed files with 130 additions and 67 deletions

View File

@ -1,5 +1,6 @@
use super::CommandBuffer;
use {DeviceId, Stored};
use track::{Tracker};
use hal::command::RawCommandBuffer;
use hal::pool::RawCommandPool;
@ -90,6 +91,8 @@ impl<B: hal::Backend> CommandAllocator<B> {
fence,
recorded_thread_id: thread_id,
device_id: Stored(device_id),
buffer_tracker: Tracker::new(),
texture_tracker: Tracker::new(),
}
}

View File

@ -13,9 +13,11 @@ use {
BufferId, CommandBufferId, ComputePassId, DeviceId, RenderPassId, TextureId, TextureViewId,
};
use registry::{HUB, Items, Registry};
use track::{BufferTracker, TextureTracker};
use std::thread::ThreadId;
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum LoadOp {
@ -76,6 +78,8 @@ pub struct CommandBuffer<B: hal::Backend> {
fence: B::Fence,
recorded_thread_id: ThreadId,
device_id: Stored<DeviceId>,
buffer_tracker: BufferTracker,
texture_tracker: TextureTracker,
}
#[repr(C)]

View File

@ -1,5 +1,6 @@
use conv;
use registry::{HUB, Items, Registry};
use track::{Tracker};
use track::{BufferTracker, TextureTracker, Tracktion, TrackPermit};
use {
Stored,
CommandBufferId, RenderPassId,
@ -8,13 +9,12 @@ use {
use hal;
use hal::command::RawCommandBuffer;
use std::iter;
pub struct RenderPass<B: hal::Backend> {
raw: B::CommandBuffer,
cmb_id: Stored<CommandBufferId>,
tracker: Tracker,
buffer_tracker: BufferTracker,
texture_tracker: TextureTracker,
}
impl<B: hal::Backend> RenderPass<B> {
@ -25,7 +25,8 @@ impl<B: hal::Backend> RenderPass<B> {
RenderPass {
raw,
cmb_id: Stored(cmb_id),
tracker: Tracker::default(),
buffer_tracker: BufferTracker::new(),
texture_tracker: TextureTracker::new(),
}
}
}
@ -39,11 +40,34 @@ pub extern "C" fn wgpu_render_pass_end_pass(
.take(pass_id);
pass.raw.end_render_pass();
HUB.command_buffers
.lock()
.get_mut(pass.cmb_id.0)
.raw
.push(pass.raw);
let buffer_guard = HUB.buffers.lock();
//let texture_guard = HUB.textures.lock();
let mut cmb_guard = HUB.command_buffers.lock();
let cmb = cmb_guard.get_mut(pass.cmb_id.0);
let cmb_buffers = &mut cmb.buffer_tracker;
let buffer_barriers = pass.buffer_tracker
.finish()
.into_iter()
.flat_map(|(id, new)| {
match cmb_buffers.track(id.0, new, TrackPermit::REPLACE) {
Ok(Tracktion::Init) => None,
Ok(Tracktion::Keep) => None,
Ok(Tracktion::Replace { old }) => Some(hal::memory::Barrier::Buffer {
states: conv::map_buffer_state(old) .. conv::map_buffer_state(new),
target: &buffer_guard.get(id.0).raw,
}),
Ok(Tracktion::Extend { .. }) |
Err(_) => panic!("Unable to do the resource transition for a pass"),
}
});
pass.raw.pipeline_barrier(
hal::pso::PipelineStage::TOP_OF_PIPE .. hal::pso::PipelineStage::BOTTOM_OF_PIPE,
hal::memory::Dependencies::empty(),
buffer_barriers,
);
cmb.raw.push(pass.raw);
pass.cmb_id.0
}

View File

@ -2,7 +2,8 @@ use hal;
use {Extent3d, binding_model, pipeline, resource};
pub(crate) fn map_buffer_usage(
pub fn map_buffer_usage(
usage: resource::BufferUsageFlags,
) -> (hal::buffer::Usage, hal::memory::Properties) {
use hal::buffer::Usage as U;
@ -40,7 +41,7 @@ pub(crate) fn map_buffer_usage(
(hal_usage, hal_memory)
}
pub(crate) fn map_binding_type(
pub fn map_binding_type(
binding_ty: binding_model::BindingType,
) -> hal::pso::DescriptorType {
use binding_model::BindingType::*;
@ -53,7 +54,7 @@ pub(crate) fn map_binding_type(
}
}
pub(crate) fn map_shader_stage_flags(
pub fn map_shader_stage_flags(
shader_stage_flags: binding_model::ShaderStageFlags,
) -> hal::pso::ShaderStageFlags {
use binding_model::{
@ -73,7 +74,7 @@ pub(crate) fn map_shader_stage_flags(
value
}
pub(crate) fn map_primitive_topology(
pub fn map_primitive_topology(
primitive_topology: pipeline::PrimitiveTopology,
) -> hal::Primitive {
use hal::Primitive as H;
@ -87,7 +88,7 @@ pub(crate) fn map_primitive_topology(
}
}
pub(crate) fn map_blend_state_descriptor(
pub fn map_blend_state_descriptor(
desc: &pipeline::BlendStateDescriptor,
) -> hal::pso::ColorBlendDesc {
let color_mask = desc.write_mask;
@ -164,7 +165,7 @@ fn map_blend_factor(blend_factor: pipeline::BlendFactor) -> hal::pso::Factor {
}
}
pub(crate) fn map_depth_stencil_state(
pub fn map_depth_stencil_state(
desc: &pipeline::DepthStencilStateDescriptor,
) -> hal::pso::DepthStencilDesc {
hal::pso::DepthStencilDesc {
@ -228,7 +229,7 @@ fn map_stencil_operation(stencil_operation: pipeline::StencilOperation) -> hal::
}
}
pub(crate) fn map_texture_format(texture_format: resource::TextureFormat) -> hal::format::Format {
pub fn map_texture_format(texture_format: resource::TextureFormat) -> hal::format::Format {
use hal::format::Format as H;
use resource::TextureFormat::*;
match texture_format {
@ -244,7 +245,7 @@ fn checked_u32_as_u16(value: u32) -> u16 {
value as u16
}
pub(crate) fn map_texture_dimension_size(
pub fn map_texture_dimension_size(
dimension: resource::TextureDimension, size: Extent3d
) -> hal::image::Kind {
use hal::image::Kind as H;
@ -260,7 +261,7 @@ pub(crate) fn map_texture_dimension_size(
}
}
pub(crate) fn map_texture_usage_flags(
pub fn map_texture_usage(
flags: resource::TextureUsageFlags, format: hal::format::Format
) -> hal::image::Usage {
use hal::image::Usage as U;
@ -290,3 +291,32 @@ pub(crate) fn map_texture_usage_flags(
// TODO: HAL Transient Attachment, HAL Input Attachment
value
}
pub fn map_buffer_state(
usage: resource::BufferUsageFlags,
) -> hal::buffer::State {
use hal::buffer::Access as A;
use resource::BufferUsageFlags as W;
let mut access = A::empty();
if usage.contains(W::TRANSFER_SRC) {
access |= A::TRANSFER_READ;
}
if usage.contains(W::TRANSFER_DST) {
access |= A::TRANSFER_WRITE;
}
if usage.contains(W::INDEX) {
access |= A::INDEX_BUFFER_READ;
}
if usage.contains(W::VERTEX) {
access |= A::VERTEX_BUFFER_READ;
}
if usage.contains(W::UNIFORM) {
access |= A::CONSTANT_BUFFER_READ | A::SHADER_READ;
}
if usage.contains(W::STORAGE) {
access |= A::SHADER_WRITE;
}
access
}

View File

@ -1,8 +1,7 @@
use {back, binding_model, command, conv, pipeline, resource};
use registry::{HUB, Items, Registry};
use track::{Tracker, UsePermit};
use track::{BufferTracker, TextureTracker, TrackPermit};
use {
Stored,
AttachmentStateId, BindGroupLayoutId, BlendStateId, CommandBufferId, DepthStencilStateId,
DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId, TextureId,
};
@ -10,9 +9,10 @@ use {
use hal::command::RawCommandBuffer;
use hal::queue::RawCommandQueue;
use hal::{self, Device as _Device};
use rendy_memory::{allocator, Config, Heaps};
use std::{ffi, slice};
use rendy_memory::{allocator, Config, Heaps};
use std::sync::Mutex;
pub struct Device<B: hal::Backend> {
@ -20,7 +20,8 @@ pub struct Device<B: hal::Backend> {
queue_group: hal::QueueGroup<B, hal::General>,
mem_allocator: Heaps<B::Memory>,
pub(crate) com_allocator: command::CommandAllocator<B>,
tracker: Tracker,
buffer_tracker: Mutex<BufferTracker>,
texture_tracker: Mutex<TextureTracker>,
mem_props: hal::MemoryProperties,
}
@ -56,7 +57,8 @@ impl<B: hal::Backend> Device<B> {
mem_allocator,
com_allocator: command::CommandAllocator::new(queue_group.family()),
queue_group,
tracker: Tracker::default(),
buffer_tracker: Mutex::new(BufferTracker::new()),
texture_tracker: Mutex::new(TextureTracker::new()),
mem_props,
}
}
@ -73,7 +75,7 @@ pub extern "C" fn wgpu_device_create_texture(
) -> TextureId {
let kind = conv::map_texture_dimension_size(desc.dimension, desc.size);
let format = conv::map_texture_format(desc.format);
let usage = conv::map_texture_usage_flags(desc.usage, format);
let usage = conv::map_texture_usage(desc.usage, format);
let device_guard = HUB.devices.lock();
let device = &device_guard.get(device_id);
let image_unbound = device
@ -111,7 +113,10 @@ pub extern "C" fn wgpu_device_create_texture(
.register(resource::Texture {
raw: bound_image,
});
device.tracker.use_texture(Stored(id), resource::TextureUsageFlags::empty(), UsePermit::empty())
device.texture_tracker
.lock()
.unwrap()
.track(id, resource::TextureUsageFlags::empty(), TrackPermit::empty())
.expect("Resource somehow is already registered");
id
@ -224,7 +229,7 @@ pub extern "C" fn wgpu_device_create_command_buffer(
device_id: DeviceId,
_desc: &command::CommandBufferDescriptor,
) -> CommandBufferId {
let mut device_guard = HUB.devices.lock();
let device_guard = HUB.devices.lock();
let device = device_guard.get(device_id);
let mut cmd_buf = device.com_allocator.allocate(device_id, &device.raw);

View File

@ -96,6 +96,7 @@ pub type DeviceId = Id;
type DeviceHandle = Device<B>;
pub type QueueId = Id;
pub type BufferId = Id;
type BufferHandle = Buffer<B>;
// Resource
pub type TextureViewId = Id;

View File

@ -13,7 +13,7 @@ use {
BlendStateHandle, CommandBufferHandle, DepthStencilStateHandle, DeviceHandle, InstanceHandle,
RenderPassHandle, ComputePassHandle,
PipelineLayoutHandle, RenderPipelineHandle, ComputePipelineHandle, ShaderModuleHandle,
TextureHandle,
BufferHandle, TextureHandle,
};
@ -48,6 +48,7 @@ pub struct Hub {
pub(crate) compute_pipelines: ConcreteRegistry<ComputePipelineHandle>,
pub(crate) render_passes: ConcreteRegistry<RenderPassHandle>,
pub(crate) compute_passes: ConcreteRegistry<ComputePassHandle>,
pub(crate) buffers: ConcreteRegistry<BufferHandle>,
pub(crate) textures: ConcreteRegistry<TextureHandle>,
}

View File

@ -25,9 +25,9 @@ pub struct BufferDescriptor {
pub usage: BufferUsageFlags,
}
pub struct Buffer<B: hal::Backend> {
pub(crate) raw: B::UnboundBuffer,
pub(crate) memory_properties: hal::memory::Properties,
pub(crate) struct Buffer<B: hal::Backend> {
pub raw: B::UnboundBuffer,
pub memory_properties: hal::memory::Properties,
// TODO: mapping, unmap()
}
@ -75,8 +75,8 @@ pub struct TextureDescriptor {
pub usage: TextureUsageFlags,
}
pub struct Texture<B: hal::Backend> {
pub(crate) raw: B::Image,
pub(crate) struct Texture<B: hal::Backend> {
pub raw: B::Image,
}
#[repr(C)]

View File

@ -4,11 +4,10 @@ use resource::{BufferUsageFlags, TextureUsageFlags};
use std::collections::hash_map::{Entry, HashMap};
use std::hash::Hash;
use std::ops::BitOr;
use std::sync::Mutex;
#[derive(Clone, Debug, PartialEq)]
pub enum UseAction<T> {
pub enum Tracktion<T> {
Init,
Keep,
Extend { old: T },
@ -16,14 +15,14 @@ pub enum UseAction<T> {
}
bitflags! {
pub struct UsePermit: u32 {
pub struct TrackPermit: u32 {
const EXTEND = 1;
const REPLACE = 2;
}
}
trait GenericUsage {
pub trait GenericUsage {
fn is_exclusive(&self) -> bool;
}
impl GenericUsage for BufferUsageFlags {
@ -37,33 +36,37 @@ impl GenericUsage for TextureUsageFlags {
}
}
#[derive(Default)]
pub struct Tracker {
buffers: Mutex<HashMap<Stored<BufferId>, BufferUsageFlags>>,
textures: Mutex<HashMap<Stored<TextureId>, TextureUsageFlags>>,
}
impl Tracker {
fn use_impl<I, U>(
map: &mut HashMap<I, U>, id: I, usage: U, permit: UsePermit
) -> Result<UseAction<U>, U>
where
I: Hash + Eq,
U: Copy + GenericUsage + BitOr<Output = U> + PartialEq,
{
match map.entry(id) {
pub struct Tracker<I, U> {
map: HashMap<Stored<I>, U>,
}
pub type BufferTracker = Tracker<BufferId, BufferUsageFlags>;
pub type TextureTracker = Tracker<TextureId, TextureUsageFlags>;
impl<
I: Hash + Eq,
U: Copy + GenericUsage + BitOr<Output = U> + PartialEq,
> Tracker<I, U> {
pub fn new() -> Self {
Tracker {
map: HashMap::new(),
}
}
pub fn track(&mut self, id: I, usage: U, permit: TrackPermit) -> Result<Tracktion<U>, U> {
match self.map.entry(Stored(id)) {
Entry::Vacant(e) => {
e.insert(usage);
Ok(UseAction::Init)
Ok(Tracktion::Init)
}
Entry::Occupied(mut e) => {
let old = *e.get();
if usage == old {
Ok(UseAction::Keep)
} else if permit.contains(UsePermit::EXTEND) && !(old | usage).is_exclusive() {
Ok(UseAction::Extend { old: e.insert(old | usage) })
} else if permit.contains(UsePermit::REPLACE) {
Ok(UseAction::Replace { old: e.insert(usage) })
Ok(Tracktion::Keep)
} else if permit.contains(TrackPermit::EXTEND) && !(old | usage).is_exclusive() {
Ok(Tracktion::Extend { old: e.insert(old | usage) })
} else if permit.contains(TrackPermit::REPLACE) {
Ok(Tracktion::Replace { old: e.insert(usage) })
} else {
Err(old)
}
@ -71,15 +74,7 @@ impl Tracker {
}
}
pub(crate) fn use_buffer(
&self, id: Stored<BufferId>, usage: BufferUsageFlags, permit: UsePermit,
) -> Result<UseAction<BufferUsageFlags>, BufferUsageFlags> {
Self::use_impl(&mut *self.buffers.lock().unwrap(), id, usage, permit)
}
pub(crate) fn use_texture(
&self, id: Stored<TextureId>, usage: TextureUsageFlags, permit: UsePermit,
) -> Result<UseAction<TextureUsageFlags>, TextureUsageFlags> {
Self::use_impl(&mut *self.textures.lock().unwrap(), id, usage, permit)
pub(crate) fn finish(self) -> HashMap<Stored<I>, U> {
self.map
}
}