Prenentation logic and bits of frame synchronization

This commit is contained in:
Dzmitry Malyshau 2019-01-14 14:01:23 -05:00
parent 630e86f120
commit b67a0bee0d
6 changed files with 212 additions and 91 deletions

View File

@ -99,6 +99,7 @@ impl<B: hal::Backend> CommandAllocator<B> {
life_guard: LifeGuard::new(),
buffer_tracker: Tracker::new(),
texture_tracker: Tracker::new(),
swap_chain_links: Vec::new(),
}
}

View File

@ -11,6 +11,7 @@ use hal::Device;
use crate::device::{FramebufferKey, RenderPassKey};
use crate::registry::{Items, HUB};
use crate::swap_chain::SwapChainLink;
use crate::track::{BufferTracker, TextureTracker};
use crate::{conv, resource};
use crate::{
@ -87,6 +88,7 @@ pub struct CommandBuffer<B: hal::Backend> {
life_guard: LifeGuard,
pub(crate) buffer_tracker: BufferTracker,
pub(crate) texture_tracker: TextureTracker,
swap_chain_links: Vec<SwapChainLink>,
}
impl CommandBuffer<B> {
@ -162,6 +164,7 @@ pub extern "C" fn wgpu_command_buffer_begin_render_pass(
let rp_key = {
let tracker = &mut cmb.texture_tracker;
//let swap_chain_links = &mut cmb.swap_chain_links;
let depth_stencil_key = match desc.depth_stencil_attachment {
Some(ref at) => {

View File

@ -14,7 +14,7 @@ use hal::command::RawCommandBuffer;
use hal::queue::RawCommandQueue;
use hal::{self, Device as _Device, Surface as _Surface};
//use rendy_memory::{allocator, Config, Heaps};
use parking_lot::{Mutex, RwLock};
use parking_lot::{Mutex};
use std::{ffi, slice};
use std::collections::hash_map::{Entry, HashMap};
@ -134,12 +134,12 @@ impl<B: hal::Backend> DestroyedResources<B> {
pub struct Device<B: hal::Backend> {
pub(crate) raw: B::Device,
adapter_id: WeaklyStored<AdapterId>,
queue_group: hal::QueueGroup<B, hal::General>,
pub(crate) queue_group: hal::QueueGroup<B, hal::General>,
//mem_allocator: Heaps<B::Memory>,
pub(crate) com_allocator: command::CommandAllocator<B>,
life_guard: LifeGuard,
buffer_tracker: Mutex<BufferTracker>,
texture_tracker: Mutex<TextureTracker>,
pub(crate) texture_tracker: Mutex<TextureTracker>,
mem_props: hal::MemoryProperties,
pub(crate) render_passes: Mutex<HashMap<RenderPassKey, B::RenderPass>>,
pub(crate) framebuffers: Mutex<HashMap<FramebufferKey, B::Framebuffer>>,
@ -267,7 +267,7 @@ pub extern "C" fn wgpu_device_create_texture(
kind,
format: desc.format,
full_range,
swap_chain_link: RwLock::new(None),
swap_chain_link: None,
life_guard,
});
let query = device.texture_tracker
@ -301,26 +301,27 @@ pub extern "C" fn wgpu_texture_create_texture_view(
hal::format::Swizzle::NO,
hal::image::SubresourceRange {
aspects: conv::map_texture_aspect_flags(desc.aspect),
levels: desc.base_mip_level as u8
..(desc.base_mip_level + desc.level_count) as u8,
layers: desc.base_array_layer as u16
..(desc.base_array_layer + desc.array_count) as u16,
levels: desc.base_mip_level as u8 .. (desc.base_mip_level + desc.level_count) as u8,
layers: desc.base_array_layer as u16 .. (desc.base_array_layer + desc.array_count) as u16,
},
)
}
.unwrap();
.unwrap()
};
HUB.texture_views.write().register(resource::TextureView {
raw,
texture_id: Stored {
value: texture_id,
ref_count: texture.life_guard.ref_count.clone(),
},
format: texture.format,
extent: texture.kind.extent(),
samples: texture.kind.num_samples(),
life_guard: LifeGuard::new(),
})
HUB.texture_views
.write()
.register(resource::TextureView {
raw,
texture_id: Stored {
value: texture_id,
ref_count: texture.life_guard.ref_count.clone(),
},
format: texture.format,
extent: texture.kind.extent(),
samples: texture.kind.num_samples(),
is_owned_by_swap_chain: false,
life_guard: LifeGuard::new(),
})
}
#[no_mangle]
@ -334,7 +335,7 @@ pub extern "C" fn wgpu_texture_create_default_texture_view(texture_id: TextureId
hal::image::Kind::D3(..) => hal::image::ViewKind::D3,
};
let raw = unsafe {
let raw = unsafe{
HUB.devices
.read()
.get(texture.device_id.value)
@ -346,20 +347,23 @@ pub extern "C" fn wgpu_texture_create_default_texture_view(texture_id: TextureId
hal::format::Swizzle::NO,
texture.full_range.clone(),
)
}
.unwrap();
.unwrap()
};
HUB.texture_views.write().register(resource::TextureView {
raw,
texture_id: Stored {
value: texture_id,
ref_count: texture.life_guard.ref_count.clone(),
},
format: texture.format,
extent: texture.kind.extent(),
samples: texture.kind.num_samples(),
life_guard: LifeGuard::new(),
})
HUB.texture_views
.write()
.register(resource::TextureView {
raw,
texture_id: Stored {
value: texture_id,
ref_count: texture.life_guard.ref_count.clone(),
},
format: texture.format,
extent: texture.kind.extent(),
samples: texture.kind.num_samples(),
is_owned_by_swap_chain: false,
life_guard: LifeGuard::new(),
})
}
#[no_mangle]
@ -849,13 +853,17 @@ pub extern "C" fn wgpu_device_create_swap_chain(
let mut surface_guard = HUB.surfaces.write();
let surface = surface_guard.get_mut(surface_id);
let mut texture_guard = HUB.textures.write();
let mut texture_view_guard = HUB.texture_views.write();
let mut swap_chain_guard = HUB.swap_chains.write();
let (caps, formats, _present_modes, _composite_alphas) = surface.raw.compatibility(physical_device);
let num_frames = caps.image_count.start; //TODO: configure?
let frame_format = conv::map_texture_format(desc.format);
let config = hal::SwapchainConfig::new(
desc.width,
desc.height,
conv::map_texture_format(desc.format),
caps.image_count.start, //TODO: configure?
frame_format,
num_frames, //TODO: configure?
);
let usage = conv::map_texture_usage(desc.usage, hal::format::Aspects::COLOR);
@ -874,51 +882,94 @@ pub extern "C" fn wgpu_device_create_swap_chain(
)
.unwrap()
};
let frames = match backbuffer {
hal::Backbuffer::Images(images) => images
.into_iter()
.map(|image| {
let texture = resource::Texture {
raw: image,
device_id: Stored {
value: device_id,
ref_count: device.life_guard.ref_count.clone(),
},
kind: hal::image::Kind::D2(desc.width, desc.height, 1, 1),
format: desc.format,
full_range: hal::image::SubresourceRange {
aspects: hal::format::Aspects::COLOR,
levels: 0 .. 1,
layers: 0 .. 1,
},
swap_chain_link: RwLock::new(None),
life_guard: LifeGuard::new(),
};
swap_chain::Frame {
texture: Stored {
ref_count: texture.life_guard.ref_count.clone(),
value: texture_guard.register(texture),
},
fence: device.raw.create_fence(true).unwrap(),
sem_available: device.raw.create_semaphore().unwrap(),
sem_present: device.raw.create_semaphore().unwrap(),
}
})
.collect(),
hal::Backbuffer::Framebuffer(_) => panic!("Deprecated API detected!"),
let command_pool = unsafe {
device.raw
.create_command_pool_typed(
&device.queue_group,
hal::pool::CommandPoolCreateFlags::RESET_INDIVIDUAL,
)
.unwrap()
};
HUB.swap_chains
.write()
let swap_chain_id = swap_chain_guard
.register(swap_chain::SwapChain {
raw,
device_id: Stored {
value: device_id,
ref_count: device.life_guard.ref_count.clone(),
},
frames,
frames: Vec::with_capacity(num_frames as usize),
acquired: Vec::with_capacity(num_frames as usize),
sem_available: device.raw.create_semaphore().unwrap(),
command_pool,
epoch: 1,
})
});
let swap_chain = swap_chain_guard.get_mut(swap_chain_id);
let images = match backbuffer {
hal::Backbuffer::Images(images) => images,
hal::Backbuffer::Framebuffer(_) => panic!("Deprecated API detected!"),
};
for (i, image) in images.into_iter().enumerate() {
let kind = hal::image::Kind::D2(desc.width, desc.height, 1, 1);
let full_range = hal::image::SubresourceRange {
aspects: hal::format::Aspects::COLOR,
levels: 0 .. 1,
layers: 0 .. 1,
};
let view_raw = unsafe {
device.raw
.create_image_view(
&image,
hal::image::ViewKind::D2,
frame_format,
hal::format::Swizzle::NO,
full_range.clone(),
)
.unwrap()
};
let texture = resource::Texture {
raw: image,
device_id: Stored {
value: device_id,
ref_count: device.life_guard.ref_count.clone(),
},
kind,
format: desc.format,
full_range,
swap_chain_link: Some(swap_chain::SwapChainLink {
swap_chain_id: WeaklyStored(swap_chain_id), //TODO: strongly
epoch: Mutex::new(0),
image_index: i as hal::SwapImageIndex,
}),
life_guard: LifeGuard::new(),
};
let texture_id = Stored {
ref_count: texture.life_guard.ref_count.clone(),
value: texture_guard.register(texture),
};
let view = resource::TextureView {
raw: view_raw,
texture_id: texture_id.clone(),
format: desc.format,
extent: kind.extent(),
samples: kind.num_samples(),
is_owned_by_swap_chain: true,
life_guard: LifeGuard::new(),
};
swap_chain.frames.push(swap_chain::Frame {
texture_id,
view_id: Stored {
ref_count: view.life_guard.ref_count.clone(),
value: texture_view_guard.register(view),
},
fence: device.raw.create_fence(true).unwrap(),
sem_available: device.raw.create_semaphore().unwrap(),
sem_present: device.raw.create_semaphore().unwrap(),
comb: swap_chain.command_pool.acquire_command_buffer(),
});
}
swap_chain_id
}

View File

@ -90,7 +90,7 @@ impl LifeGuard {
}
}
#[derive(Debug)]
#[derive(Clone, Debug)]
struct Stored<T> {
value: T,
ref_count: RefCount,

View File

@ -1,5 +1,4 @@
use bitflags::bitflags;
use parking_lot::RwLock;
use hal;
@ -86,7 +85,7 @@ pub(crate) struct Texture<B: hal::Backend> {
pub kind: hal::image::Kind,
pub format: TextureFormat,
pub full_range: hal::image::SubresourceRange,
pub swap_chain_link: RwLock<Option<SwapChainLink>>,
pub swap_chain_link: Option<SwapChainLink>,
pub life_guard: LifeGuard,
}
@ -127,6 +126,7 @@ pub(crate) struct TextureView<B: hal::Backend> {
pub format: TextureFormat,
pub extent: hal::image::Extent,
pub samples: hal::image::NumSamples,
pub is_owned_by_swap_chain: bool,
pub life_guard: LifeGuard,
}

View File

@ -1,21 +1,24 @@
use crate::{Stored, WeaklyStored,
DeviceId, SwapChainId, TextureId,
DeviceId, SwapChainId, TextureId, TextureViewId,
};
use crate::{conv, resource};
use crate::registry::{HUB, Items};
use crate::resource;
use crate::track::{Tracktion, TrackPermit};
use hal;
use hal::{Device as _Device, Swapchain as _Swapchain};
use std::mem;
use parking_lot::Mutex;
use std::{iter, mem};
pub type Epoch = u16;
pub(crate) struct SwapChainLink {
swap_chain_id: WeaklyStored<SwapChainId>, //TODO: strongly
epoch: Epoch,
image_index: hal::SwapImageIndex,
pub swap_chain_id: WeaklyStored<SwapChainId>, //TODO: strongly
pub epoch: Mutex<Epoch>,
pub image_index: hal::SwapImageIndex,
}
pub(crate) struct Surface<B: hal::Backend> {
@ -23,17 +26,21 @@ pub(crate) struct Surface<B: hal::Backend> {
}
pub(crate) struct Frame<B: hal::Backend> {
pub texture: Stored<TextureId>,
pub texture_id: Stored<TextureId>,
pub view_id: Stored<TextureViewId>,
pub fence: B::Fence,
pub sem_available: B::Semaphore,
pub sem_present: B::Semaphore,
pub comb: hal::command::CommandBuffer<B, hal::General, hal::command::MultiShot>,
}
pub(crate) struct SwapChain<B: hal::Backend> {
pub raw: B::Swapchain,
pub device_id: Stored<DeviceId>,
pub frames: Vec<Frame<B>>,
pub acquired: Vec<hal::SwapImageIndex>,
pub sem_available: B::Semaphore,
pub command_pool: hal::CommandPool<B, hal::General>,
pub epoch: Epoch,
}
@ -59,6 +66,7 @@ pub extern "C" fn wgpu_swap_chain_get_next_texture(
swap_chain.raw.acquire_image(!0, sync).unwrap()
};
swap_chain.acquired.push(image_index);
let frame = &mut swap_chain.frames[image_index as usize];
unsafe {
device.raw.wait_for_fence(&frame.fence, !0).unwrap();
@ -67,12 +75,70 @@ pub extern "C" fn wgpu_swap_chain_get_next_texture(
mem::swap(&mut frame.sem_available, &mut swap_chain.sem_available);
let texture_guard = HUB.textures.read();
let texture = texture_guard.get(frame.texture.value);
*texture.swap_chain_link.write() = Some(SwapChainLink {
swap_chain_id: WeaklyStored(swap_chain_id),
epoch: swap_chain.epoch,
image_index,
});
let texture = texture_guard.get(frame.texture_id.value);
match texture.swap_chain_link {
Some(ref link) => *link.epoch.lock() = swap_chain.epoch,
None => unreachable!(),
}
frame.texture.value
frame.texture_id.value
}
#[no_mangle]
pub extern "C" fn wgpu_swap_chain_present(
swap_chain_id: SwapChainId,
) {
let mut swap_chain_guard = HUB.swap_chains.write();
let swap_chain = swap_chain_guard.get_mut(swap_chain_id);
let mut device_guard = HUB.devices.write();
let device = device_guard.get_mut(swap_chain.device_id.value);
let image_index = swap_chain.acquired.remove(0);
let frame = &mut swap_chain.frames[image_index as usize];
let texture_guard = HUB.textures.read();
let texture = texture_guard.get(frame.texture_id.value);
match texture.swap_chain_link {
Some(ref link) => *link.epoch.lock() += 1,
None => unreachable!(),
}
//trace!("transit {:?} to present", frame.texture_id.value);
let tracktion = device.texture_tracker
.lock()
.transit(
frame.texture_id.value,
&texture.life_guard.ref_count,
resource::TextureUsageFlags::PRESENT,
TrackPermit::EXTEND,
)
.unwrap();
let barrier = match tracktion {
Tracktion::Keep => None,
Tracktion::Replace { old } => Some(hal::memory::Barrier::Image {
states: conv::map_texture_state(old, hal::format::Aspects::COLOR) ..
(hal::image::Access::empty(), hal::image::Layout::Present),
target: &texture.raw,
families: None,
range: texture.full_range.clone(),
}),
Tracktion::Init |
Tracktion::Extend {..} => unreachable!(),
};
unsafe {
frame.comb.begin(false);
frame.comb.pipeline_barrier(
hal::pso::PipelineStage::TOP_OF_PIPE .. hal::pso::PipelineStage::BOTTOM_OF_PIPE,
hal::memory::Dependencies::empty(),
barrier,
);
frame.comb.finish();
// now prepare the GPU submission
device.raw.reset_fence(&frame.fence);
device.queue_group.queues[0]
.submit_nosemaphores(iter::once(&frame.comb), Some(&frame.fence));
}
}