55: All the transfers r=grovesNL a=kvark



Co-authored-by: Dzmitry Malyshau <dmalyshau@mozilla.com>
This commit is contained in:
bors[bot] 2019-02-07 13:20:29 +00:00
commit c7cd741543
7 changed files with 436 additions and 124 deletions

View File

@ -558,11 +558,28 @@ WGPUComputePassId wgpu_command_buffer_begin_compute_pass(WGPUCommandBufferId com
WGPURenderPassId wgpu_command_buffer_begin_render_pass(WGPUCommandBufferId command_buffer_id,
WGPURenderPassDescriptor desc);
void wgpu_command_buffer_copy_buffer_to_buffer(WGPUCommandBufferId command_buffer_id,
WGPUBufferId src,
uint32_t src_offset,
WGPUBufferId dst,
uint32_t dst_offset,
uint32_t size);
void wgpu_command_buffer_copy_buffer_to_texture(WGPUCommandBufferId command_buffer_id,
const WGPUBufferCopyView *source,
const WGPUTextureCopyView *destination,
WGPUExtent3d copy_size);
void wgpu_command_buffer_copy_texture_to_buffer(WGPUCommandBufferId command_buffer_id,
const WGPUTextureCopyView *source,
const WGPUBufferCopyView *destination,
WGPUExtent3d copy_size);
void wgpu_command_buffer_copy_texture_to_texture(WGPUCommandBufferId command_buffer_id,
const WGPUTextureCopyView *source,
const WGPUTextureCopyView *destination,
WGPUExtent3d copy_size);
void wgpu_compute_pass_dispatch(WGPUComputePassId pass_id, uint32_t x, uint32_t y, uint32_t z);
WGPUCommandBufferId wgpu_compute_pass_end_pass(WGPUComputePassId pass_id);

View File

@ -2,10 +2,12 @@ mod allocator;
mod bind;
mod compute;
mod render;
mod transfer;
pub(crate) use self::allocator::CommandAllocator;
pub use self::compute::*;
pub use self::render::*;
pub use self::transfer::*;
use crate::device::{
FramebufferKey, RenderPassKey,
@ -13,13 +15,12 @@ use crate::device::{
};
use crate::registry::{Items, HUB};
use crate::swap_chain::{SwapChainLink, SwapImageEpoch};
use crate::track::{BufferTracker, TextureTracker, TrackPermit, Tracktion};
use crate::track::{BufferTracker, TextureTracker};
use crate::{conv, resource};
use crate::{
BufferId, CommandBufferId, ComputePassId, DeviceId,
RenderPassId, TextureId, TextureViewId,
BufferUsageFlags, TextureUsageFlags, Color,
Extent3d, Origin3d,
LifeGuard, Stored, WeaklyStored,
B,
};
@ -34,8 +35,6 @@ use std::{iter, slice};
use std::thread::ThreadId;
const BITS_PER_BYTE: u32 = 8;
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum LoadOp {
@ -75,22 +74,6 @@ pub struct RenderPassDescriptor {
pub depth_stencil_attachment: *const RenderPassDepthStencilAttachmentDescriptor<TextureViewId>,
}
#[repr(C)]
pub struct BufferCopyView {
pub buffer: BufferId,
pub offset: u32,
pub row_pitch: u32,
pub image_height: u32,
}
#[repr(C)]
pub struct TextureCopyView {
pub texture: TextureId,
pub level: u32,
pub slice: u32,
pub origin: Origin3d,
//TODO: pub aspect: TextureAspect,
}
pub struct CommandBuffer<B: hal::Backend> {
pub(crate) raw: Vec<B::CommandBuffer>,
@ -382,97 +365,3 @@ pub extern "C" fn wgpu_command_buffer_begin_compute_pass(
.write()
.register(ComputePass::new(raw, stored))
}
#[no_mangle]
pub extern "C" fn wgpu_command_buffer_copy_buffer_to_texture(
command_buffer_id: CommandBufferId,
source: &BufferCopyView,
destination: &TextureCopyView,
copy_size: Extent3d,
) {
let mut cmb_guard = HUB.command_buffers.write();
let cmb = cmb_guard.get_mut(command_buffer_id);
let buffer_guard = HUB.buffers.read();
let texture_guard = HUB.textures.read();
let (src_buffer, src_tracktion) = cmb.buffer_tracker
.get_with_usage(
&*buffer_guard,
source.buffer,
BufferUsageFlags::TRANSFER_SRC,
TrackPermit::REPLACE,
)
.unwrap();
let src_barrier = match src_tracktion {
Tracktion::Init |
Tracktion::Keep => None,
Tracktion::Extend { .. } => unreachable!(),
Tracktion::Replace { old } => Some(hal::memory::Barrier::Buffer {
states: conv::map_buffer_state(old) .. hal::buffer::Access::TRANSFER_WRITE,
target: &src_buffer.raw,
families: None,
range: None .. None,
}),
};
let (dst_texture, dst_tracktion) = cmb.texture_tracker
.get_with_usage(
&*texture_guard,
destination.texture,
TextureUsageFlags::TRANSFER_DST,
TrackPermit::REPLACE,
)
.unwrap();
let aspects = dst_texture.full_range.aspects;
let dst_texture_state = conv::map_texture_state(TextureUsageFlags::TRANSFER_DST, aspects);
let dst_barrier = match dst_tracktion {
Tracktion::Init |
Tracktion::Keep => None,
Tracktion::Extend { .. } => unreachable!(),
Tracktion::Replace { old } => Some(hal::memory::Barrier::Image {
states: conv::map_texture_state(old, aspects) .. dst_texture_state,
target: &dst_texture.raw,
families: None,
range: dst_texture.full_range.clone(),
}),
};
if let Some(ref link) = dst_texture.swap_chain_link {
cmb.swap_chain_links.push(SwapChainLink {
swap_chain_id: link.swap_chain_id.clone(),
epoch: *link.epoch.lock(),
image_index: link.image_index,
});
}
let bytes_per_texel = conv::map_texture_format(dst_texture.format)
.surface_desc().bits as u32 / BITS_PER_BYTE;
let buffer_width = source.row_pitch / bytes_per_texel;
assert_eq!(source.row_pitch % bytes_per_texel, 0);
let region = hal::command::BufferImageCopy {
buffer_offset: source.offset as hal::buffer::Offset,
buffer_width,
buffer_height: source.image_height,
image_layers: hal::image::SubresourceLayers {
aspects, //TODO
level: destination.level as hal::image::Level,
layers: destination.slice as u16 .. destination.slice as u16 + 1,
},
image_offset: conv::map_origin(destination.origin),
image_extent: conv::map_extent(copy_size),
};
let cmb_raw = cmb.raw.last_mut().unwrap();
unsafe {
cmb_raw.pipeline_barrier(
all_buffer_stages() .. all_image_stages(),
hal::memory::Dependencies::empty(),
src_barrier.into_iter().chain(dst_barrier),
);
cmb_raw.copy_buffer_to_image(
&src_buffer.raw,
&dst_texture.raw,
dst_texture_state.1,
iter::once(region),
);
}
}

View File

@ -1,7 +1,7 @@
use crate::command::bind::Binder;
use crate::resource::BufferUsageFlags;
use crate::registry::{Items, HUB};
use crate::track::{BufferTracker, TextureTracker, TrackPermit};
use crate::track::{BufferTracker, TextureTracker};
use crate::{
CommandBuffer, Stored,
BindGroupId, BufferId, CommandBufferId, RenderPassId, RenderPipelineId,
@ -65,12 +65,11 @@ pub extern "C" fn wgpu_render_pass_set_index_buffer(
let buffer_guard = HUB.buffers.read();
let pass = pass_guard.get_mut(pass_id);
let (buffer, _) = pass.buffer_tracker
.get_with_usage(
let buffer = pass.buffer_tracker
.get_with_extended_usage(
&*buffer_guard,
buffer_id,
BufferUsageFlags::INDEX,
TrackPermit::EXTEND,
)
.unwrap();
@ -104,11 +103,10 @@ pub extern "C" fn wgpu_render_pass_set_vertex_buffers(
let pass = pass_guard.get_mut(pass_id);
for &id in buffers {
pass.buffer_tracker
.get_with_usage(
.get_with_extended_usage(
&*buffer_guard,
id,
BufferUsageFlags::VERTEX,
TrackPermit::EXTEND,
)
.unwrap();
}

View File

@ -0,0 +1,336 @@
use crate::device::{all_buffer_stages, all_image_stages};
use crate::registry::{Items, HUB};
use crate::swap_chain::SwapChainLink;
use crate::conv;
use crate::{
BufferId, CommandBufferId, TextureId,
BufferUsageFlags, TextureUsageFlags,
Extent3d, Origin3d,
};
use hal::command::RawCommandBuffer;
use std::iter;
const BITS_PER_BYTE: u32 = 8;
#[repr(C)]
pub struct BufferCopyView {
pub buffer: BufferId,
pub offset: u32,
pub row_pitch: u32,
pub image_height: u32,
}
#[repr(C)]
pub struct TextureCopyView {
pub texture: TextureId,
pub level: u32,
pub slice: u32,
pub origin: Origin3d,
//TODO: pub aspect: TextureAspect,
}
#[no_mangle]
pub extern "C" fn wgpu_command_buffer_copy_buffer_to_buffer(
command_buffer_id: CommandBufferId,
src: BufferId,
src_offset: u32,
dst: BufferId,
dst_offset: u32,
size: u32,
) {
let mut cmb_guard = HUB.command_buffers.write();
let cmb = cmb_guard.get_mut(command_buffer_id);
let buffer_guard = HUB.buffers.read();
let (src_buffer, src_usage) = cmb.buffer_tracker
.get_with_replaced_usage(
&*buffer_guard,
src,
BufferUsageFlags::TRANSFER_SRC,
)
.unwrap();
let src_barrier = src_usage.map(|old| hal::memory::Barrier::Buffer {
states: conv::map_buffer_state(old) .. hal::buffer::Access::TRANSFER_READ,
target: &src_buffer.raw,
families: None,
range: None .. None,
});
let (dst_buffer, dst_usage) = cmb.buffer_tracker
.get_with_replaced_usage(
&*buffer_guard,
dst,
BufferUsageFlags::TRANSFER_DST,
)
.unwrap();
let dst_barrier = dst_usage.map(|old| hal::memory::Barrier::Buffer {
states: conv::map_buffer_state(old) .. hal::buffer::Access::TRANSFER_WRITE,
target: &dst_buffer.raw,
families: None,
range: None .. None,
});
let region = hal::command::BufferCopy {
src: src_offset as hal::buffer::Offset,
dst: dst_offset as hal::buffer::Offset,
size: size as hal::buffer::Offset,
};
let cmb_raw = cmb.raw.last_mut().unwrap();
unsafe {
cmb_raw.pipeline_barrier(
all_buffer_stages() .. all_buffer_stages(),
hal::memory::Dependencies::empty(),
src_barrier.into_iter().chain(dst_barrier),
);
cmb_raw.copy_buffer(
&src_buffer.raw,
&dst_buffer.raw,
iter::once(region),
);
}
}
#[no_mangle]
pub extern "C" fn wgpu_command_buffer_copy_buffer_to_texture(
command_buffer_id: CommandBufferId,
source: &BufferCopyView,
destination: &TextureCopyView,
copy_size: Extent3d,
) {
let mut cmb_guard = HUB.command_buffers.write();
let cmb = cmb_guard.get_mut(command_buffer_id);
let buffer_guard = HUB.buffers.read();
let texture_guard = HUB.textures.read();
let (src_buffer, src_usage) = cmb.buffer_tracker
.get_with_replaced_usage(
&*buffer_guard,
source.buffer,
BufferUsageFlags::TRANSFER_SRC,
)
.unwrap();
let src_barrier = src_usage.map(|old| hal::memory::Barrier::Buffer {
states: conv::map_buffer_state(old) .. hal::buffer::Access::TRANSFER_READ,
target: &src_buffer.raw,
families: None,
range: None .. None,
});
let (dst_texture, dst_usage) = cmb.texture_tracker
.get_with_replaced_usage(
&*texture_guard,
destination.texture,
TextureUsageFlags::TRANSFER_DST,
)
.unwrap();
let aspects = dst_texture.full_range.aspects;
let dst_texture_state = conv::map_texture_state(TextureUsageFlags::TRANSFER_DST, aspects);
let dst_barrier = dst_usage.map(|old| hal::memory::Barrier::Image {
states: conv::map_texture_state(old, aspects) .. dst_texture_state,
target: &dst_texture.raw,
families: None,
range: dst_texture.full_range.clone(),
});
if let Some(ref link) = dst_texture.swap_chain_link {
cmb.swap_chain_links.push(SwapChainLink {
swap_chain_id: link.swap_chain_id.clone(),
epoch: *link.epoch.lock(),
image_index: link.image_index,
});
}
let bytes_per_texel = conv::map_texture_format(dst_texture.format)
.surface_desc().bits as u32 / BITS_PER_BYTE;
let buffer_width = source.row_pitch / bytes_per_texel;
assert_eq!(source.row_pitch % bytes_per_texel, 0);
let region = hal::command::BufferImageCopy {
buffer_offset: source.offset as hal::buffer::Offset,
buffer_width,
buffer_height: source.image_height,
image_layers: hal::image::SubresourceLayers {
aspects, //TODO
level: destination.level as hal::image::Level,
layers: destination.slice as u16 .. destination.slice as u16 + 1,
},
image_offset: conv::map_origin(destination.origin),
image_extent: conv::map_extent(copy_size),
};
let cmb_raw = cmb.raw.last_mut().unwrap();
let stages = all_buffer_stages() | all_image_stages();
unsafe {
cmb_raw.pipeline_barrier(
stages .. stages,
hal::memory::Dependencies::empty(),
src_barrier.into_iter().chain(dst_barrier),
);
cmb_raw.copy_buffer_to_image(
&src_buffer.raw,
&dst_texture.raw,
dst_texture_state.1,
iter::once(region),
);
}
}
#[no_mangle]
pub extern "C" fn wgpu_command_buffer_copy_texture_to_buffer(
command_buffer_id: CommandBufferId,
source: &TextureCopyView,
destination: &BufferCopyView,
copy_size: Extent3d,
) {
let mut cmb_guard = HUB.command_buffers.write();
let cmb = cmb_guard.get_mut(command_buffer_id);
let buffer_guard = HUB.buffers.read();
let texture_guard = HUB.textures.read();
let (src_texture, src_usage) = cmb.texture_tracker
.get_with_replaced_usage(
&*texture_guard,
source.texture,
TextureUsageFlags::TRANSFER_SRC,
)
.unwrap();
let aspects = src_texture.full_range.aspects;
let src_texture_state = conv::map_texture_state(TextureUsageFlags::TRANSFER_SRC, aspects);
let src_barrier = src_usage.map(|old| hal::memory::Barrier::Image {
states: conv::map_texture_state(old, aspects) .. src_texture_state,
target: &src_texture.raw,
families: None,
range: src_texture.full_range.clone(),
});
assert!(src_texture.swap_chain_link.is_none()); //TODO
let (dst_buffer, dst_usage) = cmb.buffer_tracker
.get_with_replaced_usage(
&*buffer_guard,
destination.buffer,
BufferUsageFlags::TRANSFER_DST,
)
.unwrap();
let dst_barrier = dst_usage.map(|old| hal::memory::Barrier::Buffer {
states: conv::map_buffer_state(old) .. hal::buffer::Access::TRANSFER_WRITE,
target: &dst_buffer.raw,
families: None,
range: None .. None,
});
let bytes_per_texel = conv::map_texture_format(src_texture.format)
.surface_desc().bits as u32 / BITS_PER_BYTE;
let buffer_width = destination.row_pitch / bytes_per_texel;
assert_eq!(destination.row_pitch % bytes_per_texel, 0);
let region = hal::command::BufferImageCopy {
buffer_offset: destination.offset as hal::buffer::Offset,
buffer_width,
buffer_height: destination.image_height,
image_layers: hal::image::SubresourceLayers {
aspects, //TODO
level: source.level as hal::image::Level,
layers: source.slice as u16 .. source.slice as u16 + 1,
},
image_offset: conv::map_origin(source.origin),
image_extent: conv::map_extent(copy_size),
};
let cmb_raw = cmb.raw.last_mut().unwrap();
let stages = all_buffer_stages() | all_image_stages();
unsafe {
cmb_raw.pipeline_barrier(
stages .. stages,
hal::memory::Dependencies::empty(),
src_barrier.into_iter().chain(dst_barrier),
);
cmb_raw.copy_image_to_buffer(
&src_texture.raw,
src_texture_state.1,
&dst_buffer.raw,
iter::once(region),
);
}
}
#[no_mangle]
pub extern "C" fn wgpu_command_buffer_copy_texture_to_texture(
command_buffer_id: CommandBufferId,
source: &TextureCopyView,
destination: &TextureCopyView,
copy_size: Extent3d,
) {
let mut cmb_guard = HUB.command_buffers.write();
let cmb = cmb_guard.get_mut(command_buffer_id);
let texture_guard = HUB.textures.read();
let (src_texture, src_usage) = cmb.texture_tracker
.get_with_replaced_usage(
&*texture_guard,
source.texture,
TextureUsageFlags::TRANSFER_SRC,
)
.unwrap();
let (dst_texture, dst_usage) = cmb.texture_tracker
.get_with_replaced_usage(
&*texture_guard,
destination.texture,
TextureUsageFlags::TRANSFER_DST,
)
.unwrap();
let aspects = src_texture.full_range.aspects & dst_texture.full_range.aspects;
let src_texture_state = conv::map_texture_state(TextureUsageFlags::TRANSFER_SRC, aspects);
let dst_texture_state = conv::map_texture_state(TextureUsageFlags::TRANSFER_DST, aspects);
let src_barrier = src_usage.map(|old| hal::memory::Barrier::Image {
states: conv::map_texture_state(old, aspects) .. src_texture_state,
target: &src_texture.raw,
families: None,
range: src_texture.full_range.clone(),
});
let dst_barrier = dst_usage.map(|old| hal::memory::Barrier::Image {
states: conv::map_texture_state(old, aspects) .. dst_texture_state,
target: &dst_texture.raw,
families: None,
range: dst_texture.full_range.clone(),
});
if let Some(ref link) = dst_texture.swap_chain_link {
cmb.swap_chain_links.push(SwapChainLink {
swap_chain_id: link.swap_chain_id.clone(),
epoch: *link.epoch.lock(),
image_index: link.image_index,
});
}
let region = hal::command::ImageCopy {
src_subresource: hal::image::SubresourceLayers {
aspects,
level: source.level as hal::image::Level,
layers: source.slice as u16 .. source.slice as u16 + 1,
},
src_offset: conv::map_origin(source.origin),
dst_subresource: hal::image::SubresourceLayers {
aspects,
level: destination.level as hal::image::Level,
layers: destination.slice as u16 .. destination.slice as u16 + 1,
},
dst_offset: conv::map_origin(destination.origin),
extent: conv::map_extent(copy_size),
};
let cmb_raw = cmb.raw.last_mut().unwrap();
unsafe {
cmb_raw.pipeline_barrier(
all_image_stages() .. all_image_stages(),
hal::memory::Dependencies::empty(),
src_barrier.into_iter().chain(dst_barrier),
);
cmb_raw.copy_image(
&src_texture.raw,
src_texture_state.1,
&dst_texture.raw,
dst_texture_state.1,
iter::once(region),
);
}
}

View File

@ -668,12 +668,11 @@ pub extern "C" fn wgpu_device_create_bind_group(
for b in bindings {
let descriptor = match b.resource {
binding_model::BindingResource::Buffer(ref bb) => {
let (buffer, _) = used_buffers
.get_with_usage(
let buffer = used_buffers
.get_with_extended_usage(
&*buffer_guard,
bb.buffer,
resource::BufferUsageFlags::UNIFORM,
TrackPermit::EXTEND,
)
.unwrap();
let range = Some(bb.offset as u64) .. Some((bb.offset + bb.size) as u64);

View File

@ -190,7 +190,7 @@ impl<I: Clone + Hash + Eq, U: Copy + GenericUsage + BitOr<Output = U> + PartialE
}
impl<U: Copy + GenericUsage + BitOr<Output = U> + PartialEq> Tracker<Id, U> {
pub(crate) fn get_with_usage<'a, T: 'a + Borrow<RefCount>, V: Items<T>>(
fn get_with_usage<'a, T: 'a + Borrow<RefCount>, V: Items<T>>(
&mut self,
items: &'a V,
id: Id,
@ -201,4 +201,31 @@ impl<U: Copy + GenericUsage + BitOr<Output = U> + PartialEq> Tracker<Id, U> {
self.transit(id, item.borrow(), usage, permit)
.map(|tracktion| (item, tracktion))
}
pub(crate) fn get_with_extended_usage<'a, T: 'a + Borrow<RefCount>, V: Items<T>>(
&mut self,
items: &'a V,
id: Id,
usage: U,
) -> Result<&'a T, U> {
let item = items.get(id);
self.transit(id, item.borrow(), usage, TrackPermit::EXTEND)
.map(|_tracktion| item)
}
pub(crate) fn get_with_replaced_usage<'a, T: 'a + Borrow<RefCount>, V: Items<T>>(
&mut self,
items: &'a V,
id: Id,
usage: U,
) -> Result<(&'a T, Option<U>), U> {
let item = items.get(id);
self.transit(id, item.borrow(), usage, TrackPermit::REPLACE)
.map(|tracktion| (item, match tracktion {
Tracktion::Init |
Tracktion::Keep => None,
Tracktion::Extend { ..} => unreachable!(),
Tracktion::Replace { old } => Some(old),
}))
}
}

View File

@ -496,6 +496,24 @@ impl CommandBuffer {
}
}
pub fn copy_buffer_tobuffer(
&mut self,
source: &Buffer,
source_offset: u32,
destination: &Buffer,
destination_offset: u32,
copy_size: u32,
) {
wgn::wgpu_command_buffer_copy_buffer_to_buffer(
self.id,
source.id,
source_offset,
destination.id,
destination_offset,
copy_size,
);
}
pub fn copy_buffer_to_texture(
&mut self,
source: BufferCopyView,
@ -509,6 +527,34 @@ impl CommandBuffer {
copy_size,
);
}
pub fn copy_texture_to_buffer(
&mut self,
source: TextureCopyView,
destination: BufferCopyView,
copy_size: Extent3d,
) {
wgn::wgpu_command_buffer_copy_texture_to_buffer(
self.id,
&source.into_native(),
&destination.into_native(),
copy_size,
);
}
pub fn copy_texture_to_texture(
&mut self,
source: TextureCopyView,
destination: TextureCopyView,
copy_size: Extent3d,
) {
wgn::wgpu_command_buffer_copy_texture_to_texture(
self.id,
&source.into_native(),
&destination.into_native(),
copy_size,
);
}
}
impl<'a> RenderPass<'a> {