mirror of
https://github.com/italicsjenga/portability.git
synced 2024-11-22 23:11:30 +11:00
Support recording swapchain commands from multiple threads
This commit is contained in:
parent
d4fbf6c0a8
commit
bbd2e78d26
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -593,6 +593,7 @@ dependencies = [
|
||||||
"gfx-hal 0.6.0 (git+https://github.com/gfx-rs/gfx)",
|
"gfx-hal 0.6.0 (git+https://github.com/gfx-rs/gfx)",
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"renderdoc 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"renderdoc 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"typed-arena 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"typed-arena 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
|
@ -23,6 +23,7 @@ copyless = "0.1.1"
|
||||||
env_logger = { version = "0.7", optional = true }
|
env_logger = { version = "0.7", optional = true }
|
||||||
lazy_static = "1"
|
lazy_static = "1"
|
||||||
log = { version = "0.4", features = ["release_max_level_error"] }
|
log = { version = "0.4", features = ["release_max_level_error"] }
|
||||||
|
parking_lot = "0.11"
|
||||||
renderdoc = { version = "0.3", optional = true }
|
renderdoc = { version = "0.3", optional = true }
|
||||||
typed-arena = "2"
|
typed-arena = "2"
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
use hal::{
|
use hal::{
|
||||||
adapter::PhysicalDevice,
|
adapter::PhysicalDevice,
|
||||||
buffer::IndexBufferView,
|
buffer::IndexBufferView,
|
||||||
|
@ -10,6 +12,9 @@ use hal::{
|
||||||
{command as com, memory, pass, pso, queue}, {Features, Instance},
|
{command as com, memory, pass, pso, queue}, {Features, Instance},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
use typed_arena::Arena;
|
||||||
|
|
||||||
#[cfg(feature = "gfx-backend-metal")]
|
#[cfg(feature = "gfx-backend-metal")]
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -19,9 +24,6 @@ use std::{
|
||||||
os::raw::{c_int, c_void},
|
os::raw::{c_int, c_void},
|
||||||
ptr, str,
|
ptr, str,
|
||||||
};
|
};
|
||||||
use typed_arena::Arena;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
const VERSION: (u32, u32, u32) = (1, 0, 66);
|
const VERSION: (u32, u32, u32) = (1, 0, 66);
|
||||||
const DRIVER_VERSION: u32 = 1;
|
const DRIVER_VERSION: u32 = 1;
|
||||||
|
@ -3292,16 +3294,20 @@ pub unsafe extern "C" fn gfxBeginCommandBuffer(
|
||||||
pBeginInfo: *const VkCommandBufferBeginInfo,
|
pBeginInfo: *const VkCommandBufferBeginInfo,
|
||||||
) -> VkResult {
|
) -> VkResult {
|
||||||
let info = &*pBeginInfo;
|
let info = &*pBeginInfo;
|
||||||
|
let fb_resolve;
|
||||||
let inheritance = match info.pInheritanceInfo.as_ref() {
|
let inheritance = match info.pInheritanceInfo.as_ref() {
|
||||||
Some(ii) => com::CommandBufferInheritanceInfo {
|
Some(ii) => com::CommandBufferInheritanceInfo {
|
||||||
subpass: ii.renderPass.as_ref().map(|rp| pass::Subpass {
|
subpass: ii.renderPass.as_ref().map(|rp| pass::Subpass {
|
||||||
main_pass: &rp.raw,
|
main_pass: &rp.raw,
|
||||||
index: ii.subpass as _,
|
index: ii.subpass as _,
|
||||||
}),
|
}),
|
||||||
framebuffer: ii
|
framebuffer: match ii.framebuffer.as_ref() {
|
||||||
.framebuffer
|
Some(fbo) => {
|
||||||
.as_ref()
|
fb_resolve = fbo.resolve(ii.renderPass);
|
||||||
.map(|fbo| fbo.resolve(ii.renderPass)),
|
Some(&*fb_resolve)
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
},
|
||||||
occlusion_query_enable: ii.occlusionQueryEnable != VK_FALSE,
|
occlusion_query_enable: ii.occlusionQueryEnable != VK_FALSE,
|
||||||
occlusion_query_flags: conv::map_query_control(ii.queryFlags),
|
occlusion_query_flags: conv::map_query_control(ii.queryFlags),
|
||||||
pipeline_statistics: conv::map_pipeline_statistics(ii.pipelineStatistics),
|
pipeline_statistics: conv::map_pipeline_statistics(ii.pipelineStatistics),
|
||||||
|
@ -4110,7 +4116,7 @@ pub unsafe extern "C" fn gfxCmdBeginRenderPass(
|
||||||
|
|
||||||
commandBuffer.begin_render_pass(
|
commandBuffer.begin_render_pass(
|
||||||
&info.renderPass.raw,
|
&info.renderPass.raw,
|
||||||
framebuffer,
|
&*framebuffer,
|
||||||
render_area,
|
render_area,
|
||||||
clear_values,
|
clear_values,
|
||||||
contents,
|
contents,
|
||||||
|
@ -4375,7 +4381,7 @@ pub unsafe extern "C" fn gfxCreateSwapchainKHR(
|
||||||
count: info.minImageCount as u8,
|
count: info.minImageCount as u8,
|
||||||
current_index: 0,
|
current_index: 0,
|
||||||
active: None,
|
active: None,
|
||||||
lazy_framebuffers: Vec::with_capacity(1),
|
lazy_framebuffers: Mutex::new(Vec::with_capacity(1)),
|
||||||
};
|
};
|
||||||
*pSwapchain = Handle::new(swapchain);
|
*pSwapchain = Handle::new(swapchain);
|
||||||
VkResult::VK_SUCCESS
|
VkResult::VK_SUCCESS
|
||||||
|
@ -4709,7 +4715,7 @@ pub unsafe extern "C" fn gfxQueuePresentKHR(
|
||||||
} else {
|
} else {
|
||||||
warn!("Swapchain frame {} is stale, can't be presented.", *index);
|
warn!("Swapchain frame {} is stale, can't be presented.", *index);
|
||||||
}
|
}
|
||||||
for framebuffer in sc.lazy_framebuffers.drain(..) {
|
for framebuffer in sc.lazy_framebuffers.lock().drain(..) {
|
||||||
sc.gpu.device.destroy_framebuffer(framebuffer)
|
sc.gpu.device.destroy_framebuffer(framebuffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,11 +39,12 @@ mod conv;
|
||||||
mod handle;
|
mod handle;
|
||||||
mod impls;
|
mod impls;
|
||||||
|
|
||||||
use crate::back::Backend as B;
|
use crate::{
|
||||||
use crate::handle::{DispatchHandle, Handle};
|
back::Backend as B,
|
||||||
|
handle::{DispatchHandle, Handle},
|
||||||
|
};
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, slice};
|
||||||
use std::slice;
|
|
||||||
|
|
||||||
pub use crate::impls::*;
|
pub use crate::impls::*;
|
||||||
|
|
||||||
|
@ -157,11 +158,26 @@ pub enum Framebuffer {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum FramebufferResolve<'a> {
|
||||||
|
Native(&'a <B as hal::Backend>::Framebuffer),
|
||||||
|
Lazy(parking_lot::MappedMutexGuard<'a, <B as hal::Backend>::Framebuffer>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Deref for FramebufferResolve<'_> {
|
||||||
|
type Target = <B as hal::Backend>::Framebuffer;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
match *self {
|
||||||
|
FramebufferResolve::Native(fb) => fb,
|
||||||
|
FramebufferResolve::Lazy(ref guard) => &*guard,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Framebuffer {
|
impl Framebuffer {
|
||||||
fn resolve(&self, render_pass: VkRenderPass) -> &<B as hal::Backend>::Framebuffer {
|
fn resolve(&self, render_pass: VkRenderPass) -> FramebufferResolve {
|
||||||
let mut sc = None;
|
let mut sc = None;
|
||||||
match *self {
|
match *self {
|
||||||
Framebuffer::Native(ref fbo) => fbo,
|
Framebuffer::Native(ref fbo) => FramebufferResolve::Native(fbo),
|
||||||
Framebuffer::Lazy { extent, ref views } => {
|
Framebuffer::Lazy { extent, ref views } => {
|
||||||
for view in views {
|
for view in views {
|
||||||
if let Some(&mut ImageView::SwapchainFrame { ref swapchain, .. }) =
|
if let Some(&mut ImageView::SwapchainFrame { ref swapchain, .. }) =
|
||||||
|
@ -189,13 +205,19 @@ impl Framebuffer {
|
||||||
|
|
||||||
let sc = sc.expect("No swapchain frames detected");
|
let sc = sc.expect("No swapchain frames detected");
|
||||||
let gpu = sc.gpu;
|
let gpu = sc.gpu;
|
||||||
sc.lazy_framebuffers.push(unsafe {
|
|
||||||
use hal::device::Device;
|
FramebufferResolve::Lazy(parking_lot::MutexGuard::map(
|
||||||
gpu.device
|
sc.lazy_framebuffers.lock(),
|
||||||
.create_framebuffer(&render_pass.raw, attachments, extent)
|
|lazy_framebuffers| {
|
||||||
.unwrap()
|
lazy_framebuffers.push(unsafe {
|
||||||
});
|
use hal::device::Device;
|
||||||
sc.lazy_framebuffers.last().unwrap()
|
gpu.device
|
||||||
|
.create_framebuffer(&render_pass.raw, attachments, extent)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
lazy_framebuffers.last_mut().unwrap()
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,9 +249,7 @@ pub struct Swapchain<B: hal::Backend> {
|
||||||
count: u8,
|
count: u8,
|
||||||
current_index: u8,
|
current_index: u8,
|
||||||
active: Option<<B::Surface as hal::window::PresentationSurface<B>>::SwapchainImage>,
|
active: Option<<B::Surface as hal::window::PresentationSurface<B>>::SwapchainImage>,
|
||||||
// This is totally unsafe: if multiple threads would start recording render passes into
|
lazy_framebuffers: parking_lot::Mutex<Vec<<B as hal::Backend>::Framebuffer>>,
|
||||||
// that uses this swapchain, we'd have a race condition.
|
|
||||||
lazy_framebuffers: Vec<<B as hal::Backend>::Framebuffer>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* automatically generated by rust-bindgen */
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
Loading…
Reference in a new issue