mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Update render pass and framebuffers logic to the latest gfx-hal
This commit is contained in:
parent
4ce449c89f
commit
012569845d
25
Cargo.lock
generated
25
Cargo.lock
generated
@ -441,7 +441,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gfx-auxil"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=6b3a1e36939473f0062232baf11e1deacd6605f4#6b3a1e36939473f0062232baf11e1deacd6605f4"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=006f0c00782d5f602b4afa8e1fa9ffc2085af997#006f0c00782d5f602b4afa8e1fa9ffc2085af997"
|
||||
dependencies = [
|
||||
"fxhash",
|
||||
"gfx-hal",
|
||||
@ -451,7 +451,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gfx-backend-dx11"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=6b3a1e36939473f0062232baf11e1deacd6605f4#6b3a1e36939473f0062232baf11e1deacd6605f4"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=006f0c00782d5f602b4afa8e1fa9ffc2085af997#006f0c00782d5f602b4afa8e1fa9ffc2085af997"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
@ -472,7 +472,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gfx-backend-dx12"
|
||||
version = "0.6.2"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=6b3a1e36939473f0062232baf11e1deacd6605f4#6b3a1e36939473f0062232baf11e1deacd6605f4"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=006f0c00782d5f602b4afa8e1fa9ffc2085af997#006f0c00782d5f602b4afa8e1fa9ffc2085af997"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bit-set",
|
||||
@ -492,7 +492,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gfx-backend-empty"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=6b3a1e36939473f0062232baf11e1deacd6605f4#6b3a1e36939473f0062232baf11e1deacd6605f4"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=006f0c00782d5f602b4afa8e1fa9ffc2085af997#006f0c00782d5f602b4afa8e1fa9ffc2085af997"
|
||||
dependencies = [
|
||||
"gfx-hal",
|
||||
"log",
|
||||
@ -502,7 +502,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gfx-backend-gl"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=6b3a1e36939473f0062232baf11e1deacd6605f4#6b3a1e36939473f0062232baf11e1deacd6605f4"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=006f0c00782d5f602b4afa8e1fa9ffc2085af997#006f0c00782d5f602b4afa8e1fa9ffc2085af997"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
@ -525,7 +525,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gfx-backend-metal"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=6b3a1e36939473f0062232baf11e1deacd6605f4#6b3a1e36939473f0062232baf11e1deacd6605f4"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=006f0c00782d5f602b4afa8e1fa9ffc2085af997#006f0c00782d5f602b4afa8e1fa9ffc2085af997"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
@ -535,7 +535,6 @@ dependencies = [
|
||||
"foreign-types",
|
||||
"gfx-auxil",
|
||||
"gfx-hal",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"metal",
|
||||
"naga",
|
||||
@ -550,7 +549,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gfx-backend-vulkan"
|
||||
version = "0.6.5"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=6b3a1e36939473f0062232baf11e1deacd6605f4#6b3a1e36939473f0062232baf11e1deacd6605f4"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=006f0c00782d5f602b4afa8e1fa9ffc2085af997#006f0c00782d5f602b4afa8e1fa9ffc2085af997"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"ash",
|
||||
@ -558,10 +557,10 @@ dependencies = [
|
||||
"core-graphics-types",
|
||||
"gfx-hal",
|
||||
"inplace_it",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"naga",
|
||||
"objc",
|
||||
"parking_lot 0.11.0",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"winapi 0.3.9",
|
||||
@ -570,7 +569,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gfx-hal"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=6b3a1e36939473f0062232baf11e1deacd6605f4#6b3a1e36939473f0062232baf11e1deacd6605f4"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=006f0c00782d5f602b4afa8e1fa9ffc2085af997#006f0c00782d5f602b4afa8e1fa9ffc2085af997"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"naga",
|
||||
@ -580,9 +579,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "glow"
|
||||
version = "0.6.1"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1625b792e2f9267116dd41eb7d325e0ea2572ceba5069451906745e04f852f33"
|
||||
checksum = "3eac04632dc8c047fb70d658f8479583e1bb084859f67a150227769a10fc161f"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"slotmap",
|
||||
@ -1209,7 +1208,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "range-alloc"
|
||||
version = "0.1.1"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=6b3a1e36939473f0062232baf11e1deacd6605f4#6b3a1e36939473f0062232baf11e1deacd6605f4"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=006f0c00782d5f602b4afa8e1fa9ffc2085af997#006f0c00782d5f602b4afa8e1fa9ffc2085af997"
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
|
||||
@ -6,7 +6,7 @@ members = [
|
||||
"wgpu-types",
|
||||
]
|
||||
|
||||
#[patch."https://github.com/gfx-rs/gfx"]
|
||||
[patch."https://github.com/gfx-rs/gfx"]
|
||||
#hal = { package = "gfx-hal", path = "../gfx/src/hal" }
|
||||
#gfx-backend-vulkan = { path = "../gfx/src/backend/vulkan", features = ["naga"] }
|
||||
#gfx-backend-metal = { path = "../gfx/src/backend/metal", features = ["naga"] }
|
||||
@ -15,5 +15,5 @@ members = [
|
||||
#gfx-backend-dx11 = { path = "../gfx/src/backend/dx11" }
|
||||
#gfx-backend-empty = { path = "../gfx/src/backend/empty" }
|
||||
|
||||
#[patch."https://github.com/gfx-rs/naga"]
|
||||
[patch."https://github.com/gfx-rs/naga"]
|
||||
#naga = { path = "../naga" }
|
||||
|
||||
@ -36,24 +36,24 @@ thiserror = "1"
|
||||
gpu-alloc = { git = "https://github.com/zakarumych/gpu-alloc", rev = "29e761f24edc50e28d238e723503b146d55d222e", features = ["tracing"] }
|
||||
gpu-descriptor = { git = "https://github.com/zakarumych/gpu-descriptor", rev = "df74fd8c7bea03149058a41aab0e4fe04077b266", features = ["tracing"] }
|
||||
|
||||
hal = { package = "gfx-hal", git = "https://github.com/gfx-rs/gfx", rev = "6b3a1e36939473f0062232baf11e1deacd6605f4" }
|
||||
gfx-backend-empty = { git = "https://github.com/gfx-rs/gfx", rev = "6b3a1e36939473f0062232baf11e1deacd6605f4" }
|
||||
hal = { package = "gfx-hal", git = "https://github.com/gfx-rs/gfx", rev = "006f0c00782d5f602b4afa8e1fa9ffc2085af997" }
|
||||
gfx-backend-empty = { git = "https://github.com/gfx-rs/gfx", rev = "006f0c00782d5f602b4afa8e1fa9ffc2085af997" }
|
||||
|
||||
[target.'cfg(all(not(target_arch = "wasm32"), all(unix, not(target_os = "ios"), not(target_os = "macos"))))'.dependencies]
|
||||
gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", rev = "6b3a1e36939473f0062232baf11e1deacd6605f4", features = ["naga"] }
|
||||
gfx-backend-gl = { git = "https://github.com/gfx-rs/gfx", rev = "6b3a1e36939473f0062232baf11e1deacd6605f4", features = ["naga"] }
|
||||
gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", rev = "006f0c00782d5f602b4afa8e1fa9ffc2085af997", features = ["naga"] }
|
||||
gfx-backend-gl = { git = "https://github.com/gfx-rs/gfx", rev = "006f0c00782d5f602b4afa8e1fa9ffc2085af997", features = ["naga"] }
|
||||
|
||||
[target.'cfg(all(not(target_arch = "wasm32"), any(target_os = "ios", target_os = "macos")))'.dependencies]
|
||||
gfx-backend-metal = { git = "https://github.com/gfx-rs/gfx", rev = "6b3a1e36939473f0062232baf11e1deacd6605f4", features = ["naga"] }
|
||||
gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", rev = "6b3a1e36939473f0062232baf11e1deacd6605f4", optional = true }
|
||||
gfx-backend-metal = { git = "https://github.com/gfx-rs/gfx", rev = "006f0c00782d5f602b4afa8e1fa9ffc2085af997", features = ["naga"] }
|
||||
gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", rev = "006f0c00782d5f602b4afa8e1fa9ffc2085af997", optional = true }
|
||||
|
||||
[target.'cfg(all(not(target_arch = "wasm32"), windows))'.dependencies]
|
||||
gfx-backend-dx12 = { git = "https://github.com/gfx-rs/gfx", rev = "6b3a1e36939473f0062232baf11e1deacd6605f4" }
|
||||
gfx-backend-dx11 = { git = "https://github.com/gfx-rs/gfx", rev = "6b3a1e36939473f0062232baf11e1deacd6605f4" }
|
||||
gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", rev = "6b3a1e36939473f0062232baf11e1deacd6605f4", features = ["naga"] }
|
||||
gfx-backend-dx12 = { git = "https://github.com/gfx-rs/gfx", rev = "006f0c00782d5f602b4afa8e1fa9ffc2085af997" }
|
||||
gfx-backend-dx11 = { git = "https://github.com/gfx-rs/gfx", rev = "006f0c00782d5f602b4afa8e1fa9ffc2085af997" }
|
||||
gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", rev = "006f0c00782d5f602b4afa8e1fa9ffc2085af997", features = ["naga"] }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
gfx-backend-gl = { git = "https://github.com/gfx-rs/gfx", rev = "6b3a1e36939473f0062232baf11e1deacd6605f4", features = ["naga"] }
|
||||
gfx-backend-gl = { git = "https://github.com/gfx-rs/gfx", rev = "006f0c00782d5f602b4afa8e1fa9ffc2085af997", features = ["naga"] }
|
||||
|
||||
[dependencies.naga]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
|
||||
@ -43,7 +43,7 @@ pub struct CommandBuffer<B: hal::Backend> {
|
||||
recorded_thread_id: ThreadId,
|
||||
pub(crate) device_id: Stored<id::DeviceId>,
|
||||
pub(crate) trackers: TrackerSet,
|
||||
pub(crate) used_swap_chains: SmallVec<[(Stored<id::SwapChainId>, B::Framebuffer); 1]>,
|
||||
pub(crate) used_swap_chains: SmallVec<[Stored<id::SwapChainId>; 1]>,
|
||||
limits: wgt::Limits,
|
||||
private_features: PrivateFeatures,
|
||||
has_labels: bool,
|
||||
@ -217,7 +217,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
Ok(cmd_buf) => {
|
||||
cmd_buf.is_recording = false;
|
||||
// stop tracking the swapchain image, if used
|
||||
for (ref sc_id, _) in cmd_buf.used_swap_chains.iter() {
|
||||
for sc_id in cmd_buf.used_swap_chains.iter() {
|
||||
let view_id = swap_chain_guard[sc_id.value]
|
||||
.acquired_view_id
|
||||
.as_ref()
|
||||
|
||||
@ -11,8 +11,8 @@ use crate::{
|
||||
},
|
||||
conv,
|
||||
device::{
|
||||
AttachmentData, AttachmentDataVec, Device, FramebufferKey, RenderPassCompatibilityError,
|
||||
RenderPassContext, RenderPassKey, MAX_COLOR_TARGETS, MAX_VERTEX_BUFFERS,
|
||||
AttachmentData, AttachmentDataVec, Device, RenderPassCompatibilityError, RenderPassContext,
|
||||
RenderPassKey, RenderPassLock, MAX_COLOR_TARGETS, MAX_VERTEX_BUFFERS,
|
||||
},
|
||||
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Storage, Token},
|
||||
id,
|
||||
@ -42,6 +42,7 @@ use std::{
|
||||
borrow::{Borrow, Cow},
|
||||
collections::hash_map::Entry,
|
||||
fmt, iter,
|
||||
marker::PhantomData,
|
||||
num::NonZeroU32,
|
||||
ops::Range,
|
||||
str,
|
||||
@ -503,15 +504,14 @@ struct RenderAttachment<'a> {
|
||||
new_use: TextureUse,
|
||||
}
|
||||
|
||||
type UsedSwapChainInfo<F> = Option<(Stored<id::SwapChainId>, F)>;
|
||||
|
||||
struct RenderPassInfo<'a, B: hal::Backend> {
|
||||
context: RenderPassContext,
|
||||
trackers: TrackerSet,
|
||||
render_attachments: AttachmentDataVec<RenderAttachment<'a>>,
|
||||
used_swapchain_with_framebuffer: UsedSwapChainInfo<B::Framebuffer>,
|
||||
used_swap_chain: Option<Stored<id::SwapChainId>>,
|
||||
is_ds_read_only: bool,
|
||||
extent: wgt::Extent3d,
|
||||
_phantom: PhantomData<B>,
|
||||
}
|
||||
|
||||
impl<'a, B: GfxBackend> RenderPassInfo<'a, B> {
|
||||
@ -543,7 +543,6 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> {
|
||||
let mut depth_stencil_aspects = hal::format::Aspects::empty();
|
||||
let mut used_swap_chain = None::<Stored<id::SwapChainId>>;
|
||||
let mut trackers = TrackerSet::new(B::VARIANT);
|
||||
let mut used_swapchain_with_framebuffer = None;
|
||||
|
||||
let mut add_view = |view: &TextureView<B>| {
|
||||
if let Some(ex) = extent {
|
||||
@ -809,8 +808,11 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> {
|
||||
return Err(RenderPassErrorInner::InvalidSampleCount(sample_count));
|
||||
}
|
||||
|
||||
let mut render_pass_cache = device.render_passes.lock();
|
||||
let render_pass = match render_pass_cache.entry(rp_key.clone()) {
|
||||
let RenderPassLock {
|
||||
ref mut render_passes,
|
||||
ref mut framebuffers,
|
||||
} = *device.render_passes.lock();
|
||||
let render_pass = match render_passes.entry(rp_key.clone()) {
|
||||
Entry::Occupied(e) => e.into_mut(),
|
||||
Entry::Vacant(entry) => {
|
||||
let color_ids: [hal::pass::AttachmentRef; MAX_COLOR_TARGETS] = [
|
||||
@ -871,82 +873,40 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> {
|
||||
}
|
||||
};
|
||||
|
||||
let mut framebuffer_cache;
|
||||
let fb_key = FramebufferKey {
|
||||
let view_data = AttachmentData {
|
||||
colors: color_attachments
|
||||
.iter()
|
||||
.map(|at| id::Valid(at.attachment))
|
||||
.map(|at| view_guard.get(at.attachment).unwrap())
|
||||
.collect(),
|
||||
resolves: color_attachments
|
||||
.iter()
|
||||
.filter_map(|at| at.resolve_target)
|
||||
.map(id::Valid)
|
||||
.map(|attachment| view_guard.get(attachment).unwrap())
|
||||
.collect(),
|
||||
depth_stencil: depth_stencil_attachment.map(|at| id::Valid(at.attachment)),
|
||||
depth_stencil: depth_stencil_attachment
|
||||
.map(|at| view_guard.get(at.attachment).unwrap()),
|
||||
};
|
||||
let fb_key = view_data.map(|view| view.framebuffer_attachment.clone());
|
||||
let context = RenderPassContext {
|
||||
attachments: AttachmentData {
|
||||
colors: fb_key
|
||||
.colors
|
||||
.iter()
|
||||
.map(|&at| view_guard[at].format)
|
||||
.collect(),
|
||||
resolves: fb_key
|
||||
.resolves
|
||||
.iter()
|
||||
.map(|&at| view_guard[at].format)
|
||||
.collect(),
|
||||
depth_stencil: fb_key.depth_stencil.map(|at| view_guard[at].format),
|
||||
},
|
||||
attachments: view_data.map(|view| view.format),
|
||||
sample_count,
|
||||
};
|
||||
|
||||
let framebuffer = match used_swap_chain.take() {
|
||||
Some(sc_id) => {
|
||||
// Always create a new framebuffer and delete it after presentation.
|
||||
let attachments = fb_key
|
||||
.all()
|
||||
.map(|&id| match view_guard[id].inner {
|
||||
TextureViewInner::Native { ref raw, .. } => raw,
|
||||
TextureViewInner::SwapChain { ref image, .. } => Borrow::borrow(image),
|
||||
})
|
||||
.collect::<AttachmentDataVec<_>>();
|
||||
let framebuffer = unsafe {
|
||||
// Cache framebuffers by the device.
|
||||
let framebuffer = match framebuffers.entry(fb_key) {
|
||||
Entry::Occupied(e) => e.into_mut(),
|
||||
Entry::Vacant(e) => {
|
||||
let fb = unsafe {
|
||||
device
|
||||
.raw
|
||||
.create_framebuffer(&render_pass, attachments, extent.unwrap())
|
||||
.create_framebuffer(
|
||||
&render_pass,
|
||||
e.key().all().map(|fat| fat.clone()),
|
||||
extent.unwrap(),
|
||||
)
|
||||
.or(Err(RenderPassErrorInner::OutOfMemory))?
|
||||
};
|
||||
used_swapchain_with_framebuffer = Some((sc_id, framebuffer));
|
||||
&mut used_swapchain_with_framebuffer.as_mut().unwrap().1
|
||||
}
|
||||
None => {
|
||||
// Cache framebuffers by the device.
|
||||
framebuffer_cache = device.framebuffers.lock();
|
||||
match framebuffer_cache.entry(fb_key) {
|
||||
Entry::Occupied(e) => e.into_mut(),
|
||||
Entry::Vacant(e) => {
|
||||
let fb = {
|
||||
let attachments = e
|
||||
.key()
|
||||
.all()
|
||||
.map(|&id| match view_guard[id].inner {
|
||||
TextureViewInner::Native { ref raw, .. } => raw,
|
||||
TextureViewInner::SwapChain { ref image, .. } => {
|
||||
Borrow::borrow(image)
|
||||
}
|
||||
})
|
||||
.collect::<AttachmentDataVec<_>>();
|
||||
unsafe {
|
||||
device
|
||||
.raw
|
||||
.create_framebuffer(&render_pass, attachments, extent.unwrap())
|
||||
.or(Err(RenderPassErrorInner::OutOfMemory))?
|
||||
}
|
||||
};
|
||||
e.insert(fb)
|
||||
}
|
||||
}
|
||||
e.insert(fb)
|
||||
}
|
||||
};
|
||||
|
||||
@ -959,59 +919,75 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> {
|
||||
h: ex.height as _,
|
||||
}
|
||||
};
|
||||
let raw_views = view_data.map(|view| match view.inner {
|
||||
TextureViewInner::Native { ref raw, .. } => raw,
|
||||
TextureViewInner::SwapChain { ref image, .. } => Borrow::borrow(image),
|
||||
});
|
||||
|
||||
let clear_values = color_attachments
|
||||
let attachments = color_attachments
|
||||
.iter()
|
||||
.zip(&rp_key.colors)
|
||||
.flat_map(|(at, (rat, _layout))| {
|
||||
match at.channel.load_op {
|
||||
LoadOp::Load => None,
|
||||
LoadOp::Clear => {
|
||||
use hal::format::ChannelType;
|
||||
//TODO: validate sign/unsign and normalized ranges of the color values
|
||||
let value = match rat.format.unwrap().base_format().1 {
|
||||
ChannelType::Unorm
|
||||
| ChannelType::Snorm
|
||||
| ChannelType::Ufloat
|
||||
| ChannelType::Sfloat
|
||||
| ChannelType::Uscaled
|
||||
| ChannelType::Sscaled
|
||||
| ChannelType::Srgb => hal::command::ClearColor {
|
||||
float32: conv::map_color_f32(&at.channel.clear_value),
|
||||
},
|
||||
ChannelType::Sint => hal::command::ClearColor {
|
||||
sint32: conv::map_color_i32(&at.channel.clear_value),
|
||||
},
|
||||
ChannelType::Uint => hal::command::ClearColor {
|
||||
uint32: conv::map_color_u32(&at.channel.clear_value),
|
||||
},
|
||||
};
|
||||
Some(hal::command::ClearValue { color: value })
|
||||
}
|
||||
}
|
||||
})
|
||||
.chain(depth_stencil_attachment.and_then(|at| {
|
||||
match (at.depth.load_op, at.stencil.load_op) {
|
||||
(LoadOp::Load, LoadOp::Load) => None,
|
||||
(LoadOp::Clear, _) | (_, LoadOp::Clear) => {
|
||||
let value = hal::command::ClearDepthStencil {
|
||||
depth: at.depth.clear_value,
|
||||
stencil: at.stencil.clear_value,
|
||||
};
|
||||
Some(hal::command::ClearValue {
|
||||
depth_stencil: value,
|
||||
})
|
||||
}
|
||||
.zip(raw_views.colors)
|
||||
.map(
|
||||
|((at, (rat, _layout)), image_view)| hal::command::RenderAttachmentInfo {
|
||||
image_view,
|
||||
clear_value: match at.channel.load_op {
|
||||
LoadOp::Load => Default::default(),
|
||||
LoadOp::Clear => {
|
||||
use hal::format::ChannelType;
|
||||
//TODO: validate sign/unsign and normalized ranges of the color values
|
||||
let value = match rat.format.unwrap().base_format().1 {
|
||||
ChannelType::Unorm
|
||||
| ChannelType::Snorm
|
||||
| ChannelType::Ufloat
|
||||
| ChannelType::Sfloat
|
||||
| ChannelType::Uscaled
|
||||
| ChannelType::Sscaled
|
||||
| ChannelType::Srgb => hal::command::ClearColor {
|
||||
float32: conv::map_color_f32(&at.channel.clear_value),
|
||||
},
|
||||
ChannelType::Sint => hal::command::ClearColor {
|
||||
sint32: conv::map_color_i32(&at.channel.clear_value),
|
||||
},
|
||||
ChannelType::Uint => hal::command::ClearColor {
|
||||
uint32: conv::map_color_u32(&at.channel.clear_value),
|
||||
},
|
||||
};
|
||||
hal::command::ClearValue { color: value }
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
.chain(raw_views.resolves.into_iter().map(|image_view| {
|
||||
hal::command::RenderAttachmentInfo {
|
||||
image_view,
|
||||
clear_value: Default::default(),
|
||||
}
|
||||
}))
|
||||
.collect::<ArrayVec<[_; MAX_COLOR_TARGETS + 1]>>();
|
||||
.chain(depth_stencil_attachment.zip(raw_views.depth_stencil).map(
|
||||
|(at, image_view)| hal::command::RenderAttachmentInfo {
|
||||
image_view,
|
||||
clear_value: match (at.depth.load_op, at.stencil.load_op) {
|
||||
(LoadOp::Load, LoadOp::Load) => Default::default(),
|
||||
(LoadOp::Clear, _) | (_, LoadOp::Clear) => {
|
||||
let value = hal::command::ClearDepthStencil {
|
||||
depth: at.depth.clear_value,
|
||||
stencil: at.stencil.clear_value,
|
||||
};
|
||||
hal::command::ClearValue {
|
||||
depth_stencil: value,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
));
|
||||
|
||||
unsafe {
|
||||
raw.begin_render_pass(
|
||||
render_pass,
|
||||
framebuffer,
|
||||
rect,
|
||||
clear_values,
|
||||
attachments,
|
||||
hal::command::SubpassContents::Inline,
|
||||
);
|
||||
raw.set_scissors(0, iter::once(&rect));
|
||||
@ -1028,20 +1004,21 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> {
|
||||
context,
|
||||
trackers,
|
||||
render_attachments,
|
||||
used_swapchain_with_framebuffer,
|
||||
used_swap_chain,
|
||||
is_ds_read_only,
|
||||
extent: wgt::Extent3d {
|
||||
width: attachment_width.ok_or(RenderPassErrorInner::MissingAttachments)?,
|
||||
height: attachment_height.ok_or(RenderPassErrorInner::MissingAttachments)?,
|
||||
depth: 1,
|
||||
},
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn finish(
|
||||
mut self,
|
||||
texture_guard: &Storage<Texture<B>, id::TextureId>,
|
||||
) -> Result<(TrackerSet, UsedSwapChainInfo<B::Framebuffer>), RenderPassErrorInner> {
|
||||
) -> Result<(TrackerSet, Option<Stored<id::SwapChainId>>), RenderPassErrorInner> {
|
||||
for ra in self.render_attachments {
|
||||
let texture = &texture_guard[ra.texture_id.value];
|
||||
check_texture_usage(texture.usage, TextureUsage::RENDER_ATTACHMENT)?;
|
||||
@ -1072,7 +1049,7 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> {
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
Ok((self.trackers, self.used_swapchain_with_framebuffer))
|
||||
Ok((self.trackers, self.used_swap_chain))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1108,7 +1085,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
|
||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||
|
||||
let (cmd_buf_raw, trackers, used_swapchain_with_framebuffer) = {
|
||||
let (cmd_buf_raw, trackers, used_swapchain) = {
|
||||
// read-only lock guard
|
||||
let (cmb_guard, mut token) = hub.command_buffers.read(&mut token);
|
||||
|
||||
@ -1866,9 +1843,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
raw.end_render_pass();
|
||||
}
|
||||
|
||||
let (trackers, used_swapchain_with_framebuffer) =
|
||||
info.finish(&*texture_guard).map_pass_err(scope)?;
|
||||
(raw, trackers, used_swapchain_with_framebuffer)
|
||||
let (trackers, used_swapchain) = info.finish(&*texture_guard).map_pass_err(scope)?;
|
||||
(raw, trackers, used_swapchain)
|
||||
};
|
||||
|
||||
let (mut cmb_guard, mut token) = hub.command_buffers.write(&mut token);
|
||||
@ -1877,9 +1853,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
let cmd_buf =
|
||||
CommandBuffer::get_encoder_mut(&mut *cmb_guard, encoder_id).map_pass_err(scope)?;
|
||||
cmd_buf.has_labels |= base.label.is_some();
|
||||
cmd_buf
|
||||
.used_swap_chains
|
||||
.extend(used_swapchain_with_framebuffer);
|
||||
cmd_buf.used_swap_chains.extend(used_swapchain);
|
||||
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(ref mut list) = cmd_buf.commands {
|
||||
|
||||
@ -14,7 +14,7 @@ use crate::{
|
||||
hub::{GfxBackend, GlobalIdentityHandlerFactory, Hub, Token},
|
||||
id, resource,
|
||||
track::TrackerSet,
|
||||
FastHashMap, RefCount, Stored, SubmissionIndex,
|
||||
RefCount, Stored, SubmissionIndex,
|
||||
};
|
||||
|
||||
use copyless::VecHelper as _;
|
||||
@ -636,74 +636,6 @@ impl<B: GfxBackend> LifetimeTracker<B> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn triage_framebuffers<G: GlobalIdentityHandlerFactory>(
|
||||
&mut self,
|
||||
hub: &Hub<B, G>,
|
||||
framebuffers: &mut FastHashMap<super::FramebufferKey, B::Framebuffer>,
|
||||
token: &mut Token<super::Device<B>>,
|
||||
) {
|
||||
let (texture_view_guard, _) = hub.texture_views.read(token);
|
||||
let remove_list = framebuffers
|
||||
.keys()
|
||||
.filter_map(|key| {
|
||||
let mut last_submit = None;
|
||||
let mut needs_cleanup = false;
|
||||
|
||||
// A framebuffer needs to be scheduled for cleanup, if there's at least one
|
||||
// attachment is no longer valid.
|
||||
|
||||
for &at in key.all() {
|
||||
// If this attachment is still registered, it's still valid
|
||||
if texture_view_guard.contains(at.0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// This attachment is no longer registered, this framebuffer needs cleanup
|
||||
needs_cleanup = true;
|
||||
|
||||
// Check if there's any active submissions that are still referring to this
|
||||
// attachment, if there are we need to get the greatest submission index, as
|
||||
// that's the last time this attachment is still valid
|
||||
let mut attachment_last_submit = None;
|
||||
for a in &self.active {
|
||||
if a.last_resources.image_views.iter().any(|&(id, _)| id == at) {
|
||||
let max = attachment_last_submit.unwrap_or(0).max(a.index);
|
||||
attachment_last_submit = Some(max);
|
||||
}
|
||||
}
|
||||
|
||||
// Between all attachments, we need the smallest index, because that's the last
|
||||
// time this framebuffer is still valid
|
||||
if let Some(attachment_last_submit) = attachment_last_submit {
|
||||
let min = last_submit
|
||||
.unwrap_or(std::usize::MAX)
|
||||
.min(attachment_last_submit);
|
||||
last_submit = Some(min);
|
||||
}
|
||||
}
|
||||
|
||||
if needs_cleanup {
|
||||
Some((key.clone(), last_submit.unwrap_or(0)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<FastHashMap<_, _>>();
|
||||
|
||||
if !remove_list.is_empty() {
|
||||
tracing::debug!("Free framebuffers {:?}", remove_list);
|
||||
for (ref key, submit_index) in remove_list {
|
||||
let framebuffer = framebuffers.remove(key).unwrap();
|
||||
self.active
|
||||
.iter_mut()
|
||||
.find(|a| a.index == submit_index)
|
||||
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
||||
.framebuffers
|
||||
.push(framebuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn handle_mapping<G: GlobalIdentityHandlerFactory>(
|
||||
&mut self,
|
||||
hub: &Hub<B, G>,
|
||||
|
||||
@ -103,12 +103,20 @@ impl<T> AttachmentData<T> {
|
||||
.chain(&self.resolves)
|
||||
.chain(&self.depth_stencil)
|
||||
}
|
||||
|
||||
pub(crate) fn map<U, F: Fn(&T) -> U>(&self, fun: F) -> AttachmentData<U> {
|
||||
AttachmentData {
|
||||
colors: self.colors.iter().map(&fun).collect(),
|
||||
resolves: self.resolves.iter().map(&fun).collect(),
|
||||
depth_stencil: self.depth_stencil.as_ref().map(&fun),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type AttachmentDataVec<T> = ArrayVec<[T; MAX_COLOR_TARGETS + MAX_COLOR_TARGETS + 1]>;
|
||||
|
||||
pub(crate) type RenderPassKey = AttachmentData<(hal::pass::Attachment, hal::image::Layout)>;
|
||||
pub(crate) type FramebufferKey = AttachmentData<id::Valid<id::TextureViewId>>;
|
||||
pub(crate) type FramebufferKey = AttachmentData<hal::image::FramebufferAttachment>;
|
||||
|
||||
#[derive(Clone, Debug, Hash, PartialEq)]
|
||||
#[cfg_attr(feature = "serial-pass", derive(serde::Deserialize, serde::Serialize))]
|
||||
@ -211,11 +219,17 @@ fn fire_map_callbacks<I: IntoIterator<Item = BufferMapPendingCallback>>(callback
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct RenderPassLock<B: hal::Backend> {
|
||||
pub(crate) render_passes: FastHashMap<RenderPassKey, B::RenderPass>,
|
||||
pub(crate) framebuffers: FastHashMap<FramebufferKey, B::Framebuffer>,
|
||||
}
|
||||
|
||||
/// Structure describing a logical device. Some members are internally mutable,
|
||||
/// stored behind mutexes.
|
||||
/// TODO: establish clear order of locking for these:
|
||||
/// `mem_allocator`, `desc_allocator`, `life_tracke`, `trackers`,
|
||||
/// `render_passes`, `framebuffers`, `pending_writes`, `trace`.
|
||||
/// `render_passes`, `pending_writes`, `trace`.
|
||||
///
|
||||
/// Currently, the rules are:
|
||||
/// 1. `life_tracker` is locked after `hub.devices`, enforced by the type system
|
||||
@ -234,8 +248,7 @@ pub struct Device<B: hal::Backend> {
|
||||
pub(crate) active_submission_index: SubmissionIndex,
|
||||
/// Has to be locked temporarily only (locked last)
|
||||
pub(crate) trackers: Mutex<TrackerSet>,
|
||||
pub(crate) render_passes: Mutex<FastHashMap<RenderPassKey, B::RenderPass>>,
|
||||
pub(crate) framebuffers: Mutex<FastHashMap<FramebufferKey, B::Framebuffer>>,
|
||||
pub(crate) render_passes: Mutex<RenderPassLock<B>>,
|
||||
// Life tracker should be locked right after the device and before anything else.
|
||||
life_tracker: Mutex<life::LifetimeTracker<B>>,
|
||||
temp_suspected: life::SuspectedResources,
|
||||
@ -297,8 +310,10 @@ impl<B: GfxBackend> Device<B> {
|
||||
life_guard: LifeGuard::new("<device>"),
|
||||
active_submission_index: 0,
|
||||
trackers: Mutex::new(TrackerSet::new(B::VARIANT)),
|
||||
render_passes: Mutex::new(FastHashMap::default()),
|
||||
framebuffers: Mutex::new(FastHashMap::default()),
|
||||
render_passes: Mutex::new(RenderPassLock {
|
||||
render_passes: FastHashMap::default(),
|
||||
framebuffers: FastHashMap::default(),
|
||||
}),
|
||||
life_tracker: Mutex::new(life::LifetimeTracker::new()),
|
||||
temp_suspected: life::SuspectedResources::default(),
|
||||
#[cfg(feature = "trace")]
|
||||
@ -359,7 +374,6 @@ impl<B: GfxBackend> Device<B> {
|
||||
token,
|
||||
);
|
||||
life_tracker.triage_mapped(hub, token);
|
||||
life_tracker.triage_framebuffers(hub, &mut *self.framebuffers.lock(), token);
|
||||
let last_done = life_tracker.triage_submissions(&self.raw, force_wait)?;
|
||||
let callbacks = life_tracker.handle_mapping(hub, &self.raw, &self.trackers, token);
|
||||
life_tracker.cleanup(&self.raw, &self.mem_allocator, &self.desc_allocator);
|
||||
@ -591,12 +605,11 @@ impl<B: GfxBackend> Device<B> {
|
||||
mip_level_count,
|
||||
));
|
||||
}
|
||||
let mut view_capabilities = hal::image::ViewCapabilities::empty();
|
||||
|
||||
let mut view_caps = hal::image::ViewCapabilities::empty();
|
||||
// 2D textures with array layer counts that are multiples of 6 could be cubemaps
|
||||
// Following gpuweb/gpuweb#68 always add the hint in that case
|
||||
if desc.dimension == TextureDimension::D2 && desc.size.depth % 6 == 0 {
|
||||
view_capabilities |= hal::image::ViewCapabilities::KIND_CUBE;
|
||||
view_caps |= hal::image::ViewCapabilities::KIND_CUBE;
|
||||
};
|
||||
|
||||
// TODO: 2D arrays, cubemap arrays
|
||||
@ -610,7 +623,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
format,
|
||||
hal::image::Tiling::Optimal,
|
||||
usage,
|
||||
view_capabilities,
|
||||
view_caps,
|
||||
)
|
||||
.map_err(|err| match err {
|
||||
hal::image::CreationError::OutOfMemory(_) => DeviceError::OutOfMemory,
|
||||
@ -642,6 +655,11 @@ impl<B: GfxBackend> Device<B> {
|
||||
kind,
|
||||
format: desc.format,
|
||||
format_features,
|
||||
framebuffer_attachment: hal::image::FramebufferAttachment {
|
||||
usage,
|
||||
format,
|
||||
view_caps,
|
||||
},
|
||||
full_range: TextureSelector {
|
||||
levels: 0..desc.mip_level_count as hal::image::Level,
|
||||
layers: 0..kind.num_layers(),
|
||||
@ -801,6 +819,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
format_features: texture.format_features,
|
||||
extent: texture.kind.extent().at_level(desc.base_mip_level as _),
|
||||
samples: texture.kind.num_samples(),
|
||||
framebuffer_attachment: texture.framebuffer_attachment.clone(),
|
||||
selector,
|
||||
life_guard: LifeGuard::new(desc.label.borrow_or_default()),
|
||||
})
|
||||
@ -2172,7 +2191,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
.get(pipeline_layout_id)
|
||||
.map_err(|_| pipeline::CreateRenderPipelineError::InvalidLayout)?;
|
||||
|
||||
let mut render_pass_cache = self.render_passes.lock();
|
||||
let mut rp_lock = self.render_passes.lock();
|
||||
let pipeline_desc = hal::pso::GraphicsPipelineDesc {
|
||||
label: desc.label.as_ref().map(AsRef::as_ref),
|
||||
primitive_assembler,
|
||||
@ -2185,7 +2204,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
layout: &layout.raw,
|
||||
subpass: hal::pass::Subpass {
|
||||
index: 0,
|
||||
main_pass: match render_pass_cache.entry(rp_key) {
|
||||
main_pass: match rp_lock.render_passes.entry(rp_key) {
|
||||
Entry::Occupied(e) => e.into_mut(),
|
||||
Entry::Vacant(e) => {
|
||||
let pass = self
|
||||
@ -2312,10 +2331,11 @@ impl<B: hal::Backend> Device<B> {
|
||||
unsafe {
|
||||
desc_alloc.cleanup(&self.raw);
|
||||
mem_alloc.clear(&self.raw);
|
||||
for (_, rp) in self.render_passes.lock().drain() {
|
||||
let rps = self.render_passes.into_inner();
|
||||
for (_, rp) in rps.render_passes {
|
||||
self.raw.destroy_render_pass(rp);
|
||||
}
|
||||
for (_, fbo) in self.framebuffers.lock().drain() {
|
||||
for (_, fbo) in rps.framebuffers {
|
||||
self.raw.destroy_framebuffer(fbo);
|
||||
}
|
||||
}
|
||||
@ -3987,6 +4007,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
}
|
||||
}
|
||||
validate_swap_chain_descriptor(&mut config, &caps)?;
|
||||
let framebuffer_attachment = config.framebuffer_attachment();
|
||||
|
||||
unsafe {
|
||||
B::get_surface_mut(surface)
|
||||
@ -4027,8 +4048,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.create_semaphore()
|
||||
.or(Err(DeviceError::OutOfMemory))?,
|
||||
acquired_view_id: None,
|
||||
acquired_framebuffers: Vec::new(),
|
||||
active_submission_index: 0,
|
||||
framebuffer_attachment,
|
||||
};
|
||||
swap_chain_guard.insert(sc_id, swap_chain);
|
||||
Ok(sc_id)
|
||||
|
||||
@ -514,19 +514,17 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
));
|
||||
}
|
||||
|
||||
for (sc_id, fbo) in cmdbuf.used_swap_chains.drain(..) {
|
||||
for sc_id in cmdbuf.used_swap_chains.drain(..) {
|
||||
let sc = &mut swap_chain_guard[sc_id.value];
|
||||
sc.active_submission_index = submit_index;
|
||||
if sc.acquired_view_id.is_none() {
|
||||
return Err(QueueSubmitError::SwapChainOutputDropped);
|
||||
}
|
||||
// For each swapchain, we only want to have at most 1 signaled semaphore.
|
||||
if sc.acquired_framebuffers.is_empty() {
|
||||
if sc.active_submission_index != submit_index {
|
||||
sc.active_submission_index = submit_index;
|
||||
// Only add a signal if this is the first time for this swapchain
|
||||
// to be used in the submission.
|
||||
signal_swapchain_semaphores.push(sc_id.value);
|
||||
}
|
||||
sc.acquired_framebuffers.push(fbo);
|
||||
}
|
||||
|
||||
// optimize the tracked states
|
||||
|
||||
@ -206,6 +206,7 @@ pub struct Texture<B: hal::Backend> {
|
||||
pub(crate) kind: hal::image::Kind,
|
||||
pub(crate) format: wgt::TextureFormat,
|
||||
pub(crate) format_features: wgt::TextureFormatFeatures,
|
||||
pub(crate) framebuffer_attachment: hal::image::FramebufferAttachment,
|
||||
pub(crate) full_range: TextureSelector,
|
||||
pub(crate) life_guard: LifeGuard,
|
||||
}
|
||||
@ -309,6 +310,7 @@ pub struct TextureView<B: hal::Backend> {
|
||||
pub(crate) format_features: wgt::TextureFormatFeatures,
|
||||
pub(crate) extent: hal::image::Extent,
|
||||
pub(crate) samples: hal::image::NumSamples,
|
||||
pub(crate) framebuffer_attachment: hal::image::FramebufferAttachment,
|
||||
pub(crate) selector: TextureSelector,
|
||||
pub(crate) life_guard: LifeGuard,
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ use crate::{
|
||||
LifeGuard, PrivateFeatures, Stored, SubmissionIndex,
|
||||
};
|
||||
|
||||
use hal::{self, device::Device as _, queue::CommandQueue as _, window::PresentationSurface as _};
|
||||
use hal::{queue::CommandQueue as _, window::PresentationSurface as _};
|
||||
use thiserror::Error;
|
||||
use wgt::{SwapChainDescriptor, SwapChainStatus};
|
||||
|
||||
@ -59,8 +59,8 @@ pub struct SwapChain<B: hal::Backend> {
|
||||
pub(crate) num_frames: hal::window::SwapImageIndex,
|
||||
pub(crate) semaphore: B::Semaphore,
|
||||
pub(crate) acquired_view_id: Option<Stored<TextureViewId>>,
|
||||
pub(crate) acquired_framebuffers: Vec<B::Framebuffer>,
|
||||
pub(crate) active_submission_index: SubmissionIndex,
|
||||
pub(crate) framebuffer_attachment: hal::image::FramebufferAttachment,
|
||||
}
|
||||
|
||||
impl<B: hal::Backend> crate::hub::Resource for SwapChain<B> {
|
||||
@ -194,6 +194,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
depth: 1,
|
||||
},
|
||||
samples: 1,
|
||||
framebuffer_attachment: sc.framebuffer_attachment.clone(),
|
||||
selector: TextureSelector {
|
||||
layers: 0..1,
|
||||
levels: 0..1,
|
||||
@ -282,12 +283,6 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
|
||||
tracing::debug!(trace = true, "Presented. End of Frame");
|
||||
|
||||
for fbo in sc.acquired_framebuffers.drain(..) {
|
||||
unsafe {
|
||||
device.raw.destroy_framebuffer(fbo);
|
||||
}
|
||||
}
|
||||
|
||||
match result {
|
||||
Ok(None) => Ok(SwapChainStatus::Good),
|
||||
Ok(Some(_)) => Ok(SwapChainStatus::Suboptimal),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user