mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Buffer transitions for a render pass
This commit is contained in:
parent
f9cd55ed59
commit
b27650bfcd
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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)]
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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>,
|
||||
}
|
||||
|
||||
|
||||
@ -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)]
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user