mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-25 00:03:29 +00:00
Rustfmt stable pass
This commit is contained in:
parent
384606f2e2
commit
a3aefe2535
@ -1,4 +0,0 @@
|
|||||||
newline_style = "Native"
|
|
||||||
blank_lines_upper_bound = 2
|
|
||||||
spaces_around_ranges = true
|
|
||||||
imports_layout = "HorizontalVertical"
|
|
@ -4,16 +4,13 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
id::{BindGroupLayoutId, BufferId, DeviceId, SamplerId, TextureViewId},
|
id::{BindGroupLayoutId, BufferId, DeviceId, SamplerId, TextureViewId},
|
||||||
track::{DUMMY_SELECTOR, TrackerSet},
|
track::{TrackerSet, DUMMY_SELECTOR},
|
||||||
FastHashMap,
|
FastHashMap, LifeGuard, RefCount, Stored,
|
||||||
LifeGuard,
|
|
||||||
RefCount,
|
|
||||||
Stored,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use wgt::{BufferAddress, TextureComponentType};
|
|
||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
use gfx_descriptor::{DescriptorCounts, DescriptorSet};
|
use gfx_descriptor::{DescriptorCounts, DescriptorSet};
|
||||||
|
use wgt::{BufferAddress, TextureComponentType};
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde_crate::{Deserialize, Serialize};
|
use serde_crate::{Deserialize, Serialize};
|
||||||
@ -21,7 +18,11 @@ use std::borrow::Borrow;
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate="serde_crate"))]
|
#[cfg_attr(
|
||||||
|
feature = "serde",
|
||||||
|
derive(Serialize, Deserialize),
|
||||||
|
serde(crate = "serde_crate")
|
||||||
|
)]
|
||||||
pub enum BindingType {
|
pub enum BindingType {
|
||||||
UniformBuffer = 0,
|
UniformBuffer = 0,
|
||||||
StorageBuffer = 1,
|
StorageBuffer = 1,
|
||||||
@ -35,7 +36,11 @@ pub enum BindingType {
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Debug, Hash, PartialEq)]
|
#[derive(Clone, Debug, Hash, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate="serde_crate"))]
|
#[cfg_attr(
|
||||||
|
feature = "serde",
|
||||||
|
derive(Serialize, Deserialize),
|
||||||
|
serde(crate = "serde_crate")
|
||||||
|
)]
|
||||||
pub struct BindGroupLayoutEntry {
|
pub struct BindGroupLayoutEntry {
|
||||||
pub binding: u32,
|
pub binding: u32,
|
||||||
pub visibility: wgt::ShaderStage,
|
pub visibility: wgt::ShaderStage,
|
||||||
@ -80,7 +85,11 @@ pub struct PipelineLayout<B: hal::Backend> {
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate="serde_crate"))]
|
#[cfg_attr(
|
||||||
|
feature = "serde",
|
||||||
|
derive(Serialize, Deserialize),
|
||||||
|
serde(crate = "serde_crate")
|
||||||
|
)]
|
||||||
pub struct BufferBinding {
|
pub struct BufferBinding {
|
||||||
pub buffer: BufferId,
|
pub buffer: BufferId,
|
||||||
pub offset: BufferAddress,
|
pub offset: BufferAddress,
|
||||||
@ -89,7 +98,11 @@ pub struct BufferBinding {
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate="serde_crate"))]
|
#[cfg_attr(
|
||||||
|
feature = "serde",
|
||||||
|
derive(Serialize, Deserialize),
|
||||||
|
serde(crate = "serde_crate")
|
||||||
|
)]
|
||||||
pub enum BindingResource {
|
pub enum BindingResource {
|
||||||
Buffer(BufferBinding),
|
Buffer(BufferBinding),
|
||||||
Sampler(SamplerId),
|
Sampler(SamplerId),
|
||||||
@ -98,7 +111,11 @@ pub enum BindingResource {
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate="serde_crate"))]
|
#[cfg_attr(
|
||||||
|
feature = "serde",
|
||||||
|
derive(Serialize, Deserialize),
|
||||||
|
serde(crate = "serde_crate")
|
||||||
|
)]
|
||||||
pub struct BindGroupEntry {
|
pub struct BindGroupEntry {
|
||||||
pub binding: u32,
|
pub binding: u32,
|
||||||
pub resource: BindingResource,
|
pub resource: BindingResource,
|
||||||
|
@ -4,13 +4,7 @@
|
|||||||
|
|
||||||
use super::CommandBuffer;
|
use super::CommandBuffer;
|
||||||
use crate::{
|
use crate::{
|
||||||
hub::GfxBackend,
|
hub::GfxBackend, id::DeviceId, track::TrackerSet, Features, LifeGuard, Stored, SubmissionIndex,
|
||||||
id::DeviceId,
|
|
||||||
track::TrackerSet,
|
|
||||||
Features,
|
|
||||||
LifeGuard,
|
|
||||||
Stored,
|
|
||||||
SubmissionIndex,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use hal::{command::CommandBuffer as _, device::Device as _, pool::CommandPool as _};
|
use hal::{command::CommandBuffer as _, device::Device as _, pool::CommandPool as _};
|
||||||
@ -27,7 +21,7 @@ struct CommandPool<B: hal::Backend> {
|
|||||||
|
|
||||||
impl<B: hal::Backend> CommandPool<B> {
|
impl<B: hal::Backend> CommandPool<B> {
|
||||||
fn maintain(&mut self, lowest_active_index: SubmissionIndex) {
|
fn maintain(&mut self, lowest_active_index: SubmissionIndex) {
|
||||||
for i in (0 .. self.pending.len()).rev() {
|
for i in (0..self.pending.len()).rev() {
|
||||||
let index = self.pending[i]
|
let index = self.pending[i]
|
||||||
.life_guard
|
.life_guard
|
||||||
.submission_index
|
.submission_index
|
||||||
@ -55,7 +49,10 @@ impl<B: hal::Backend> CommandPool<B> {
|
|||||||
|
|
||||||
fn allocate(&mut self) -> B::CommandBuffer {
|
fn allocate(&mut self) -> B::CommandBuffer {
|
||||||
if self.available.is_empty() {
|
if self.available.is_empty() {
|
||||||
unsafe { self.raw.allocate(20, hal::command::Level::Primary, &mut self.available) };
|
unsafe {
|
||||||
|
self.raw
|
||||||
|
.allocate(20, hal::command::Level::Primary, &mut self.available)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
self.available.pop().unwrap()
|
self.available.pop().unwrap()
|
||||||
}
|
}
|
||||||
@ -131,7 +128,10 @@ impl<B: hal::Backend> CommandAllocator<B> {
|
|||||||
let pool = inner.pools.get_mut(&cmd_buf.recorded_thread_id).unwrap();
|
let pool = inner.pools.get_mut(&cmd_buf.recorded_thread_id).unwrap();
|
||||||
|
|
||||||
if pool.available.is_empty() {
|
if pool.available.is_empty() {
|
||||||
unsafe { pool.raw.allocate(20, hal::command::Level::Primary, &mut pool.available) };
|
unsafe {
|
||||||
|
pool.raw
|
||||||
|
.allocate(20, hal::command::Level::Primary, &mut pool.available)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pool.available.pop().unwrap()
|
pool.available.pop().unwrap()
|
||||||
|
@ -10,8 +10,8 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use wgt::DynamicOffset;
|
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
use wgt::DynamicOffset;
|
||||||
|
|
||||||
pub const DEFAULT_BIND_GROUPS: usize = 4;
|
pub const DEFAULT_BIND_GROUPS: usize = 4;
|
||||||
type BindGroupMask = u8;
|
type BindGroupMask = u8;
|
||||||
@ -44,12 +44,7 @@ impl<'a> Iterator for FollowUpIter<'a> {
|
|||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
self.iter
|
self.iter
|
||||||
.next()
|
.next()
|
||||||
.and_then(|entry| {
|
.and_then(|entry| Some((entry.actual_value()?, entry.dynamic_offsets.as_slice())))
|
||||||
Some((
|
|
||||||
entry.actual_value()?,
|
|
||||||
entry.dynamic_offsets.as_slice(),
|
|
||||||
))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +146,7 @@ impl Binder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn reset_expectations(&mut self, length: usize) {
|
pub(crate) fn reset_expectations(&mut self, length: usize) {
|
||||||
for entry in self.entries[length ..].iter_mut() {
|
for entry in self.entries[length..].iter_mut() {
|
||||||
entry.expected_layout_id = None;
|
entry.expected_layout_id = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -185,8 +180,8 @@ impl Binder {
|
|||||||
Some((
|
Some((
|
||||||
self.pipeline_layout_id?,
|
self.pipeline_layout_id?,
|
||||||
FollowUpIter {
|
FollowUpIter {
|
||||||
iter: self.entries[index + 1 .. end].iter(),
|
iter: self.entries[index + 1..end].iter(),
|
||||||
}
|
},
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
log::trace!("\t\tskipping above compatible {}", compatible_count);
|
log::trace!("\t\tskipping above compatible {}", compatible_count);
|
||||||
|
@ -5,17 +5,16 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
command::{
|
command::{
|
||||||
bind::{Binder, LayoutChange},
|
bind::{Binder, LayoutChange},
|
||||||
CommandBuffer,
|
CommandBuffer, PhantomSlice,
|
||||||
PhantomSlice,
|
|
||||||
},
|
},
|
||||||
device::all_buffer_stages,
|
device::all_buffer_stages,
|
||||||
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Token},
|
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Token},
|
||||||
id,
|
id,
|
||||||
};
|
};
|
||||||
|
|
||||||
use wgt::{BufferAddress, BufferUsage, DynamicOffset, BIND_BUFFER_ALIGNMENT};
|
|
||||||
use hal::command::CommandBuffer as _;
|
use hal::command::CommandBuffer as _;
|
||||||
use peek_poke::{Peek, PeekPoke, Poke};
|
use peek_poke::{Peek, PeekPoke, Poke};
|
||||||
|
use wgt::{BufferAddress, BufferUsage, DynamicOffset, BIND_BUFFER_ALIGNMENT};
|
||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
@ -90,17 +89,24 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let mut pipeline_state = PipelineState::Required;
|
let mut pipeline_state = PipelineState::Required;
|
||||||
|
|
||||||
let mut peeker = raw_data.as_ptr();
|
let mut peeker = raw_data.as_ptr();
|
||||||
let raw_data_end = unsafe {
|
let raw_data_end = unsafe { raw_data.as_ptr().add(raw_data.len()) };
|
||||||
raw_data.as_ptr().add(raw_data.len())
|
|
||||||
};
|
|
||||||
let mut command = ComputeCommand::Dispatch([0; 3]); // dummy
|
let mut command = ComputeCommand::Dispatch([0; 3]); // dummy
|
||||||
loop {
|
loop {
|
||||||
assert!(unsafe { peeker.add(ComputeCommand::max_size()) } <= raw_data_end);
|
assert!(unsafe { peeker.add(ComputeCommand::max_size()) } <= raw_data_end);
|
||||||
peeker = unsafe { ComputeCommand::peek_from(peeker, &mut command) };
|
peeker = unsafe { ComputeCommand::peek_from(peeker, &mut command) };
|
||||||
match command {
|
match command {
|
||||||
ComputeCommand::SetBindGroup { index, num_dynamic_offsets, bind_group_id, phantom_offsets } => {
|
ComputeCommand::SetBindGroup {
|
||||||
|
index,
|
||||||
|
num_dynamic_offsets,
|
||||||
|
bind_group_id,
|
||||||
|
phantom_offsets,
|
||||||
|
} => {
|
||||||
let (new_peeker, offsets) = unsafe {
|
let (new_peeker, offsets) = unsafe {
|
||||||
phantom_offsets.decode_unaligned(peeker, num_dynamic_offsets as usize, raw_data_end)
|
phantom_offsets.decode_unaligned(
|
||||||
|
peeker,
|
||||||
|
num_dynamic_offsets as usize,
|
||||||
|
raw_data_end,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
peeker = new_peeker;
|
peeker = new_peeker;
|
||||||
|
|
||||||
@ -136,11 +142,14 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
&*texture_guard,
|
&*texture_guard,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some((pipeline_layout_id, follow_ups)) = binder
|
if let Some((pipeline_layout_id, follow_ups)) =
|
||||||
.provide_entry(index as usize, bind_group_id, bind_group, offsets)
|
binder.provide_entry(index as usize, bind_group_id, bind_group, offsets)
|
||||||
{
|
{
|
||||||
let bind_groups = iter::once(bind_group.raw.raw())
|
let bind_groups = iter::once(bind_group.raw.raw()).chain(
|
||||||
.chain(follow_ups.clone().map(|(bg_id, _)| bind_group_guard[bg_id].raw.raw()));
|
follow_ups
|
||||||
|
.clone()
|
||||||
|
.map(|(bg_id, _)| bind_group_guard[bg_id].raw.raw()),
|
||||||
|
);
|
||||||
unsafe {
|
unsafe {
|
||||||
raw.bind_compute_descriptor_sets(
|
raw.bind_compute_descriptor_sets(
|
||||||
&pipeline_layout_guard[pipeline_layout_id].raw,
|
&pipeline_layout_guard[pipeline_layout_id].raw,
|
||||||
@ -156,7 +165,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
}
|
}
|
||||||
ComputeCommand::SetPipeline(pipeline_id) => {
|
ComputeCommand::SetPipeline(pipeline_id) => {
|
||||||
pipeline_state = PipelineState::Set;
|
pipeline_state = PipelineState::Set;
|
||||||
let pipeline = cmb.trackers
|
let pipeline = cmb
|
||||||
|
.trackers
|
||||||
.compute_pipes
|
.compute_pipes
|
||||||
.use_extend(&*pipeline_guard, pipeline_id, (), ())
|
.use_extend(&*pipeline_guard, pipeline_id, (), ())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -169,8 +179,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
if binder.pipeline_layout_id != Some(pipeline.layout_id) {
|
if binder.pipeline_layout_id != Some(pipeline.layout_id) {
|
||||||
let pipeline_layout = &pipeline_layout_guard[pipeline.layout_id];
|
let pipeline_layout = &pipeline_layout_guard[pipeline.layout_id];
|
||||||
binder.pipeline_layout_id = Some(pipeline.layout_id);
|
binder.pipeline_layout_id = Some(pipeline.layout_id);
|
||||||
binder
|
binder.reset_expectations(pipeline_layout.bind_group_layout_ids.len());
|
||||||
.reset_expectations(pipeline_layout.bind_group_layout_ids.len());
|
|
||||||
let mut is_compatible = true;
|
let mut is_compatible = true;
|
||||||
|
|
||||||
for (index, (entry, &bgl_id)) in binder
|
for (index, (entry, &bgl_id)) in binder
|
||||||
@ -200,13 +209,21 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ComputeCommand::Dispatch(groups) => {
|
ComputeCommand::Dispatch(groups) => {
|
||||||
assert_eq!(pipeline_state, PipelineState::Set, "Dispatch error: Pipeline is missing");
|
assert_eq!(
|
||||||
|
pipeline_state,
|
||||||
|
PipelineState::Set,
|
||||||
|
"Dispatch error: Pipeline is missing"
|
||||||
|
);
|
||||||
unsafe {
|
unsafe {
|
||||||
raw.dispatch(groups);
|
raw.dispatch(groups);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ComputeCommand::DispatchIndirect { buffer_id, offset } => {
|
ComputeCommand::DispatchIndirect { buffer_id, offset } => {
|
||||||
assert_eq!(pipeline_state, PipelineState::Set, "Dispatch error: Pipeline is missing");
|
assert_eq!(
|
||||||
|
pipeline_state,
|
||||||
|
PipelineState::Set,
|
||||||
|
"Dispatch error: Pipeline is missing"
|
||||||
|
);
|
||||||
let (src_buffer, src_pending) = cmb.trackers.buffers.use_replace(
|
let (src_buffer, src_pending) = cmb.trackers.buffers.use_replace(
|
||||||
&*buffer_guard,
|
&*buffer_guard,
|
||||||
buffer_id,
|
buffer_id,
|
||||||
@ -219,7 +236,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
raw.pipeline_barrier(
|
raw.pipeline_barrier(
|
||||||
all_buffer_stages() .. all_buffer_stages(),
|
all_buffer_stages()..all_buffer_stages(),
|
||||||
hal::memory::Dependencies::empty(),
|
hal::memory::Dependencies::empty(),
|
||||||
barriers,
|
barriers,
|
||||||
);
|
);
|
||||||
@ -234,15 +251,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
|
|
||||||
pub mod compute_ffi {
|
pub mod compute_ffi {
|
||||||
use super::{
|
use super::{
|
||||||
ComputeCommand,
|
|
||||||
super::{PhantomSlice, RawPass},
|
super::{PhantomSlice, RawPass},
|
||||||
|
ComputeCommand,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{id, RawString};
|
||||||
id,
|
|
||||||
RawString,
|
|
||||||
};
|
|
||||||
use wgt::{BufferAddress, DynamicOffset};
|
|
||||||
use std::{convert::TryInto, slice};
|
use std::{convert::TryInto, slice};
|
||||||
|
use wgt::{BufferAddress, DynamicOffset};
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
@ -264,9 +278,7 @@ use wgt::{BufferAddress, DynamicOffset};
|
|||||||
bind_group_id,
|
bind_group_id,
|
||||||
phantom_offsets: PhantomSlice::default(),
|
phantom_offsets: PhantomSlice::default(),
|
||||||
});
|
});
|
||||||
pass.encode_slice(
|
pass.encode_slice(slice::from_raw_parts(offsets, offset_length));
|
||||||
slice::from_raw_parts(offsets, offset_length),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -293,24 +305,16 @@ use wgt::{BufferAddress, DynamicOffset};
|
|||||||
buffer_id: id::BufferId,
|
buffer_id: id::BufferId,
|
||||||
offset: BufferAddress,
|
offset: BufferAddress,
|
||||||
) {
|
) {
|
||||||
pass.encode(&ComputeCommand::DispatchIndirect {
|
pass.encode(&ComputeCommand::DispatchIndirect { buffer_id, offset });
|
||||||
buffer_id,
|
|
||||||
offset,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_compute_pass_push_debug_group(
|
pub extern "C" fn wgpu_compute_pass_push_debug_group(_pass: &mut RawPass, _label: RawString) {
|
||||||
_pass: &mut RawPass,
|
|
||||||
_label: RawString,
|
|
||||||
) {
|
|
||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_compute_pass_pop_debug_group(
|
pub extern "C" fn wgpu_compute_pass_pop_debug_group(_pass: &mut RawPass) {
|
||||||
_pass: &mut RawPass,
|
|
||||||
) {
|
|
||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,30 +14,17 @@ pub use self::render::*;
|
|||||||
pub use self::transfer::*;
|
pub use self::transfer::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
device::{
|
device::{all_buffer_stages, all_image_stages, MAX_COLOR_TARGETS},
|
||||||
MAX_COLOR_TARGETS,
|
|
||||||
all_buffer_stages,
|
|
||||||
all_image_stages,
|
|
||||||
},
|
|
||||||
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Storage, Token},
|
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Storage, Token},
|
||||||
id,
|
id,
|
||||||
resource::{Buffer, Texture},
|
resource::{Buffer, Texture},
|
||||||
track::TrackerSet,
|
track::TrackerSet,
|
||||||
Features,
|
Features, LifeGuard, Stored,
|
||||||
LifeGuard,
|
|
||||||
Stored,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use peek_poke::PeekPoke;
|
use peek_poke::PeekPoke;
|
||||||
|
|
||||||
use std::{
|
use std::{marker::PhantomData, mem, ptr, slice, thread::ThreadId};
|
||||||
marker::PhantomData,
|
|
||||||
mem,
|
|
||||||
ptr,
|
|
||||||
slice,
|
|
||||||
thread::ThreadId,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PeekPoke)]
|
#[derive(Clone, Copy, Debug, PeekPoke)]
|
||||||
struct PhantomSlice<T>(PhantomData<T>);
|
struct PhantomSlice<T>(PhantomData<T>);
|
||||||
@ -50,7 +37,10 @@ impl<T> Default for PhantomSlice<T> {
|
|||||||
|
|
||||||
impl<T> PhantomSlice<T> {
|
impl<T> PhantomSlice<T> {
|
||||||
unsafe fn decode_unaligned<'a>(
|
unsafe fn decode_unaligned<'a>(
|
||||||
self, pointer: *const u8, count: usize, bound: *const u8
|
self,
|
||||||
|
pointer: *const u8,
|
||||||
|
count: usize,
|
||||||
|
bound: *const u8,
|
||||||
) -> (*const u8, &'a [T]) {
|
) -> (*const u8, &'a [T]) {
|
||||||
let align_offset = pointer.align_offset(mem::align_of::<T>());
|
let align_offset = pointer.align_offset(mem::align_of::<T>());
|
||||||
let aligned = pointer.add(align_offset);
|
let aligned = pointer.add(align_offset);
|
||||||
@ -70,10 +60,7 @@ pub struct RawPass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RawPass {
|
impl RawPass {
|
||||||
fn from_vec<T>(
|
fn from_vec<T>(mut vec: Vec<T>, encoder_id: id::CommandEncoderId) -> Self {
|
||||||
mut vec: Vec<T>,
|
|
||||||
encoder_id: id::CommandEncoderId,
|
|
||||||
) -> Self {
|
|
||||||
let ptr = vec.as_mut_ptr() as *mut u8;
|
let ptr = vec.as_mut_ptr() as *mut u8;
|
||||||
let capacity = vec.capacity() * mem::size_of::<T>();
|
let capacity = vec.capacity() * mem::size_of::<T>();
|
||||||
mem::forget(vec);
|
mem::forget(vec);
|
||||||
@ -89,9 +76,7 @@ impl RawPass {
|
|||||||
///
|
///
|
||||||
/// The last command is provided, yet the encoder
|
/// The last command is provided, yet the encoder
|
||||||
/// is guaranteed to have exactly `C::max_size()` space for it.
|
/// is guaranteed to have exactly `C::max_size()` space for it.
|
||||||
unsafe fn finish<C: peek_poke::Poke>(
|
unsafe fn finish<C: peek_poke::Poke>(&mut self, command: C) {
|
||||||
&mut self, command: C
|
|
||||||
) {
|
|
||||||
self.ensure_extra_size(C::max_size());
|
self.ensure_extra_size(C::max_size());
|
||||||
let extended_end = self.data.add(C::max_size());
|
let extended_end = self.data.add(C::max_size());
|
||||||
let end = command.poke_into(self.data);
|
let end = command.poke_into(self.data);
|
||||||
@ -169,30 +154,26 @@ impl<B: GfxBackend> CommandBuffer<B> {
|
|||||||
debug_assert_eq!(B::VARIANT, base.backend());
|
debug_assert_eq!(B::VARIANT, base.backend());
|
||||||
debug_assert_eq!(B::VARIANT, head.backend());
|
debug_assert_eq!(B::VARIANT, head.backend());
|
||||||
|
|
||||||
let buffer_barriers = base
|
let buffer_barriers = base.buffers.merge_replace(&head.buffers).map(|pending| {
|
||||||
.buffers
|
let buf = &buffer_guard[pending.id];
|
||||||
.merge_replace(&head.buffers)
|
pending.into_hal(buf)
|
||||||
.map(|pending| {
|
});
|
||||||
let buf = &buffer_guard[pending.id];
|
let texture_barriers = base.textures.merge_replace(&head.textures).map(|pending| {
|
||||||
pending.into_hal(buf)
|
let tex = &texture_guard[pending.id];
|
||||||
});
|
pending.into_hal(tex)
|
||||||
let texture_barriers = base
|
});
|
||||||
.textures
|
|
||||||
.merge_replace(&head.textures)
|
|
||||||
.map(|pending| {
|
|
||||||
let tex = &texture_guard[pending.id];
|
|
||||||
pending.into_hal(tex)
|
|
||||||
});
|
|
||||||
base.views.merge_extend(&head.views).unwrap();
|
base.views.merge_extend(&head.views).unwrap();
|
||||||
base.bind_groups.merge_extend(&head.bind_groups).unwrap();
|
base.bind_groups.merge_extend(&head.bind_groups).unwrap();
|
||||||
base.samplers.merge_extend(&head.samplers).unwrap();
|
base.samplers.merge_extend(&head.samplers).unwrap();
|
||||||
base.compute_pipes.merge_extend(&head.compute_pipes).unwrap();
|
base.compute_pipes
|
||||||
|
.merge_extend(&head.compute_pipes)
|
||||||
|
.unwrap();
|
||||||
base.render_pipes.merge_extend(&head.render_pipes).unwrap();
|
base.render_pipes.merge_extend(&head.render_pipes).unwrap();
|
||||||
|
|
||||||
let stages = all_buffer_stages() | all_image_stages();
|
let stages = all_buffer_stages() | all_image_stages();
|
||||||
unsafe {
|
unsafe {
|
||||||
raw.pipeline_barrier(
|
raw.pipeline_barrier(
|
||||||
stages .. stages,
|
stages..stages,
|
||||||
hal::memory::Dependencies::empty(),
|
hal::memory::Dependencies::empty(),
|
||||||
buffer_barriers.chain(texture_barriers),
|
buffer_barriers.chain(texture_barriers),
|
||||||
);
|
);
|
||||||
@ -258,7 +239,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
comb.is_recording = false;
|
comb.is_recording = false;
|
||||||
// stop tracking the swapchain image, if used
|
// stop tracking the swapchain image, if used
|
||||||
if let Some((ref sc_id, _)) = comb.used_swap_chain {
|
if let Some((ref sc_id, _)) = comb.used_swap_chain {
|
||||||
let view_id = swap_chain_guard[sc_id.value].acquired_view_id
|
let view_id = swap_chain_guard[sc_id.value]
|
||||||
|
.acquired_view_id
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("Used swap chain frame has already presented");
|
.expect("Used swap chain frame has already presented");
|
||||||
comb.trackers.views.remove(view_id.value);
|
comb.trackers.views.remove(view_id.value);
|
||||||
|
@ -5,19 +5,12 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
command::{
|
command::{
|
||||||
bind::{Binder, LayoutChange},
|
bind::{Binder, LayoutChange},
|
||||||
PassComponent,
|
PassComponent, PhantomSlice, RawRenderPassColorAttachmentDescriptor,
|
||||||
PhantomSlice,
|
RawRenderPassDepthStencilAttachmentDescriptor, RawRenderTargets,
|
||||||
RawRenderPassColorAttachmentDescriptor,
|
|
||||||
RawRenderPassDepthStencilAttachmentDescriptor,
|
|
||||||
RawRenderTargets,
|
|
||||||
},
|
},
|
||||||
conv,
|
conv,
|
||||||
device::{
|
device::{
|
||||||
FramebufferKey,
|
FramebufferKey, RenderPassContext, RenderPassKey, MAX_COLOR_TARGETS, MAX_VERTEX_BUFFERS,
|
||||||
RenderPassContext,
|
|
||||||
RenderPassKey,
|
|
||||||
MAX_VERTEX_BUFFERS,
|
|
||||||
MAX_COLOR_TARGETS,
|
|
||||||
},
|
},
|
||||||
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Token},
|
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Token},
|
||||||
id,
|
id,
|
||||||
@ -27,31 +20,17 @@ use crate::{
|
|||||||
Stored,
|
Stored,
|
||||||
};
|
};
|
||||||
|
|
||||||
use wgt::{
|
|
||||||
BufferAddress,
|
|
||||||
BufferUsage,
|
|
||||||
Color,
|
|
||||||
DynamicOffset,
|
|
||||||
IndexFormat,
|
|
||||||
InputStepMode,
|
|
||||||
LoadOp,
|
|
||||||
RenderPassColorAttachmentDescriptorBase,
|
|
||||||
RenderPassDepthStencilAttachmentDescriptorBase,
|
|
||||||
TextureUsage,
|
|
||||||
BIND_BUFFER_ALIGNMENT
|
|
||||||
};
|
|
||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
use hal::command::CommandBuffer as _;
|
use hal::command::CommandBuffer as _;
|
||||||
use peek_poke::{Peek, PeekPoke, Poke};
|
use peek_poke::{Peek, PeekPoke, Poke};
|
||||||
|
use wgt::{
|
||||||
|
BufferAddress, BufferUsage, Color, DynamicOffset, IndexFormat, InputStepMode, LoadOp,
|
||||||
|
RenderPassColorAttachmentDescriptorBase, RenderPassDepthStencilAttachmentDescriptorBase,
|
||||||
|
TextureUsage, BIND_BUFFER_ALIGNMENT,
|
||||||
|
};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Borrow,
|
borrow::Borrow, collections::hash_map::Entry, iter, marker::PhantomData, mem, ops::Range, slice,
|
||||||
collections::hash_map::Entry,
|
|
||||||
iter,
|
|
||||||
marker::PhantomData,
|
|
||||||
mem,
|
|
||||||
ops::Range,
|
|
||||||
slice,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type RenderPassColorAttachmentDescriptor =
|
pub type RenderPassColorAttachmentDescriptor =
|
||||||
@ -156,10 +135,10 @@ impl super::RawPass {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
for (color, at) in targets.colors
|
for (color, at) in targets.colors.iter_mut().zip(slice::from_raw_parts(
|
||||||
.iter_mut()
|
desc.color_attachments,
|
||||||
.zip(slice::from_raw_parts(desc.color_attachments, desc.color_attachments_length))
|
desc.color_attachments_length,
|
||||||
{
|
)) {
|
||||||
*color = RawRenderPassColorAttachmentDescriptor {
|
*color = RawRenderPassColorAttachmentDescriptor {
|
||||||
attachment: at.attachment.into_raw(),
|
attachment: at.attachment.into_raw(),
|
||||||
resolve_target: at.resolve_target.map_or(0, |id| id.into_raw()),
|
resolve_target: at.resolve_target.map_or(0, |id| id.into_raw()),
|
||||||
@ -335,25 +314,22 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let (view_guard, _) = hub.texture_views.read(&mut token);
|
let (view_guard, _) = hub.texture_views.read(&mut token);
|
||||||
|
|
||||||
let mut peeker = raw_data.as_ptr();
|
let mut peeker = raw_data.as_ptr();
|
||||||
let raw_data_end = unsafe {
|
let raw_data_end = unsafe { raw_data.as_ptr().add(raw_data.len()) };
|
||||||
raw_data.as_ptr().add(raw_data.len())
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut targets: RawRenderTargets = unsafe { mem::zeroed() };
|
let mut targets: RawRenderTargets = unsafe { mem::zeroed() };
|
||||||
assert!(unsafe { peeker.add(RawRenderTargets::max_size()) <= raw_data_end });
|
assert!(unsafe { peeker.add(RawRenderTargets::max_size()) <= raw_data_end });
|
||||||
peeker = unsafe { RawRenderTargets::peek_from(peeker, &mut targets) };
|
peeker = unsafe { RawRenderTargets::peek_from(peeker, &mut targets) };
|
||||||
|
|
||||||
let color_attachments = targets.colors
|
let color_attachments = targets
|
||||||
|
.colors
|
||||||
.iter()
|
.iter()
|
||||||
.take_while(|at| at.attachment != 0)
|
.take_while(|at| at.attachment != 0)
|
||||||
.map(|at| {
|
.map(|at| RenderPassColorAttachmentDescriptor {
|
||||||
RenderPassColorAttachmentDescriptor {
|
attachment: id::TextureViewId::from_raw(at.attachment).unwrap(),
|
||||||
attachment: id::TextureViewId::from_raw(at.attachment).unwrap(),
|
resolve_target: id::TextureViewId::from_raw(at.resolve_target),
|
||||||
resolve_target: id::TextureViewId::from_raw(at.resolve_target),
|
load_op: at.component.load_op,
|
||||||
load_op: at.component.load_op,
|
store_op: at.component.store_op,
|
||||||
store_op: at.component.store_op,
|
clear_color: at.component.clear_value,
|
||||||
clear_color: at.component.clear_value,
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.collect::<ArrayVec<[_; MAX_COLOR_TARGETS]>>();
|
.collect::<ArrayVec<[_; MAX_COLOR_TARGETS]>>();
|
||||||
let depth_stencil_attachment_body;
|
let depth_stencil_attachment_body;
|
||||||
@ -401,7 +377,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
&'a hal::image::SubresourceRange,
|
&'a hal::image::SubresourceRange,
|
||||||
Option<TextureUsage>,
|
Option<TextureUsage>,
|
||||||
);
|
);
|
||||||
let mut output_attachments = ArrayVec::<[OutputAttachment; MAX_TOTAL_ATTACHMENTS]>::new();
|
let mut output_attachments =
|
||||||
|
ArrayVec::<[OutputAttachment; MAX_TOTAL_ATTACHMENTS]>::new();
|
||||||
|
|
||||||
log::trace!(
|
log::trace!(
|
||||||
"Encoding render pass begin in command buffer {:?}",
|
"Encoding render pass begin in command buffer {:?}",
|
||||||
@ -427,17 +404,19 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Using render pass for transition.
|
// Using render pass for transition.
|
||||||
let consistent_usage = base_trackers.textures.query(
|
let consistent_usage = base_trackers
|
||||||
source_id.value,
|
.textures
|
||||||
view.range.clone(),
|
.query(source_id.value, view.range.clone());
|
||||||
);
|
|
||||||
output_attachments.push((source_id, &view.range, consistent_usage));
|
output_attachments.push((source_id, &view.range, consistent_usage));
|
||||||
|
|
||||||
let old_layout = match consistent_usage {
|
let old_layout = match consistent_usage {
|
||||||
Some(usage) => conv::map_texture_state(
|
Some(usage) => {
|
||||||
usage,
|
conv::map_texture_state(
|
||||||
hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL,
|
usage,
|
||||||
).1,
|
hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL,
|
||||||
|
)
|
||||||
|
.1
|
||||||
|
}
|
||||||
None => hal::image::Layout::DepthStencilAttachmentOptimal,
|
None => hal::image::Layout::DepthStencilAttachmentOptimal,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -449,7 +428,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
at.stencil_load_op,
|
at.stencil_load_op,
|
||||||
at.stencil_store_op,
|
at.stencil_store_op,
|
||||||
),
|
),
|
||||||
layouts: old_layout .. hal::image::Layout::DepthStencilAttachmentOptimal,
|
layouts: old_layout..hal::image::Layout::DepthStencilAttachmentOptimal,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
@ -469,25 +448,25 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
view.samples, sample_count,
|
view.samples, sample_count,
|
||||||
"All attachments must have the same sample_count"
|
"All attachments must have the same sample_count"
|
||||||
);
|
);
|
||||||
let first_use = trackers.views.init(
|
let first_use = trackers
|
||||||
at.attachment,
|
.views
|
||||||
view.life_guard.add_ref(),
|
.init(at.attachment, view.life_guard.add_ref(), PhantomData)
|
||||||
PhantomData,
|
.is_ok();
|
||||||
).is_ok();
|
|
||||||
|
|
||||||
let layouts = match view.inner {
|
let layouts = match view.inner {
|
||||||
TextureViewInner::Native { ref source_id, .. } => {
|
TextureViewInner::Native { ref source_id, .. } => {
|
||||||
let consistent_usage = base_trackers.textures.query(
|
let consistent_usage = base_trackers
|
||||||
source_id.value,
|
.textures
|
||||||
view.range.clone(),
|
.query(source_id.value, view.range.clone());
|
||||||
);
|
|
||||||
output_attachments.push((source_id, &view.range, consistent_usage));
|
output_attachments.push((source_id, &view.range, consistent_usage));
|
||||||
|
|
||||||
let old_layout = match consistent_usage {
|
let old_layout = match consistent_usage {
|
||||||
Some(usage) => conv::map_texture_state(usage, hal::format::Aspects::COLOR).1,
|
Some(usage) => {
|
||||||
|
conv::map_texture_state(usage, hal::format::Aspects::COLOR).1
|
||||||
|
}
|
||||||
None => hal::image::Layout::ColorAttachmentOptimal,
|
None => hal::image::Layout::ColorAttachmentOptimal,
|
||||||
};
|
};
|
||||||
old_layout .. hal::image::Layout::ColorAttachmentOptimal
|
old_layout..hal::image::Layout::ColorAttachmentOptimal
|
||||||
}
|
}
|
||||||
TextureViewInner::SwapChain { ref source_id, .. } => {
|
TextureViewInner::SwapChain { ref source_id, .. } => {
|
||||||
if let Some((ref sc_id, _)) = cmb.used_swap_chain {
|
if let Some((ref sc_id, _)) = cmb.used_swap_chain {
|
||||||
@ -503,7 +482,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
} else {
|
} else {
|
||||||
end
|
end
|
||||||
};
|
};
|
||||||
start .. end
|
start..end
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -516,35 +495,32 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for resolve_target in color_attachments
|
for resolve_target in color_attachments.iter().flat_map(|at| at.resolve_target) {
|
||||||
.iter()
|
|
||||||
.flat_map(|at| at.resolve_target)
|
|
||||||
{
|
|
||||||
let view = &view_guard[resolve_target];
|
let view = &view_guard[resolve_target];
|
||||||
assert_eq!(extent, Some(view.extent));
|
assert_eq!(extent, Some(view.extent));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
view.samples, 1,
|
view.samples, 1,
|
||||||
"All resolve_targets must have a sample_count of 1"
|
"All resolve_targets must have a sample_count of 1"
|
||||||
);
|
);
|
||||||
let first_use = trackers.views.init(
|
let first_use = trackers
|
||||||
resolve_target,
|
.views
|
||||||
view.life_guard.add_ref(),
|
.init(resolve_target, view.life_guard.add_ref(), PhantomData)
|
||||||
PhantomData,
|
.is_ok();
|
||||||
).is_ok();
|
|
||||||
|
|
||||||
let layouts = match view.inner {
|
let layouts = match view.inner {
|
||||||
TextureViewInner::Native { ref source_id, .. } => {
|
TextureViewInner::Native { ref source_id, .. } => {
|
||||||
let consistent_usage = base_trackers.textures.query(
|
let consistent_usage = base_trackers
|
||||||
source_id.value,
|
.textures
|
||||||
view.range.clone(),
|
.query(source_id.value, view.range.clone());
|
||||||
);
|
|
||||||
output_attachments.push((source_id, &view.range, consistent_usage));
|
output_attachments.push((source_id, &view.range, consistent_usage));
|
||||||
|
|
||||||
let old_layout = match consistent_usage {
|
let old_layout = match consistent_usage {
|
||||||
Some(usage) => conv::map_texture_state(usage, hal::format::Aspects::COLOR).1,
|
Some(usage) => {
|
||||||
|
conv::map_texture_state(usage, hal::format::Aspects::COLOR).1
|
||||||
|
}
|
||||||
None => hal::image::Layout::ColorAttachmentOptimal,
|
None => hal::image::Layout::ColorAttachmentOptimal,
|
||||||
};
|
};
|
||||||
old_layout .. hal::image::Layout::ColorAttachmentOptimal
|
old_layout..hal::image::Layout::ColorAttachmentOptimal
|
||||||
}
|
}
|
||||||
TextureViewInner::SwapChain { ref source_id, .. } => {
|
TextureViewInner::SwapChain { ref source_id, .. } => {
|
||||||
if let Some((ref sc_id, _)) = cmb.used_swap_chain {
|
if let Some((ref sc_id, _)) = cmb.used_swap_chain {
|
||||||
@ -560,7 +536,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
} else {
|
} else {
|
||||||
end
|
end
|
||||||
};
|
};
|
||||||
start .. end
|
start..end
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -650,7 +626,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let subpass = hal::pass::SubpassDesc {
|
let subpass = hal::pass::SubpassDesc {
|
||||||
colors: &color_ids[.. color_attachments.len()],
|
colors: &color_ids[..color_attachments.len()],
|
||||||
resolves: &resolve_ids,
|
resolves: &resolve_ids,
|
||||||
depth_stencil: depth_stencil_attachment.map(|_| &depth_id),
|
depth_stencil: depth_stencil_attachment.map(|_| &depth_id),
|
||||||
inputs: &[],
|
inputs: &[],
|
||||||
@ -791,7 +767,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
0,
|
0,
|
||||||
iter::once(hal::pso::Viewport {
|
iter::once(hal::pso::Viewport {
|
||||||
rect,
|
rect,
|
||||||
depth: 0.0 .. 1.0,
|
depth: 0.0..1.0,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -838,9 +814,18 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
assert!(unsafe { peeker.add(RenderCommand::max_size()) } <= raw_data_end);
|
assert!(unsafe { peeker.add(RenderCommand::max_size()) } <= raw_data_end);
|
||||||
peeker = unsafe { RenderCommand::peek_from(peeker, &mut command) };
|
peeker = unsafe { RenderCommand::peek_from(peeker, &mut command) };
|
||||||
match command {
|
match command {
|
||||||
RenderCommand::SetBindGroup { index, num_dynamic_offsets, bind_group_id, phantom_offsets } => {
|
RenderCommand::SetBindGroup {
|
||||||
|
index,
|
||||||
|
num_dynamic_offsets,
|
||||||
|
bind_group_id,
|
||||||
|
phantom_offsets,
|
||||||
|
} => {
|
||||||
let (new_peeker, offsets) = unsafe {
|
let (new_peeker, offsets) = unsafe {
|
||||||
phantom_offsets.decode_unaligned(peeker, num_dynamic_offsets as usize, raw_data_end)
|
phantom_offsets.decode_unaligned(
|
||||||
|
peeker,
|
||||||
|
num_dynamic_offsets as usize,
|
||||||
|
raw_data_end,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
peeker = new_peeker;
|
peeker = new_peeker;
|
||||||
|
|
||||||
@ -864,11 +849,17 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
|
|
||||||
trackers.merge_extend(&bind_group.used);
|
trackers.merge_extend(&bind_group.used);
|
||||||
|
|
||||||
if let Some((pipeline_layout_id, follow_ups)) = state.binder
|
if let Some((pipeline_layout_id, follow_ups)) = state.binder.provide_entry(
|
||||||
.provide_entry(index as usize, bind_group_id, bind_group, offsets)
|
index as usize,
|
||||||
{
|
bind_group_id,
|
||||||
let bind_groups = iter::once(bind_group.raw.raw())
|
bind_group,
|
||||||
.chain(follow_ups.clone().map(|(bg_id, _)| bind_group_guard[bg_id].raw.raw()));
|
offsets,
|
||||||
|
) {
|
||||||
|
let bind_groups = iter::once(bind_group.raw.raw()).chain(
|
||||||
|
follow_ups
|
||||||
|
.clone()
|
||||||
|
.map(|(bg_id, _)| bind_group_guard[bg_id].raw.raw()),
|
||||||
|
);
|
||||||
unsafe {
|
unsafe {
|
||||||
raw.bind_graphics_descriptor_sets(
|
raw.bind_graphics_descriptor_sets(
|
||||||
&&pipeline_layout_guard[pipeline_layout_id].raw,
|
&&pipeline_layout_guard[pipeline_layout_id].raw,
|
||||||
@ -877,7 +868,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
offsets
|
offsets
|
||||||
.iter()
|
.iter()
|
||||||
.chain(follow_ups.flat_map(|(_, offsets)| offsets))
|
.chain(follow_ups.flat_map(|(_, offsets)| offsets))
|
||||||
.cloned()
|
.cloned(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -898,9 +889,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
"The render pipeline and renderpass have mismatching sample_count"
|
"The render pipeline and renderpass have mismatching sample_count"
|
||||||
);
|
);
|
||||||
|
|
||||||
state.blend_color
|
state
|
||||||
|
.blend_color
|
||||||
.require(pipeline.flags.contains(PipelineFlags::BLEND_COLOR));
|
.require(pipeline.flags.contains(PipelineFlags::BLEND_COLOR));
|
||||||
state.stencil_reference
|
state
|
||||||
|
.stencil_reference
|
||||||
.require(pipeline.flags.contains(PipelineFlags::STENCIL_REFERENCE));
|
.require(pipeline.flags.contains(PipelineFlags::STENCIL_REFERENCE));
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -911,7 +904,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
if state.binder.pipeline_layout_id != Some(pipeline.layout_id) {
|
if state.binder.pipeline_layout_id != Some(pipeline.layout_id) {
|
||||||
let pipeline_layout = &pipeline_layout_guard[pipeline.layout_id];
|
let pipeline_layout = &pipeline_layout_guard[pipeline.layout_id];
|
||||||
state.binder.pipeline_layout_id = Some(pipeline.layout_id);
|
state.binder.pipeline_layout_id = Some(pipeline.layout_id);
|
||||||
state.binder
|
state
|
||||||
|
.binder
|
||||||
.reset_expectations(pipeline_layout.bind_group_layout_ids.len());
|
.reset_expectations(pipeline_layout.bind_group_layout_ids.len());
|
||||||
let mut is_compatible = true;
|
let mut is_compatible = true;
|
||||||
|
|
||||||
@ -968,30 +962,35 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Update vertex buffer limits
|
// Update vertex buffer limits
|
||||||
for (vbs, &(stride, rate)) in state
|
for (vbs, &(stride, rate)) in
|
||||||
.vertex
|
state.vertex.inputs.iter_mut().zip(&pipeline.vertex_strides)
|
||||||
.inputs
|
|
||||||
.iter_mut()
|
|
||||||
.zip(&pipeline.vertex_strides)
|
|
||||||
{
|
{
|
||||||
vbs.stride = stride;
|
vbs.stride = stride;
|
||||||
vbs.rate = rate;
|
vbs.rate = rate;
|
||||||
}
|
}
|
||||||
for vbs in state.vertex.inputs[pipeline.vertex_strides.len() ..].iter_mut() {
|
for vbs in state.vertex.inputs[pipeline.vertex_strides.len()..].iter_mut() {
|
||||||
vbs.stride = 0;
|
vbs.stride = 0;
|
||||||
vbs.rate = InputStepMode::Vertex;
|
vbs.rate = InputStepMode::Vertex;
|
||||||
}
|
}
|
||||||
state.vertex.update_limits();
|
state.vertex.update_limits();
|
||||||
}
|
}
|
||||||
RenderCommand::SetIndexBuffer { buffer_id, offset, size } => {
|
RenderCommand::SetIndexBuffer {
|
||||||
|
buffer_id,
|
||||||
|
offset,
|
||||||
|
size,
|
||||||
|
} => {
|
||||||
let buffer = trackers
|
let buffer = trackers
|
||||||
.buffers
|
.buffers
|
||||||
.use_extend(&*buffer_guard, buffer_id, (), BufferUsage::INDEX)
|
.use_extend(&*buffer_guard, buffer_id, (), BufferUsage::INDEX)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(buffer.usage.contains(BufferUsage::INDEX));
|
assert!(buffer.usage.contains(BufferUsage::INDEX));
|
||||||
|
|
||||||
let end = if size != 0 { offset + size } else { buffer.size };
|
let end = if size != 0 {
|
||||||
state.index.bound_buffer_view = Some((buffer_id, offset .. end));
|
offset + size
|
||||||
|
} else {
|
||||||
|
buffer.size
|
||||||
|
};
|
||||||
|
state.index.bound_buffer_view = Some((buffer_id, offset..end));
|
||||||
state.index.update_limit();
|
state.index.update_limit();
|
||||||
|
|
||||||
let view = hal::buffer::IndexBufferView {
|
let view = hal::buffer::IndexBufferView {
|
||||||
@ -1007,7 +1006,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
raw.bind_index_buffer(view);
|
raw.bind_index_buffer(view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RenderCommand::SetVertexBuffer { slot, buffer_id, offset, size } => {
|
RenderCommand::SetVertexBuffer {
|
||||||
|
slot,
|
||||||
|
buffer_id,
|
||||||
|
offset,
|
||||||
|
size,
|
||||||
|
} => {
|
||||||
let buffer = trackers
|
let buffer = trackers
|
||||||
.buffers
|
.buffers
|
||||||
.use_extend(&*buffer_guard, buffer_id, (), BufferUsage::VERTEX)
|
.use_extend(&*buffer_guard, buffer_id, (), BufferUsage::VERTEX)
|
||||||
@ -1040,7 +1044,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
raw.set_stencil_reference(hal::pso::Face::all(), value);
|
raw.set_stencil_reference(hal::pso::Face::all(), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RenderCommand::SetViewport { ref rect, depth_min, depth_max } => {
|
RenderCommand::SetViewport {
|
||||||
|
ref rect,
|
||||||
|
depth_min,
|
||||||
|
depth_max,
|
||||||
|
} => {
|
||||||
use std::{convert::TryFrom, i16};
|
use std::{convert::TryFrom, i16};
|
||||||
let r = hal::pso::Rect {
|
let r = hal::pso::Rect {
|
||||||
x: i16::try_from(rect.x.round() as i64).unwrap_or(0),
|
x: i16::try_from(rect.x.round() as i64).unwrap_or(0),
|
||||||
@ -1053,7 +1061,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
0,
|
0,
|
||||||
iter::once(hal::pso::Viewport {
|
iter::once(hal::pso::Viewport {
|
||||||
rect: r,
|
rect: r,
|
||||||
depth: depth_min .. depth_max,
|
depth: depth_min..depth_max,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1067,13 +1075,15 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
h: i16::try_from(rect.h).unwrap_or(i16::MAX),
|
h: i16::try_from(rect.h).unwrap_or(i16::MAX),
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
raw.set_scissors(
|
raw.set_scissors(0, iter::once(r));
|
||||||
0,
|
|
||||||
iter::once(r),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RenderCommand::Draw { vertex_count, instance_count, first_vertex, first_instance } => {
|
RenderCommand::Draw {
|
||||||
|
vertex_count,
|
||||||
|
instance_count,
|
||||||
|
first_vertex,
|
||||||
|
first_instance,
|
||||||
|
} => {
|
||||||
state.is_ready().unwrap();
|
state.is_ready().unwrap();
|
||||||
assert!(
|
assert!(
|
||||||
first_vertex + vertex_count <= state.vertex.vertex_limit,
|
first_vertex + vertex_count <= state.vertex.vertex_limit,
|
||||||
@ -1086,12 +1096,18 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
raw.draw(
|
raw.draw(
|
||||||
first_vertex .. first_vertex + vertex_count,
|
first_vertex..first_vertex + vertex_count,
|
||||||
first_instance .. first_instance + instance_count,
|
first_instance..first_instance + instance_count,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RenderCommand::DrawIndexed { index_count, instance_count, first_index, base_vertex, first_instance } => {
|
RenderCommand::DrawIndexed {
|
||||||
|
index_count,
|
||||||
|
instance_count,
|
||||||
|
first_index,
|
||||||
|
base_vertex,
|
||||||
|
first_instance,
|
||||||
|
} => {
|
||||||
state.is_ready().unwrap();
|
state.is_ready().unwrap();
|
||||||
|
|
||||||
//TODO: validate that base_vertex + max_index() is within the provided range
|
//TODO: validate that base_vertex + max_index() is within the provided range
|
||||||
@ -1106,9 +1122,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
raw.draw_indexed(
|
raw.draw_indexed(
|
||||||
first_index .. first_index + index_count,
|
first_index..first_index + index_count,
|
||||||
base_vertex,
|
base_vertex,
|
||||||
first_instance .. first_instance + instance_count,
|
first_instance..first_instance + instance_count,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1117,12 +1133,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
|
|
||||||
let buffer = trackers
|
let buffer = trackers
|
||||||
.buffers
|
.buffers
|
||||||
.use_extend(
|
.use_extend(&*buffer_guard, buffer_id, (), BufferUsage::INDIRECT)
|
||||||
&*buffer_guard,
|
|
||||||
buffer_id,
|
|
||||||
(),
|
|
||||||
BufferUsage::INDIRECT,
|
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(buffer.usage.contains(BufferUsage::INDIRECT));
|
assert!(buffer.usage.contains(BufferUsage::INDIRECT));
|
||||||
|
|
||||||
@ -1135,12 +1146,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
|
|
||||||
let buffer = trackers
|
let buffer = trackers
|
||||||
.buffers
|
.buffers
|
||||||
.use_extend(
|
.use_extend(&*buffer_guard, buffer_id, (), BufferUsage::INDIRECT)
|
||||||
&*buffer_guard,
|
|
||||||
buffer_id,
|
|
||||||
(),
|
|
||||||
BufferUsage::INDIRECT,
|
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(buffer.usage.contains(BufferUsage::INDIRECT));
|
assert!(buffer.usage.contains(BufferUsage::INDIRECT));
|
||||||
|
|
||||||
@ -1169,15 +1175,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
|
|
||||||
pub mod render_ffi {
|
pub mod render_ffi {
|
||||||
use super::{
|
use super::{
|
||||||
RenderCommand,
|
|
||||||
super::{PhantomSlice, RawPass, Rect},
|
super::{PhantomSlice, RawPass, Rect},
|
||||||
|
RenderCommand,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{id, RawString};
|
||||||
id,
|
|
||||||
RawString,
|
|
||||||
};
|
|
||||||
use wgt::{BufferAddress, Color, DynamicOffset};
|
|
||||||
use std::{convert::TryInto, slice};
|
use std::{convert::TryInto, slice};
|
||||||
|
use wgt::{BufferAddress, Color, DynamicOffset};
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
@ -1199,9 +1202,7 @@ pub mod render_ffi {
|
|||||||
bind_group_id,
|
bind_group_id,
|
||||||
phantom_offsets: PhantomSlice::default(),
|
phantom_offsets: PhantomSlice::default(),
|
||||||
});
|
});
|
||||||
pass.encode_slice(
|
pass.encode_slice(slice::from_raw_parts(offsets, offset_length));
|
||||||
slice::from_raw_parts(offsets, offset_length),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -1243,10 +1244,7 @@ pub mod render_ffi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wgpu_render_pass_set_blend_color(
|
pub unsafe extern "C" fn wgpu_render_pass_set_blend_color(pass: &mut RawPass, color: &Color) {
|
||||||
pass: &mut RawPass,
|
|
||||||
color: &Color,
|
|
||||||
) {
|
|
||||||
pass.encode(&RenderCommand::SetBlendColor(*color));
|
pass.encode(&RenderCommand::SetBlendColor(*color));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1326,10 +1324,7 @@ pub mod render_ffi {
|
|||||||
buffer_id: id::BufferId,
|
buffer_id: id::BufferId,
|
||||||
offset: BufferAddress,
|
offset: BufferAddress,
|
||||||
) {
|
) {
|
||||||
pass.encode(&RenderCommand::DrawIndirect {
|
pass.encode(&RenderCommand::DrawIndirect { buffer_id, offset });
|
||||||
buffer_id,
|
|
||||||
offset,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -1338,10 +1333,7 @@ pub mod render_ffi {
|
|||||||
buffer_id: id::BufferId,
|
buffer_id: id::BufferId,
|
||||||
offset: BufferAddress,
|
offset: BufferAddress,
|
||||||
) {
|
) {
|
||||||
pass.encode(&RenderCommand::DrawIndexedIndirect {
|
pass.encode(&RenderCommand::DrawIndexedIndirect { buffer_id, offset });
|
||||||
buffer_id,
|
|
||||||
offset,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -1354,25 +1346,17 @@ pub mod render_ffi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_render_pass_push_debug_group(
|
pub extern "C" fn wgpu_render_pass_push_debug_group(_pass: &mut RawPass, _label: RawString) {
|
||||||
_pass: &mut RawPass,
|
|
||||||
_label: RawString,
|
|
||||||
) {
|
|
||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_render_pass_pop_debug_group(
|
pub extern "C" fn wgpu_render_pass_pop_debug_group(_pass: &mut RawPass) {
|
||||||
_pass: &mut RawPass,
|
|
||||||
) {
|
|
||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_render_pass_insert_debug_marker(
|
pub extern "C" fn wgpu_render_pass_insert_debug_marker(_pass: &mut RawPass, _label: RawString) {
|
||||||
_pass: &mut RawPass,
|
|
||||||
_label: RawString,
|
|
||||||
) {
|
|
||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,8 @@ use crate::{
|
|||||||
id::{BufferId, CommandEncoderId, TextureId},
|
id::{BufferId, CommandEncoderId, TextureId},
|
||||||
};
|
};
|
||||||
|
|
||||||
use wgt::{BufferAddress, BufferUsage, Extent3d, Origin3d, TextureUsage};
|
|
||||||
use hal::command::CommandBuffer as _;
|
use hal::command::CommandBuffer as _;
|
||||||
|
use wgt::{BufferAddress, BufferUsage, Extent3d, Origin3d, TextureUsage};
|
||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
@ -47,8 +47,8 @@ impl TextureCopyView {
|
|||||||
{
|
{
|
||||||
hal::image::SubresourceRange {
|
hal::image::SubresourceRange {
|
||||||
aspects,
|
aspects,
|
||||||
levels: level .. level + 1,
|
levels: level..level + 1,
|
||||||
layers: layer .. layer + 1,
|
layers: layer..layer + 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ impl TextureCopyView {
|
|||||||
hal::image::SubresourceLayers {
|
hal::image::SubresourceLayers {
|
||||||
aspects,
|
aspects,
|
||||||
level: self.mip_level as hal::image::Level,
|
level: self.mip_level as hal::image::Level,
|
||||||
layers: layer .. layer + 1,
|
layers: layer..layer + 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,7 +113,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let cmb_raw = cmb.raw.last_mut().unwrap();
|
let cmb_raw = cmb.raw.last_mut().unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
cmb_raw.pipeline_barrier(
|
cmb_raw.pipeline_barrier(
|
||||||
all_buffer_stages() .. all_buffer_stages(),
|
all_buffer_stages()..all_buffer_stages(),
|
||||||
hal::memory::Dependencies::empty(),
|
hal::memory::Dependencies::empty(),
|
||||||
barriers,
|
barriers,
|
||||||
);
|
);
|
||||||
@ -172,7 +172,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let stages = all_buffer_stages() | all_image_stages();
|
let stages = all_buffer_stages() | all_image_stages();
|
||||||
unsafe {
|
unsafe {
|
||||||
cmb_raw.pipeline_barrier(
|
cmb_raw.pipeline_barrier(
|
||||||
stages .. stages,
|
stages..stages,
|
||||||
hal::memory::Dependencies::empty(),
|
hal::memory::Dependencies::empty(),
|
||||||
src_barriers.chain(dst_barriers),
|
src_barriers.chain(dst_barriers),
|
||||||
);
|
);
|
||||||
@ -236,7 +236,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let stages = all_buffer_stages() | all_image_stages();
|
let stages = all_buffer_stages() | all_image_stages();
|
||||||
unsafe {
|
unsafe {
|
||||||
cmb_raw.pipeline_barrier(
|
cmb_raw.pipeline_barrier(
|
||||||
stages .. stages,
|
stages..stages,
|
||||||
hal::memory::Dependencies::empty(),
|
hal::memory::Dependencies::empty(),
|
||||||
src_barriers.chain(dst_barrier),
|
src_barriers.chain(dst_barrier),
|
||||||
);
|
);
|
||||||
@ -297,7 +297,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let cmb_raw = cmb.raw.last_mut().unwrap();
|
let cmb_raw = cmb.raw.last_mut().unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
cmb_raw.pipeline_barrier(
|
cmb_raw.pipeline_barrier(
|
||||||
all_image_stages() .. all_image_stages(),
|
all_image_stages()..all_image_stages(),
|
||||||
hal::memory::Dependencies::empty(),
|
hal::memory::Dependencies::empty(),
|
||||||
barriers,
|
barriers,
|
||||||
);
|
);
|
||||||
|
@ -4,32 +4,16 @@
|
|||||||
|
|
||||||
use crate::{binding_model, Features};
|
use crate::{binding_model, Features};
|
||||||
use wgt::{
|
use wgt::{
|
||||||
BlendDescriptor,
|
BlendDescriptor, BlendFactor, Color, ColorStateDescriptor, ColorWrite, CompareFunction,
|
||||||
BlendFactor,
|
CullMode, DepthStencilStateDescriptor, Extent3d, FrontFace, IndexFormat, Origin3d,
|
||||||
Color,
|
PrimitiveTopology, RasterizationStateDescriptor, StencilOperation, StencilStateFaceDescriptor,
|
||||||
ColorStateDescriptor,
|
TextureFormat, VertexFormat,
|
||||||
ColorWrite,
|
|
||||||
CompareFunction,
|
|
||||||
CullMode,
|
|
||||||
DepthStencilStateDescriptor,
|
|
||||||
Extent3d,
|
|
||||||
FrontFace,
|
|
||||||
IndexFormat,
|
|
||||||
Origin3d,
|
|
||||||
PrimitiveTopology,
|
|
||||||
RasterizationStateDescriptor,
|
|
||||||
StencilOperation,
|
|
||||||
StencilStateFaceDescriptor,
|
|
||||||
TextureFormat,
|
|
||||||
VertexFormat,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn map_buffer_usage(
|
pub fn map_buffer_usage(usage: wgt::BufferUsage) -> (hal::buffer::Usage, hal::memory::Properties) {
|
||||||
usage: wgt::BufferUsage,
|
|
||||||
) -> (hal::buffer::Usage, hal::memory::Properties) {
|
|
||||||
use wgt::BufferUsage as W;
|
|
||||||
use hal::buffer::Usage as U;
|
use hal::buffer::Usage as U;
|
||||||
use hal::memory::Properties as P;
|
use hal::memory::Properties as P;
|
||||||
|
use wgt::BufferUsage as W;
|
||||||
|
|
||||||
let mut hal_memory = P::empty();
|
let mut hal_memory = P::empty();
|
||||||
if usage.contains(W::MAP_READ) {
|
if usage.contains(W::MAP_READ) {
|
||||||
@ -69,8 +53,8 @@ pub fn map_texture_usage(
|
|||||||
usage: wgt::TextureUsage,
|
usage: wgt::TextureUsage,
|
||||||
aspects: hal::format::Aspects,
|
aspects: hal::format::Aspects,
|
||||||
) -> hal::image::Usage {
|
) -> hal::image::Usage {
|
||||||
use wgt::TextureUsage as W;
|
|
||||||
use hal::image::Usage as U;
|
use hal::image::Usage as U;
|
||||||
|
use wgt::TextureUsage as W;
|
||||||
|
|
||||||
let mut value = U::empty();
|
let mut value = U::empty();
|
||||||
if usage.contains(W::COPY_SRC) {
|
if usage.contains(W::COPY_SRC) {
|
||||||
@ -97,73 +81,46 @@ pub fn map_texture_usage(
|
|||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_binding_type(
|
pub fn map_binding_type(binding: &binding_model::BindGroupLayoutEntry) -> hal::pso::DescriptorType {
|
||||||
binding: &binding_model::BindGroupLayoutEntry,
|
|
||||||
) -> hal::pso::DescriptorType {
|
|
||||||
use crate::binding_model::BindingType as Bt;
|
use crate::binding_model::BindingType as Bt;
|
||||||
use hal::pso;
|
use hal::pso;
|
||||||
match binding.ty {
|
match binding.ty {
|
||||||
Bt::UniformBuffer => {
|
Bt::UniformBuffer => pso::DescriptorType::Buffer {
|
||||||
pso::DescriptorType::Buffer {
|
ty: pso::BufferDescriptorType::Uniform,
|
||||||
ty: pso::BufferDescriptorType::Uniform,
|
format: pso::BufferDescriptorFormat::Structured {
|
||||||
format: pso::BufferDescriptorFormat::Structured {
|
dynamic_offset: binding.has_dynamic_offset,
|
||||||
dynamic_offset: binding.has_dynamic_offset,
|
},
|
||||||
},
|
},
|
||||||
}
|
Bt::StorageBuffer => pso::DescriptorType::Buffer {
|
||||||
}
|
ty: pso::BufferDescriptorType::Storage { read_only: false },
|
||||||
Bt::StorageBuffer => {
|
format: pso::BufferDescriptorFormat::Structured {
|
||||||
pso::DescriptorType::Buffer {
|
dynamic_offset: binding.has_dynamic_offset,
|
||||||
ty: pso::BufferDescriptorType::Storage {
|
},
|
||||||
read_only: false,
|
},
|
||||||
},
|
Bt::ReadonlyStorageBuffer => pso::DescriptorType::Buffer {
|
||||||
format: pso::BufferDescriptorFormat::Structured {
|
ty: pso::BufferDescriptorType::Storage { read_only: false },
|
||||||
dynamic_offset: binding.has_dynamic_offset,
|
format: pso::BufferDescriptorFormat::Structured {
|
||||||
},
|
dynamic_offset: binding.has_dynamic_offset,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
Bt::ReadonlyStorageBuffer => {
|
Bt::Sampler | Bt::ComparisonSampler => pso::DescriptorType::Sampler,
|
||||||
pso::DescriptorType::Buffer {
|
Bt::SampledTexture => pso::DescriptorType::Image {
|
||||||
ty: pso::BufferDescriptorType::Storage {
|
ty: pso::ImageDescriptorType::Sampled {
|
||||||
read_only: false,
|
with_sampler: false,
|
||||||
},
|
},
|
||||||
format: pso::BufferDescriptorFormat::Structured {
|
},
|
||||||
dynamic_offset: binding.has_dynamic_offset,
|
Bt::ReadonlyStorageTexture => pso::DescriptorType::Image {
|
||||||
},
|
ty: pso::ImageDescriptorType::Storage { read_only: false },
|
||||||
}
|
},
|
||||||
}
|
Bt::WriteonlyStorageTexture => pso::DescriptorType::Image {
|
||||||
Bt::Sampler |
|
ty: pso::ImageDescriptorType::Storage { read_only: true },
|
||||||
Bt::ComparisonSampler => {
|
},
|
||||||
pso::DescriptorType::Sampler
|
|
||||||
}
|
|
||||||
Bt::SampledTexture => {
|
|
||||||
pso::DescriptorType::Image {
|
|
||||||
ty: pso::ImageDescriptorType::Sampled {
|
|
||||||
with_sampler: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Bt::ReadonlyStorageTexture => {
|
|
||||||
pso::DescriptorType::Image {
|
|
||||||
ty: pso::ImageDescriptorType::Storage {
|
|
||||||
read_only: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Bt::WriteonlyStorageTexture => {
|
|
||||||
pso::DescriptorType::Image {
|
|
||||||
ty: pso::ImageDescriptorType::Storage {
|
|
||||||
read_only: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_shader_stage_flags(
|
pub fn map_shader_stage_flags(shader_stage_flags: wgt::ShaderStage) -> hal::pso::ShaderStageFlags {
|
||||||
shader_stage_flags: wgt::ShaderStage,
|
|
||||||
) -> hal::pso::ShaderStageFlags {
|
|
||||||
use wgt::ShaderStage as Ss;
|
|
||||||
use hal::pso::ShaderStageFlags as H;
|
use hal::pso::ShaderStageFlags as H;
|
||||||
|
use wgt::ShaderStage as Ss;
|
||||||
|
|
||||||
let mut value = H::empty();
|
let mut value = H::empty();
|
||||||
if shader_stage_flags.contains(Ss::VERTEX) {
|
if shader_stage_flags.contains(Ss::VERTEX) {
|
||||||
@ -194,11 +151,9 @@ pub fn map_extent(extent: Extent3d) -> hal::image::Extent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_primitive_topology(
|
pub fn map_primitive_topology(primitive_topology: PrimitiveTopology) -> hal::pso::Primitive {
|
||||||
primitive_topology: PrimitiveTopology,
|
|
||||||
) -> hal::pso::Primitive {
|
|
||||||
use wgt::PrimitiveTopology as Pt;
|
|
||||||
use hal::pso::Primitive as H;
|
use hal::pso::Primitive as H;
|
||||||
|
use wgt::PrimitiveTopology as Pt;
|
||||||
match primitive_topology {
|
match primitive_topology {
|
||||||
Pt::PointList => H::PointList,
|
Pt::PointList => H::PointList,
|
||||||
Pt::LineList => H::LineList,
|
Pt::LineList => H::LineList,
|
||||||
@ -208,9 +163,7 @@ pub fn map_primitive_topology(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_color_state_descriptor(
|
pub fn map_color_state_descriptor(desc: &ColorStateDescriptor) -> hal::pso::ColorBlendDesc {
|
||||||
desc: &ColorStateDescriptor,
|
|
||||||
) -> hal::pso::ColorBlendDesc {
|
|
||||||
let color_mask = desc.write_mask;
|
let color_mask = desc.write_mask;
|
||||||
let blend_state = if desc.color_blend != BlendDescriptor::REPLACE
|
let blend_state = if desc.color_blend != BlendDescriptor::REPLACE
|
||||||
|| desc.alpha_blend != BlendDescriptor::REPLACE
|
|| desc.alpha_blend != BlendDescriptor::REPLACE
|
||||||
@ -229,8 +182,8 @@ pub fn map_color_state_descriptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn map_color_write_flags(flags: ColorWrite) -> hal::pso::ColorMask {
|
fn map_color_write_flags(flags: ColorWrite) -> hal::pso::ColorMask {
|
||||||
use wgt::ColorWrite as Cw;
|
|
||||||
use hal::pso::ColorMask as H;
|
use hal::pso::ColorMask as H;
|
||||||
|
use wgt::ColorWrite as Cw;
|
||||||
|
|
||||||
let mut value = H::empty();
|
let mut value = H::empty();
|
||||||
if flags.contains(Cw::RED) {
|
if flags.contains(Cw::RED) {
|
||||||
@ -249,8 +202,8 @@ fn map_color_write_flags(flags: ColorWrite) -> hal::pso::ColorMask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn map_blend_descriptor(blend_desc: &BlendDescriptor) -> hal::pso::BlendOp {
|
fn map_blend_descriptor(blend_desc: &BlendDescriptor) -> hal::pso::BlendOp {
|
||||||
use wgt::BlendOperation as Bo;
|
|
||||||
use hal::pso::BlendOp as H;
|
use hal::pso::BlendOp as H;
|
||||||
|
use wgt::BlendOperation as Bo;
|
||||||
match blend_desc.operation {
|
match blend_desc.operation {
|
||||||
Bo::Add => H::Add {
|
Bo::Add => H::Add {
|
||||||
src: map_blend_factor(blend_desc.src_factor),
|
src: map_blend_factor(blend_desc.src_factor),
|
||||||
@ -270,8 +223,8 @@ fn map_blend_descriptor(blend_desc: &BlendDescriptor) -> hal::pso::BlendOp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn map_blend_factor(blend_factor: BlendFactor) -> hal::pso::Factor {
|
fn map_blend_factor(blend_factor: BlendFactor) -> hal::pso::Factor {
|
||||||
use wgt::BlendFactor as Bf;
|
|
||||||
use hal::pso::Factor as H;
|
use hal::pso::Factor as H;
|
||||||
|
use wgt::BlendFactor as Bf;
|
||||||
match blend_factor {
|
match blend_factor {
|
||||||
Bf::Zero => H::Zero,
|
Bf::Zero => H::Zero,
|
||||||
Bf::One => H::One,
|
Bf::One => H::One,
|
||||||
@ -293,11 +246,10 @@ pub fn map_depth_stencil_state_descriptor(
|
|||||||
desc: &DepthStencilStateDescriptor,
|
desc: &DepthStencilStateDescriptor,
|
||||||
) -> hal::pso::DepthStencilDesc {
|
) -> hal::pso::DepthStencilDesc {
|
||||||
hal::pso::DepthStencilDesc {
|
hal::pso::DepthStencilDesc {
|
||||||
depth: if desc.depth_write_enabled
|
depth: if desc.depth_write_enabled || desc.depth_compare != CompareFunction::Always {
|
||||||
|| desc.depth_compare != CompareFunction::Always
|
|
||||||
{
|
|
||||||
Some(hal::pso::DepthTest {
|
Some(hal::pso::DepthTest {
|
||||||
fun: map_compare_function(desc.depth_compare).expect("DepthStencilStateDescriptor has undefined compare function"),
|
fun: map_compare_function(desc.depth_compare)
|
||||||
|
.expect("DepthStencilStateDescriptor has undefined compare function"),
|
||||||
write: desc.depth_write_enabled,
|
write: desc.depth_write_enabled,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -328,11 +280,10 @@ pub fn map_depth_stencil_state_descriptor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_stencil_face(
|
fn map_stencil_face(stencil_state_face_desc: &StencilStateFaceDescriptor) -> hal::pso::StencilFace {
|
||||||
stencil_state_face_desc: &StencilStateFaceDescriptor,
|
|
||||||
) -> hal::pso::StencilFace {
|
|
||||||
hal::pso::StencilFace {
|
hal::pso::StencilFace {
|
||||||
fun: map_compare_function(stencil_state_face_desc.compare).expect("StencilStateFaceDescriptor has undefined compare function"),
|
fun: map_compare_function(stencil_state_face_desc.compare)
|
||||||
|
.expect("StencilStateFaceDescriptor has undefined compare function"),
|
||||||
op_fail: map_stencil_operation(stencil_state_face_desc.fail_op),
|
op_fail: map_stencil_operation(stencil_state_face_desc.fail_op),
|
||||||
op_depth_fail: map_stencil_operation(stencil_state_face_desc.depth_fail_op),
|
op_depth_fail: map_stencil_operation(stencil_state_face_desc.depth_fail_op),
|
||||||
op_pass: map_stencil_operation(stencil_state_face_desc.pass_op),
|
op_pass: map_stencil_operation(stencil_state_face_desc.pass_op),
|
||||||
@ -340,8 +291,8 @@ fn map_stencil_face(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_compare_function(compare_function: CompareFunction) -> Option<hal::pso::Comparison> {
|
pub fn map_compare_function(compare_function: CompareFunction) -> Option<hal::pso::Comparison> {
|
||||||
use wgt::CompareFunction as Cf;
|
|
||||||
use hal::pso::Comparison as H;
|
use hal::pso::Comparison as H;
|
||||||
|
use wgt::CompareFunction as Cf;
|
||||||
match compare_function {
|
match compare_function {
|
||||||
Cf::Undefined => None,
|
Cf::Undefined => None,
|
||||||
Cf::Never => Some(H::Never),
|
Cf::Never => Some(H::Never),
|
||||||
@ -356,8 +307,8 @@ pub fn map_compare_function(compare_function: CompareFunction) -> Option<hal::ps
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn map_stencil_operation(stencil_operation: StencilOperation) -> hal::pso::StencilOp {
|
fn map_stencil_operation(stencil_operation: StencilOperation) -> hal::pso::StencilOp {
|
||||||
use wgt::StencilOperation as So;
|
|
||||||
use hal::pso::StencilOp as H;
|
use hal::pso::StencilOp as H;
|
||||||
|
use wgt::StencilOperation as So;
|
||||||
match stencil_operation {
|
match stencil_operation {
|
||||||
So::Keep => H::Keep,
|
So::Keep => H::Keep,
|
||||||
So::Zero => H::Zero,
|
So::Zero => H::Zero,
|
||||||
@ -374,8 +325,8 @@ pub(crate) fn map_texture_format(
|
|||||||
texture_format: TextureFormat,
|
texture_format: TextureFormat,
|
||||||
features: Features,
|
features: Features,
|
||||||
) -> hal::format::Format {
|
) -> hal::format::Format {
|
||||||
use wgt::TextureFormat as Tf;
|
|
||||||
use hal::format::Format as H;
|
use hal::format::Format as H;
|
||||||
|
use wgt::TextureFormat as Tf;
|
||||||
match texture_format {
|
match texture_format {
|
||||||
// Normal 8 bit formats
|
// Normal 8 bit formats
|
||||||
Tf::R8Unorm => H::R8Unorm,
|
Tf::R8Unorm => H::R8Unorm,
|
||||||
@ -444,8 +395,8 @@ pub(crate) fn map_texture_format(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_vertex_format(vertex_format: VertexFormat) -> hal::format::Format {
|
pub fn map_vertex_format(vertex_format: VertexFormat) -> hal::format::Format {
|
||||||
use wgt::VertexFormat as Vf;
|
|
||||||
use hal::format::Format as H;
|
use hal::format::Format as H;
|
||||||
|
use wgt::VertexFormat as Vf;
|
||||||
match vertex_format {
|
match vertex_format {
|
||||||
Vf::Uchar2 => H::Rg8Uint,
|
Vf::Uchar2 => H::Rg8Uint,
|
||||||
Vf::Uchar4 => H::Rgba8Uint,
|
Vf::Uchar4 => H::Rgba8Uint,
|
||||||
@ -495,8 +446,8 @@ pub fn map_texture_dimension_size(
|
|||||||
array_size: u32,
|
array_size: u32,
|
||||||
sample_size: u32,
|
sample_size: u32,
|
||||||
) -> hal::image::Kind {
|
) -> hal::image::Kind {
|
||||||
use wgt::TextureDimension::*;
|
|
||||||
use hal::image::Kind as H;
|
use hal::image::Kind as H;
|
||||||
|
use wgt::TextureDimension::*;
|
||||||
match dimension {
|
match dimension {
|
||||||
D1 => {
|
D1 => {
|
||||||
assert_eq!(height, 1);
|
assert_eq!(height, 1);
|
||||||
@ -531,11 +482,9 @@ pub fn map_texture_dimension_size(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_texture_view_dimension(
|
pub fn map_texture_view_dimension(dimension: wgt::TextureViewDimension) -> hal::image::ViewKind {
|
||||||
dimension: wgt::TextureViewDimension,
|
|
||||||
) -> hal::image::ViewKind {
|
|
||||||
use wgt::TextureViewDimension::*;
|
|
||||||
use hal::image::ViewKind as H;
|
use hal::image::ViewKind as H;
|
||||||
|
use wgt::TextureViewDimension::*;
|
||||||
match dimension {
|
match dimension {
|
||||||
D1 => H::D1,
|
D1 => H::D1,
|
||||||
D2 => H::D2,
|
D2 => H::D2,
|
||||||
@ -547,8 +496,8 @@ pub fn map_texture_view_dimension(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_buffer_state(usage: wgt::BufferUsage) -> hal::buffer::State {
|
pub fn map_buffer_state(usage: wgt::BufferUsage) -> hal::buffer::State {
|
||||||
use wgt::BufferUsage as W;
|
|
||||||
use hal::buffer::Access as A;
|
use hal::buffer::Access as A;
|
||||||
|
use wgt::BufferUsage as W;
|
||||||
|
|
||||||
let mut access = A::empty();
|
let mut access = A::empty();
|
||||||
if usage.contains(W::COPY_SRC) {
|
if usage.contains(W::COPY_SRC) {
|
||||||
@ -580,8 +529,8 @@ pub fn map_texture_state(
|
|||||||
usage: wgt::TextureUsage,
|
usage: wgt::TextureUsage,
|
||||||
aspects: hal::format::Aspects,
|
aspects: hal::format::Aspects,
|
||||||
) -> hal::image::State {
|
) -> hal::image::State {
|
||||||
use wgt::TextureUsage as W;
|
|
||||||
use hal::image::{Access as A, Layout as L};
|
use hal::image::{Access as A, Layout as L};
|
||||||
|
use wgt::TextureUsage as W;
|
||||||
|
|
||||||
let is_color = aspects.contains(hal::format::Aspects::COLOR);
|
let is_color = aspects.contains(hal::format::Aspects::COLOR);
|
||||||
let layout = match usage {
|
let layout = match usage {
|
||||||
@ -619,10 +568,7 @@ pub fn map_texture_state(
|
|||||||
(access, layout)
|
(access, layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_load_store_ops(
|
pub fn map_load_store_ops(load: wgt::LoadOp, store: wgt::StoreOp) -> hal::pass::AttachmentOps {
|
||||||
load: wgt::LoadOp,
|
|
||||||
store: wgt::StoreOp,
|
|
||||||
) -> hal::pass::AttachmentOps {
|
|
||||||
hal::pass::AttachmentOps {
|
hal::pass::AttachmentOps {
|
||||||
load: match load {
|
load: match load {
|
||||||
wgt::LoadOp::Clear => hal::pass::AttachmentLoadOp::Clear,
|
wgt::LoadOp::Clear => hal::pass::AttachmentLoadOp::Clear,
|
||||||
@ -668,8 +614,8 @@ pub fn map_filter(filter: wgt::FilterMode) -> hal::image::Filter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_wrap(address: wgt::AddressMode) -> hal::image::WrapMode {
|
pub fn map_wrap(address: wgt::AddressMode) -> hal::image::WrapMode {
|
||||||
use wgt::AddressMode as Am;
|
|
||||||
use hal::image::WrapMode as W;
|
use hal::image::WrapMode as W;
|
||||||
|
use wgt::AddressMode as Am;
|
||||||
match address {
|
match address {
|
||||||
Am::ClampToEdge => W::Clamp,
|
Am::ClampToEdge => W::Clamp,
|
||||||
Am::Repeat => W::Tile,
|
Am::Repeat => W::Tile,
|
||||||
|
@ -4,25 +4,18 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Token},
|
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Token},
|
||||||
id,
|
id, resource,
|
||||||
resource,
|
|
||||||
track::TrackerSet,
|
track::TrackerSet,
|
||||||
FastHashMap,
|
FastHashMap, RefCount, Stored, SubmissionIndex,
|
||||||
Stored,
|
|
||||||
RefCount,
|
|
||||||
SubmissionIndex,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use copyless::VecHelper as _;
|
use copyless::VecHelper as _;
|
||||||
use hal::device::Device as _;
|
|
||||||
use parking_lot::Mutex;
|
|
||||||
use gfx_descriptor::{DescriptorAllocator, DescriptorSet};
|
use gfx_descriptor::{DescriptorAllocator, DescriptorSet};
|
||||||
use gfx_memory::{Heaps, MemoryBlock};
|
use gfx_memory::{Heaps, MemoryBlock};
|
||||||
|
use hal::device::Device as _;
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
use std::{
|
use std::sync::atomic::Ordering;
|
||||||
sync::atomic::Ordering,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const CLEANUP_WAIT_MS: u64 = 5000;
|
const CLEANUP_WAIT_MS: u64 = 5000;
|
||||||
|
|
||||||
@ -55,8 +48,10 @@ impl SuspectedResources {
|
|||||||
self.texture_views.extend_from_slice(&other.texture_views);
|
self.texture_views.extend_from_slice(&other.texture_views);
|
||||||
self.samplers.extend_from_slice(&other.samplers);
|
self.samplers.extend_from_slice(&other.samplers);
|
||||||
self.bind_groups.extend_from_slice(&other.bind_groups);
|
self.bind_groups.extend_from_slice(&other.bind_groups);
|
||||||
self.compute_pipelines.extend_from_slice(&other.compute_pipelines);
|
self.compute_pipelines
|
||||||
self.render_pipelines.extend_from_slice(&other.render_pipelines);
|
.extend_from_slice(&other.compute_pipelines);
|
||||||
|
self.render_pipelines
|
||||||
|
.extend_from_slice(&other.render_pipelines);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,14 +192,12 @@ impl<B: hal::Backend> LifetimeTracker<B> {
|
|||||||
new_suspects: &SuspectedResources,
|
new_suspects: &SuspectedResources,
|
||||||
) {
|
) {
|
||||||
self.suspected_resources.extend(new_suspects);
|
self.suspected_resources.extend(new_suspects);
|
||||||
self.active
|
self.active.alloc().init(ActiveSubmission {
|
||||||
.alloc()
|
index,
|
||||||
.init(ActiveSubmission {
|
fence,
|
||||||
index,
|
last_resources: NonReferencedResources::new(),
|
||||||
fence,
|
mapped: Vec::new(),
|
||||||
last_resources: NonReferencedResources::new(),
|
});
|
||||||
mapped: Vec::new(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map(&mut self, buffer: id::BufferId, ref_count: RefCount) {
|
pub fn map(&mut self, buffer: id::BufferId, ref_count: RefCount) {
|
||||||
@ -238,11 +231,7 @@ impl<B: hal::Backend> LifetimeTracker<B> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the last submission index that is done.
|
/// Returns the last submission index that is done.
|
||||||
pub fn triage_submissions(
|
pub fn triage_submissions(&mut self, device: &B::Device, force_wait: bool) -> SubmissionIndex {
|
||||||
&mut self,
|
|
||||||
device: &B::Device,
|
|
||||||
force_wait: bool,
|
|
||||||
) -> SubmissionIndex {
|
|
||||||
if force_wait {
|
if force_wait {
|
||||||
self.wait_idle(device);
|
self.wait_idle(device);
|
||||||
}
|
}
|
||||||
@ -259,7 +248,7 @@ impl<B: hal::Backend> LifetimeTracker<B> {
|
|||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
for a in self.active.drain(.. done_count) {
|
for a in self.active.drain(..done_count) {
|
||||||
log::trace!("Active submission {} is done", a.index);
|
log::trace!("Active submission {} is done", a.index);
|
||||||
self.free_resources.extend(a.last_resources);
|
self.free_resources.extend(a.last_resources);
|
||||||
self.ready_to_map.extend(a.mapped);
|
self.ready_to_map.extend(a.mapped);
|
||||||
@ -278,14 +267,9 @@ impl<B: hal::Backend> LifetimeTracker<B> {
|
|||||||
descriptor_allocator_mutex: &Mutex<DescriptorAllocator<B>>,
|
descriptor_allocator_mutex: &Mutex<DescriptorAllocator<B>>,
|
||||||
) {
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.free_resources.clean(
|
self.free_resources
|
||||||
device,
|
.clean(device, heaps_mutex, descriptor_allocator_mutex);
|
||||||
heaps_mutex,
|
descriptor_allocator_mutex.lock().cleanup(device);
|
||||||
descriptor_allocator_mutex,
|
|
||||||
);
|
|
||||||
descriptor_allocator_mutex
|
|
||||||
.lock()
|
|
||||||
.cleanup(device);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -309,17 +293,26 @@ impl<B: GfxBackend> LifetimeTracker<B> {
|
|||||||
let res = guard.remove(id).unwrap();
|
let res = guard.remove(id).unwrap();
|
||||||
|
|
||||||
assert!(res.used.bind_groups.is_empty());
|
assert!(res.used.bind_groups.is_empty());
|
||||||
self.suspected_resources.buffers.extend(res.used.buffers.used());
|
self.suspected_resources
|
||||||
self.suspected_resources.textures.extend(res.used.textures.used());
|
.buffers
|
||||||
self.suspected_resources.texture_views.extend(res.used.views.used());
|
.extend(res.used.buffers.used());
|
||||||
self.suspected_resources.samplers.extend(res.used.samplers.used());
|
self.suspected_resources
|
||||||
|
.textures
|
||||||
|
.extend(res.used.textures.used());
|
||||||
|
self.suspected_resources
|
||||||
|
.texture_views
|
||||||
|
.extend(res.used.views.used());
|
||||||
|
self.suspected_resources
|
||||||
|
.samplers
|
||||||
|
.extend(res.used.samplers.used());
|
||||||
|
|
||||||
let submit_index = res.life_guard.submission_index.load(Ordering::Acquire);
|
let submit_index = res.life_guard.submission_index.load(Ordering::Acquire);
|
||||||
self.active
|
self.active
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|a| a.index == submit_index)
|
.find(|a| a.index == submit_index)
|
||||||
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
||||||
.desc_sets.push(res.raw);
|
.desc_sets
|
||||||
|
.push(res.raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -346,7 +339,8 @@ impl<B: GfxBackend> LifetimeTracker<B> {
|
|||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|a| a.index == submit_index)
|
.find(|a| a.index == submit_index)
|
||||||
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
||||||
.image_views.push((id, raw));
|
.image_views
|
||||||
|
.push((id, raw));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -365,7 +359,8 @@ impl<B: GfxBackend> LifetimeTracker<B> {
|
|||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|a| a.index == submit_index)
|
.find(|a| a.index == submit_index)
|
||||||
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
||||||
.images.push((res.raw, res.memory));
|
.images
|
||||||
|
.push((res.raw, res.memory));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -384,7 +379,8 @@ impl<B: GfxBackend> LifetimeTracker<B> {
|
|||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|a| a.index == submit_index)
|
.find(|a| a.index == submit_index)
|
||||||
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
||||||
.samplers.push(res.raw);
|
.samplers
|
||||||
|
.push(res.raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -404,7 +400,8 @@ impl<B: GfxBackend> LifetimeTracker<B> {
|
|||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|a| a.index == submit_index)
|
.find(|a| a.index == submit_index)
|
||||||
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
||||||
.buffers.push((res.raw, res.memory));
|
.buffers
|
||||||
|
.push((res.raw, res.memory));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,7 +420,8 @@ impl<B: GfxBackend> LifetimeTracker<B> {
|
|||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|a| a.index == submit_index)
|
.find(|a| a.index == submit_index)
|
||||||
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
||||||
.compute_pipes.push(res.raw);
|
.compute_pipes
|
||||||
|
.push(res.raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -442,7 +440,8 @@ impl<B: GfxBackend> LifetimeTracker<B> {
|
|||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|a| a.index == submit_index)
|
.find(|a| a.index == submit_index)
|
||||||
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
||||||
.graphics_pipes.push(res.raw);
|
.graphics_pipes
|
||||||
|
.push(res.raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -517,7 +516,9 @@ impl<B: GfxBackend> LifetimeTracker<B> {
|
|||||||
// Between all attachments, we need the smallest index, because that's the last
|
// Between all attachments, we need the smallest index, because that's the last
|
||||||
// time this framebuffer is still valid
|
// time this framebuffer is still valid
|
||||||
if let Some(attachment_last_submit) = attachment_last_submit {
|
if let Some(attachment_last_submit) = attachment_last_submit {
|
||||||
let min = last_submit.unwrap_or(std::usize::MAX).min(attachment_last_submit);
|
let min = last_submit
|
||||||
|
.unwrap_or(std::usize::MAX)
|
||||||
|
.min(attachment_last_submit);
|
||||||
last_submit = Some(min);
|
last_submit = Some(min);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -537,7 +538,8 @@ impl<B: GfxBackend> LifetimeTracker<B> {
|
|||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|a| a.index == submit_index)
|
.find(|a| a.index == submit_index)
|
||||||
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
||||||
.framebuffers.push(framebuffer);
|
.framebuffers
|
||||||
|
.push(framebuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,18 +555,25 @@ impl<B: GfxBackend> LifetimeTracker<B> {
|
|||||||
}
|
}
|
||||||
let hub = B::hub(global);
|
let hub = B::hub(global);
|
||||||
let (mut buffer_guard, _) = B::hub(global).buffers.write(token);
|
let (mut buffer_guard, _) = B::hub(global).buffers.write(token);
|
||||||
let mut pending_callbacks: Vec<super::BufferMapPendingCallback> = Vec::with_capacity(self.ready_to_map.len());
|
let mut pending_callbacks: Vec<super::BufferMapPendingCallback> =
|
||||||
|
Vec::with_capacity(self.ready_to_map.len());
|
||||||
let mut trackers = trackers.lock();
|
let mut trackers = trackers.lock();
|
||||||
for buffer_id in self.ready_to_map.drain(..) {
|
for buffer_id in self.ready_to_map.drain(..) {
|
||||||
let buffer = &mut buffer_guard[buffer_id];
|
let buffer = &mut buffer_guard[buffer_id];
|
||||||
if buffer.life_guard.ref_count.is_none() && trackers.buffers.remove_abandoned(buffer_id) {
|
if buffer.life_guard.ref_count.is_none() && trackers.buffers.remove_abandoned(buffer_id)
|
||||||
|
{
|
||||||
buffer.map_state = resource::BufferMapState::Idle;
|
buffer.map_state = resource::BufferMapState::Idle;
|
||||||
log::debug!("Mapping request is dropped because the buffer is destroyed.");
|
log::debug!("Mapping request is dropped because the buffer is destroyed.");
|
||||||
hub.buffers.free_id(buffer_id);
|
hub.buffers.free_id(buffer_id);
|
||||||
let buffer = buffer_guard.remove(buffer_id).unwrap();
|
let buffer = buffer_guard.remove(buffer_id).unwrap();
|
||||||
self.free_resources.buffers.push((buffer.raw, buffer.memory));
|
self.free_resources
|
||||||
|
.buffers
|
||||||
|
.push((buffer.raw, buffer.memory));
|
||||||
} else {
|
} else {
|
||||||
let mapping = match std::mem::replace(&mut buffer.map_state, resource::BufferMapState::Active) {
|
let mapping = match std::mem::replace(
|
||||||
|
&mut buffer.map_state,
|
||||||
|
resource::BufferMapState::Active,
|
||||||
|
) {
|
||||||
resource::BufferMapState::Waiting(pending_mapping) => pending_mapping,
|
resource::BufferMapState::Waiting(pending_mapping) => pending_mapping,
|
||||||
_ => panic!("No pending mapping."),
|
_ => panic!("No pending mapping."),
|
||||||
};
|
};
|
||||||
|
@ -3,22 +3,13 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
binding_model,
|
binding_model, command, conv,
|
||||||
command,
|
|
||||||
conv,
|
|
||||||
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Input, Token},
|
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Input, Token},
|
||||||
id,
|
id, pipeline, resource, swap_chain,
|
||||||
pipeline,
|
|
||||||
resource,
|
|
||||||
swap_chain,
|
|
||||||
track::{BufferState, TextureState, TrackerSet},
|
track::{BufferState, TextureState, TrackerSet},
|
||||||
FastHashMap,
|
FastHashMap, Features, LifeGuard, Stored,
|
||||||
Features,
|
|
||||||
LifeGuard,
|
|
||||||
Stored,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use wgt::{BufferAddress, InputStepMode, TextureDimension, TextureFormat, BIND_BUFFER_ALIGNMENT};
|
|
||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
use copyless::VecHelper as _;
|
use copyless::VecHelper as _;
|
||||||
use gfx_descriptor::DescriptorAllocator;
|
use gfx_descriptor::DescriptorAllocator;
|
||||||
@ -32,14 +23,10 @@ use hal::{
|
|||||||
};
|
};
|
||||||
use parking_lot::{Mutex, MutexGuard};
|
use parking_lot::{Mutex, MutexGuard};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
use wgt::{BufferAddress, InputStepMode, TextureDimension, TextureFormat, BIND_BUFFER_ALIGNMENT};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::hash_map::Entry,
|
collections::hash_map::Entry, ffi, iter, marker::PhantomData, ptr, slice,
|
||||||
ffi,
|
|
||||||
iter,
|
|
||||||
marker::PhantomData,
|
|
||||||
ptr,
|
|
||||||
slice,
|
|
||||||
sync::atomic::Ordering,
|
sync::atomic::Ordering,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -108,8 +95,11 @@ type RawBufferMut = *mut u8;
|
|||||||
type BufferMapResult = Result<RawBufferMut, hal::device::MapError>;
|
type BufferMapResult = Result<RawBufferMut, hal::device::MapError>;
|
||||||
type BufferMapPendingCallback = (resource::BufferMapOperation, BufferMapResult);
|
type BufferMapPendingCallback = (resource::BufferMapOperation, BufferMapResult);
|
||||||
|
|
||||||
pub type BufferMapReadCallback =
|
pub type BufferMapReadCallback = unsafe extern "C" fn(
|
||||||
unsafe extern "C" fn(status: resource::BufferMapAsyncStatus, data: *const u8, userdata: *mut u8);
|
status: resource::BufferMapAsyncStatus,
|
||||||
|
data: *const u8,
|
||||||
|
userdata: *mut u8,
|
||||||
|
);
|
||||||
pub type BufferMapWriteCallback =
|
pub type BufferMapWriteCallback =
|
||||||
unsafe extern "C" fn(status: resource::BufferMapAsyncStatus, data: *mut u8, userdata: *mut u8);
|
unsafe extern "C" fn(status: resource::BufferMapAsyncStatus, data: *mut u8, userdata: *mut u8);
|
||||||
|
|
||||||
@ -140,11 +130,8 @@ fn map_buffer<B: hal::Backend>(
|
|||||||
};
|
};
|
||||||
match kind {
|
match kind {
|
||||||
HostMap::Read => unsafe {
|
HostMap::Read => unsafe {
|
||||||
raw.invalidate_mapped_memory_ranges(iter::once((
|
raw.invalidate_mapped_memory_ranges(iter::once((buffer.memory.memory(), segment)))
|
||||||
buffer.memory.memory(),
|
.unwrap();
|
||||||
segment,
|
|
||||||
)))
|
|
||||||
.unwrap();
|
|
||||||
},
|
},
|
||||||
HostMap::Write => {
|
HostMap::Write => {
|
||||||
buffer.mapped_write_segments.push(segment);
|
buffer.mapped_write_segments.push(segment);
|
||||||
@ -154,28 +141,24 @@ fn map_buffer<B: hal::Backend>(
|
|||||||
Ok(ptr.as_ptr())
|
Ok(ptr.as_ptr())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unmap_buffer<B: hal::Backend>(
|
fn unmap_buffer<B: hal::Backend>(raw: &B::Device, buffer: &mut resource::Buffer<B>) {
|
||||||
raw: &B::Device,
|
|
||||||
buffer: &mut resource::Buffer<B>,
|
|
||||||
) {
|
|
||||||
match buffer.map_state {
|
match buffer.map_state {
|
||||||
resource::BufferMapState::Idle => {
|
resource::BufferMapState::Idle => {
|
||||||
log::error!("Buffer already unmapped");
|
log::error!("Buffer already unmapped");
|
||||||
return;
|
return;
|
||||||
},
|
}
|
||||||
_ => buffer.map_state = resource::BufferMapState::Idle,
|
_ => buffer.map_state = resource::BufferMapState::Idle,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !buffer.mapped_write_segments.is_empty() {
|
if !buffer.mapped_write_segments.is_empty() {
|
||||||
unsafe {
|
unsafe {
|
||||||
raw
|
raw.flush_mapped_memory_ranges(
|
||||||
.flush_mapped_memory_ranges(
|
buffer
|
||||||
buffer
|
.mapped_write_segments
|
||||||
.mapped_write_segments
|
.iter()
|
||||||
.iter()
|
.map(|r| (buffer.memory.memory(), r.clone())),
|
||||||
.map(|r| (buffer.memory.memory(), r.clone())),
|
)
|
||||||
)
|
.unwrap()
|
||||||
.unwrap()
|
|
||||||
};
|
};
|
||||||
buffer.mapped_write_segments.clear();
|
buffer.mapped_write_segments.clear();
|
||||||
}
|
}
|
||||||
@ -195,15 +178,14 @@ fn fire_map_callbacks<I: IntoIterator<Item = BufferMapPendingCallback>>(callback
|
|||||||
match operation {
|
match operation {
|
||||||
resource::BufferMapOperation::Read { callback, userdata } => unsafe {
|
resource::BufferMapOperation::Read { callback, userdata } => unsafe {
|
||||||
callback(status, ptr, userdata)
|
callback(status, ptr, userdata)
|
||||||
}
|
},
|
||||||
resource::BufferMapOperation::Write { callback, userdata } => unsafe {
|
resource::BufferMapOperation::Write { callback, userdata } => unsafe {
|
||||||
callback(status, ptr, userdata)
|
callback(status, ptr, userdata)
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Device<B: hal::Backend> {
|
pub struct Device<B: hal::Backend> {
|
||||||
pub(crate) raw: B::Device,
|
pub(crate) raw: B::Device,
|
||||||
@ -272,7 +254,8 @@ impl<B: GfxBackend> Device<B> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn lock_life<'a>(
|
fn lock_life<'a>(
|
||||||
&'a self, _token: &mut Token<'a, Self>
|
&'a self,
|
||||||
|
_token: &mut Token<'a, Self>,
|
||||||
) -> MutexGuard<'a, life::LifetimeTracker<B>> {
|
) -> MutexGuard<'a, life::LifetimeTracker<B>> {
|
||||||
self.life_tracker.lock()
|
self.life_tracker.lock()
|
||||||
}
|
}
|
||||||
@ -290,11 +273,7 @@ impl<B: GfxBackend> Device<B> {
|
|||||||
life_tracker.triage_framebuffers(global, &mut *self.framebuffers.lock(), token);
|
life_tracker.triage_framebuffers(global, &mut *self.framebuffers.lock(), token);
|
||||||
let _last_done = life_tracker.triage_submissions(&self.raw, force_wait);
|
let _last_done = life_tracker.triage_submissions(&self.raw, force_wait);
|
||||||
let callbacks = life_tracker.handle_mapping(global, &self.raw, &self.trackers, token);
|
let callbacks = life_tracker.handle_mapping(global, &self.raw, &self.trackers, token);
|
||||||
life_tracker.cleanup(
|
life_tracker.cleanup(&self.raw, &self.mem_allocator, &self.desc_allocator);
|
||||||
&self.raw,
|
|
||||||
&self.mem_allocator,
|
|
||||||
&self.desc_allocator,
|
|
||||||
);
|
|
||||||
callbacks
|
callbacks
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,7 +296,12 @@ impl<B: GfxBackend> Device<B> {
|
|||||||
} else if (Bu::MAP_READ | Bu::COPY_DST).contains(desc.usage) {
|
} else if (Bu::MAP_READ | Bu::COPY_DST).contains(desc.usage) {
|
||||||
(Kind::Linear, MemoryUsage::Staging { read_back: true })
|
(Kind::Linear, MemoryUsage::Staging { read_back: true })
|
||||||
} else {
|
} else {
|
||||||
(Kind::General, MemoryUsage::Dynamic { sparse_updates: false })
|
(
|
||||||
|
Kind::General,
|
||||||
|
MemoryUsage::Dynamic {
|
||||||
|
sparse_updates: false,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -344,11 +328,7 @@ impl<B: GfxBackend> Device<B> {
|
|||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.raw
|
self.raw
|
||||||
.bind_buffer_memory(
|
.bind_buffer_memory(memory.memory(), memory.segment().offset, &mut buffer)
|
||||||
memory.memory(),
|
|
||||||
memory.segment().offset,
|
|
||||||
&mut buffer,
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -378,9 +358,9 @@ impl<B: GfxBackend> Device<B> {
|
|||||||
// Ensure `D24Plus` textures cannot be copied
|
// Ensure `D24Plus` textures cannot be copied
|
||||||
match desc.format {
|
match desc.format {
|
||||||
TextureFormat::Depth24Plus | TextureFormat::Depth24PlusStencil8 => {
|
TextureFormat::Depth24Plus | TextureFormat::Depth24PlusStencil8 => {
|
||||||
assert!(!desc.usage.intersects(
|
assert!(!desc
|
||||||
wgt::TextureUsage::COPY_SRC | wgt::TextureUsage::COPY_DST
|
.usage
|
||||||
));
|
.intersects(wgt::TextureUsage::COPY_SRC | wgt::TextureUsage::COPY_DST));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -407,14 +387,17 @@ impl<B: GfxBackend> Device<B> {
|
|||||||
// TODO: 2D arrays, cubemap arrays
|
// TODO: 2D arrays, cubemap arrays
|
||||||
|
|
||||||
let mut image = unsafe {
|
let mut image = unsafe {
|
||||||
let mut image = self.raw.create_image(
|
let mut image = self
|
||||||
kind,
|
.raw
|
||||||
desc.mip_level_count as hal::image::Level,
|
.create_image(
|
||||||
format,
|
kind,
|
||||||
hal::image::Tiling::Optimal,
|
desc.mip_level_count as hal::image::Level,
|
||||||
usage,
|
format,
|
||||||
view_capabilities,
|
hal::image::Tiling::Optimal,
|
||||||
).unwrap();
|
usage,
|
||||||
|
view_capabilities,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
if !desc.label.is_null() {
|
if !desc.label.is_null() {
|
||||||
let label = ffi::CStr::from_ptr(desc.label).to_string_lossy();
|
let label = ffi::CStr::from_ptr(desc.label).to_string_lossy();
|
||||||
self.raw.set_image_name(&mut image, &label);
|
self.raw.set_image_name(&mut image, &label);
|
||||||
@ -438,11 +421,7 @@ impl<B: GfxBackend> Device<B> {
|
|||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.raw
|
self.raw
|
||||||
.bind_image_memory(
|
.bind_image_memory(memory.memory(), memory.segment().offset, &mut image)
|
||||||
memory.memory(),
|
|
||||||
memory.segment().offset,
|
|
||||||
&mut image,
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -457,8 +436,8 @@ impl<B: GfxBackend> Device<B> {
|
|||||||
format: desc.format,
|
format: desc.format,
|
||||||
full_range: hal::image::SubresourceRange {
|
full_range: hal::image::SubresourceRange {
|
||||||
aspects,
|
aspects,
|
||||||
levels: 0 .. desc.mip_level_count as hal::image::Level,
|
levels: 0..desc.mip_level_count as hal::image::Level,
|
||||||
layers: 0 .. desc.array_layer_count as hal::image::Layer,
|
layers: 0..desc.array_layer_count as hal::image::Layer,
|
||||||
},
|
},
|
||||||
memory,
|
memory,
|
||||||
life_guard: LifeGuard::new(),
|
life_guard: LifeGuard::new(),
|
||||||
@ -489,11 +468,9 @@ impl<B: hal::Backend> Device<B> {
|
|||||||
|
|
||||||
pub(crate) fn dispose(self) {
|
pub(crate) fn dispose(self) {
|
||||||
self.life_tracker.lock().triage_submissions(&self.raw, true);
|
self.life_tracker.lock().triage_submissions(&self.raw, true);
|
||||||
self.life_tracker.lock().cleanup(
|
self.life_tracker
|
||||||
&self.raw,
|
.lock()
|
||||||
&self.mem_allocator,
|
.cleanup(&self.raw, &self.mem_allocator, &self.desc_allocator);
|
||||||
&self.desc_allocator,
|
|
||||||
);
|
|
||||||
self.com_allocator.destroy(&self.raw);
|
self.com_allocator.destroy(&self.raw);
|
||||||
let mut desc_alloc = self.desc_allocator.into_inner();
|
let mut desc_alloc = self.desc_allocator.into_inner();
|
||||||
let mut mem_alloc = self.mem_allocator.into_inner();
|
let mut mem_alloc = self.mem_allocator.into_inner();
|
||||||
@ -510,7 +487,6 @@ impl<B: hal::Backend> Device<B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||||
pub fn device_create_buffer<B: GfxBackend>(
|
pub fn device_create_buffer<B: GfxBackend>(
|
||||||
&self,
|
&self,
|
||||||
@ -568,7 +544,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
Ok(ptr) => {
|
Ok(ptr) => {
|
||||||
buffer.map_state = resource::BufferMapState::Active;
|
buffer.map_state = resource::BufferMapState::Active;
|
||||||
ptr
|
ptr
|
||||||
},
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("failed to create buffer in a mapped state: {:?}", e);
|
log::error!("failed to create buffer in a mapped state: {:?}", e);
|
||||||
ptr::null_mut()
|
ptr::null_mut()
|
||||||
@ -577,9 +553,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
|
|
||||||
let id = hub.buffers.register_identity(id_in, buffer, &mut token);
|
let id = hub.buffers.register_identity(id_in, buffer, &mut token);
|
||||||
log::info!("Created mapped buffer {:?} with {:?}", id, desc);
|
log::info!("Created mapped buffer {:?} with {:?}", id, desc);
|
||||||
device.trackers
|
device
|
||||||
|
.trackers
|
||||||
.lock()
|
.lock()
|
||||||
.buffers.init(
|
.buffers
|
||||||
|
.init(
|
||||||
id,
|
id,
|
||||||
ref_count,
|
ref_count,
|
||||||
BufferState::with_usage(wgt::BufferUsage::MAP_WRITE),
|
BufferState::with_usage(wgt::BufferUsage::MAP_WRITE),
|
||||||
@ -609,7 +587,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
match map_buffer(
|
match map_buffer(
|
||||||
&device.raw,
|
&device.raw,
|
||||||
&mut buffer,
|
&mut buffer,
|
||||||
hal::buffer::SubRange { offset, size: Some(data.len() as BufferAddress) },
|
hal::buffer::SubRange {
|
||||||
|
offset,
|
||||||
|
size: Some(data.len() as BufferAddress),
|
||||||
|
},
|
||||||
HostMap::Write,
|
HostMap::Write,
|
||||||
) {
|
) {
|
||||||
Ok(ptr) => unsafe {
|
Ok(ptr) => unsafe {
|
||||||
@ -644,7 +625,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
match map_buffer(
|
match map_buffer(
|
||||||
&device.raw,
|
&device.raw,
|
||||||
&mut buffer,
|
&mut buffer,
|
||||||
hal::buffer::SubRange { offset, size: Some(data.len() as BufferAddress) },
|
hal::buffer::SubRange {
|
||||||
|
offset,
|
||||||
|
size: Some(data.len() as BufferAddress),
|
||||||
|
},
|
||||||
HostMap::Read,
|
HostMap::Read,
|
||||||
) {
|
) {
|
||||||
Ok(ptr) => unsafe {
|
Ok(ptr) => unsafe {
|
||||||
@ -674,7 +658,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||||
device_guard[device_id]
|
device_guard[device_id]
|
||||||
.lock_life(&mut token)
|
.lock_life(&mut token)
|
||||||
.suspected_resources.buffers.push(buffer_id);
|
.suspected_resources
|
||||||
|
.buffers
|
||||||
|
.push(buffer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn device_create_texture<B: GfxBackend>(
|
pub fn device_create_texture<B: GfxBackend>(
|
||||||
@ -693,13 +679,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let ref_count = texture.life_guard.add_ref();
|
let ref_count = texture.life_guard.add_ref();
|
||||||
|
|
||||||
let id = hub.textures.register_identity(id_in, texture, &mut token);
|
let id = hub.textures.register_identity(id_in, texture, &mut token);
|
||||||
device.trackers
|
device
|
||||||
|
.trackers
|
||||||
.lock()
|
.lock()
|
||||||
.textures.init(
|
.textures
|
||||||
id,
|
.init(id, ref_count, TextureState::with_range(&range))
|
||||||
ref_count,
|
|
||||||
TextureState::with_range(&range),
|
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
@ -718,7 +702,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||||
device_guard[device_id]
|
device_guard[device_id]
|
||||||
.lock_life(&mut token)
|
.lock_life(&mut token)
|
||||||
.suspected_resources.textures.push(texture_id);
|
.suspected_resources
|
||||||
|
.textures
|
||||||
|
.push(texture_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn texture_create_view<B: GfxBackend>(
|
pub fn texture_create_view<B: GfxBackend>(
|
||||||
@ -750,8 +736,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
};
|
};
|
||||||
let range = hal::image::SubresourceRange {
|
let range = hal::image::SubresourceRange {
|
||||||
aspects: texture.full_range.aspects,
|
aspects: texture.full_range.aspects,
|
||||||
levels: desc.base_mip_level as u8 .. end_level,
|
levels: desc.base_mip_level as u8..end_level,
|
||||||
layers: desc.base_array_layer as u16 .. end_layer,
|
layers: desc.base_array_layer as u16..end_layer,
|
||||||
};
|
};
|
||||||
(desc.format, kind, range)
|
(desc.format, kind, range)
|
||||||
}
|
}
|
||||||
@ -797,9 +783,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let ref_count = view.life_guard.add_ref();
|
let ref_count = view.life_guard.add_ref();
|
||||||
|
|
||||||
let id = hub.texture_views.register_identity(id_in, view, &mut token);
|
let id = hub.texture_views.register_identity(id_in, view, &mut token);
|
||||||
device.trackers
|
device
|
||||||
|
.trackers
|
||||||
.lock()
|
.lock()
|
||||||
.views.init(id, ref_count, PhantomData)
|
.views
|
||||||
|
.init(id, ref_count, PhantomData)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
@ -827,7 +815,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||||
device_guard[device_id]
|
device_guard[device_id]
|
||||||
.lock_life(&mut token)
|
.lock_life(&mut token)
|
||||||
.suspected_resources.texture_views.push(texture_view_id);
|
.suspected_resources
|
||||||
|
.texture_views
|
||||||
|
.push(texture_view_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn device_create_sampler<B: GfxBackend>(
|
pub fn device_create_sampler<B: GfxBackend>(
|
||||||
@ -851,7 +841,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
conv::map_wrap(desc.address_mode_w),
|
conv::map_wrap(desc.address_mode_w),
|
||||||
),
|
),
|
||||||
lod_bias: hal::image::Lod(0.0),
|
lod_bias: hal::image::Lod(0.0),
|
||||||
lod_range: hal::image::Lod(desc.lod_min_clamp) .. hal::image::Lod(desc.lod_max_clamp),
|
lod_range: hal::image::Lod(desc.lod_min_clamp)..hal::image::Lod(desc.lod_max_clamp),
|
||||||
comparison: conv::map_compare_function(desc.compare),
|
comparison: conv::map_compare_function(desc.compare),
|
||||||
border: hal::image::PackedColor(0),
|
border: hal::image::PackedColor(0),
|
||||||
normalized: true,
|
normalized: true,
|
||||||
@ -869,9 +859,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let ref_count = sampler.life_guard.add_ref();
|
let ref_count = sampler.life_guard.add_ref();
|
||||||
|
|
||||||
let id = hub.samplers.register_identity(id_in, sampler, &mut token);
|
let id = hub.samplers.register_identity(id_in, sampler, &mut token);
|
||||||
device.trackers
|
device
|
||||||
|
.trackers
|
||||||
.lock()
|
.lock()
|
||||||
.samplers.init(id, ref_count, PhantomData)
|
.samplers
|
||||||
|
.init(id, ref_count, PhantomData)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
@ -890,7 +882,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||||
device_guard[device_id]
|
device_guard[device_id]
|
||||||
.lock_life(&mut token)
|
.lock_life(&mut token)
|
||||||
.suspected_resources.samplers.push(sampler_id);
|
.suspected_resources
|
||||||
|
.samplers
|
||||||
|
.push(sampler_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn device_create_bind_group_layout<B: GfxBackend>(
|
pub fn device_create_bind_group_layout<B: GfxBackend>(
|
||||||
@ -902,11 +896,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let mut token = Token::root();
|
let mut token = Token::root();
|
||||||
let hub = B::hub(self);
|
let hub = B::hub(self);
|
||||||
let entries = unsafe { slice::from_raw_parts(desc.entries, desc.entries_length) };
|
let entries = unsafe { slice::from_raw_parts(desc.entries, desc.entries_length) };
|
||||||
let entry_map: FastHashMap<_, _> = entries
|
let entry_map: FastHashMap<_, _> =
|
||||||
.iter()
|
entries.iter().cloned().map(|b| (b.binding, b)).collect();
|
||||||
.cloned()
|
|
||||||
.map(|b| (b.binding, b))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// TODO: deduplicate the bind group layouts at some level.
|
// TODO: deduplicate the bind group layouts at some level.
|
||||||
// We can't do it right here, because in the remote scenario
|
// We can't do it right here, because in the remote scenario
|
||||||
@ -942,7 +933,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
if !desc.label.is_null() {
|
if !desc.label.is_null() {
|
||||||
let label = ffi::CStr::from_ptr(desc.label).to_string_lossy();
|
let label = ffi::CStr::from_ptr(desc.label).to_string_lossy();
|
||||||
device.raw.set_descriptor_set_layout_name(&mut raw_layout, &label);
|
device
|
||||||
|
.raw
|
||||||
|
.set_descriptor_set_layout_name(&mut raw_layout, &label);
|
||||||
}
|
}
|
||||||
raw_layout
|
raw_layout
|
||||||
};
|
};
|
||||||
@ -962,13 +955,20 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
.register_identity(id_in, layout, &mut token)
|
.register_identity(id_in, layout, &mut token)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bind_group_layout_destroy<B: GfxBackend>(&self, bind_group_layout_id: id::BindGroupLayoutId) {
|
pub fn bind_group_layout_destroy<B: GfxBackend>(
|
||||||
|
&self,
|
||||||
|
bind_group_layout_id: id::BindGroupLayoutId,
|
||||||
|
) {
|
||||||
let hub = B::hub(self);
|
let hub = B::hub(self);
|
||||||
let mut token = Token::root();
|
let mut token = Token::root();
|
||||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||||
let (bgl, _) = hub.bind_group_layouts.unregister(bind_group_layout_id, &mut token);
|
let (bgl, _) = hub
|
||||||
|
.bind_group_layouts
|
||||||
|
.unregister(bind_group_layout_id, &mut token);
|
||||||
unsafe {
|
unsafe {
|
||||||
device_guard[bgl.device_id.value].raw.destroy_descriptor_set_layout(bgl.raw);
|
device_guard[bgl.device_id.value]
|
||||||
|
.raw
|
||||||
|
.destroy_descriptor_set_layout(bgl.raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1020,9 +1020,13 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let hub = B::hub(self);
|
let hub = B::hub(self);
|
||||||
let mut token = Token::root();
|
let mut token = Token::root();
|
||||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||||
let (pipeline_layout, _) = hub.pipeline_layouts.unregister(pipeline_layout_id, &mut token);
|
let (pipeline_layout, _) = hub
|
||||||
|
.pipeline_layouts
|
||||||
|
.unregister(pipeline_layout_id, &mut token);
|
||||||
unsafe {
|
unsafe {
|
||||||
device_guard[pipeline_layout.device_id.value].raw.destroy_pipeline_layout(pipeline_layout.raw);
|
device_guard[pipeline_layout.device_id.value]
|
||||||
|
.raw
|
||||||
|
.destroy_pipeline_layout(pipeline_layout.raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1039,8 +1043,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let device = &device_guard[device_id];
|
let device = &device_guard[device_id];
|
||||||
let (bind_group_layout_guard, mut token) = hub.bind_group_layouts.read(&mut token);
|
let (bind_group_layout_guard, mut token) = hub.bind_group_layouts.read(&mut token);
|
||||||
let bind_group_layout = &bind_group_layout_guard[desc.layout];
|
let bind_group_layout = &bind_group_layout_guard[desc.layout];
|
||||||
let entries =
|
let entries = unsafe { slice::from_raw_parts(desc.entries, desc.entries_length) };
|
||||||
unsafe { slice::from_raw_parts(desc.entries, desc.entries_length) };
|
|
||||||
assert_eq!(entries.len(), bind_group_layout.entries.len());
|
assert_eq!(entries.len(), bind_group_layout.entries.len());
|
||||||
|
|
||||||
let desc_set = unsafe {
|
let desc_set = unsafe {
|
||||||
@ -1078,7 +1081,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
//TODO: group writes into contiguous sections
|
//TODO: group writes into contiguous sections
|
||||||
let mut writes = Vec::new();
|
let mut writes = Vec::new();
|
||||||
for b in entries.iter() {
|
for b in entries.iter() {
|
||||||
let decl = bind_group_layout.entries.get(&b.binding)
|
let decl = bind_group_layout
|
||||||
|
.entries
|
||||||
|
.get(&b.binding)
|
||||||
.expect("Failed to find binding declaration for binding");
|
.expect("Failed to find binding declaration for binding");
|
||||||
let descriptor = match b.resource {
|
let descriptor = match b.resource {
|
||||||
binding_model::BindingResource::Buffer(ref bb) => {
|
binding_model::BindingResource::Buffer(ref bb) => {
|
||||||
@ -1092,11 +1097,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
binding_model::BindingType::ReadonlyStorageBuffer => {
|
binding_model::BindingType::ReadonlyStorageBuffer => {
|
||||||
(BIND_BUFFER_ALIGNMENT, wgt::BufferUsage::STORAGE_READ)
|
(BIND_BUFFER_ALIGNMENT, wgt::BufferUsage::STORAGE_READ)
|
||||||
}
|
}
|
||||||
binding_model::BindingType::Sampler |
|
binding_model::BindingType::Sampler
|
||||||
binding_model::BindingType::ComparisonSampler |
|
| binding_model::BindingType::ComparisonSampler
|
||||||
binding_model::BindingType::SampledTexture |
|
| binding_model::BindingType::SampledTexture
|
||||||
binding_model::BindingType::ReadonlyStorageTexture |
|
| binding_model::BindingType::ReadonlyStorageTexture
|
||||||
binding_model::BindingType::WriteonlyStorageTexture => {
|
| binding_model::BindingType::WriteonlyStorageTexture => {
|
||||||
panic!("Mismatched buffer binding for {:?}", decl)
|
panic!("Mismatched buffer binding for {:?}", decl)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1118,12 +1123,14 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
|
|
||||||
let sub_range = hal::buffer::SubRange {
|
let sub_range = hal::buffer::SubRange {
|
||||||
offset: bb.offset,
|
offset: bb.offset,
|
||||||
size: if bb.size == 0 { None } else {
|
size: if bb.size == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
let end = bb.offset + bb.size;
|
let end = bb.offset + bb.size;
|
||||||
assert!(
|
assert!(
|
||||||
end <= buffer.size,
|
end <= buffer.size,
|
||||||
"Bound buffer range {:?} does not fit in buffer size {}",
|
"Bound buffer range {:?} does not fit in buffer size {}",
|
||||||
bb.offset .. end,
|
bb.offset..end,
|
||||||
buffer.size
|
buffer.size
|
||||||
);
|
);
|
||||||
Some(bb.size)
|
Some(bb.size)
|
||||||
@ -1133,8 +1140,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
}
|
}
|
||||||
binding_model::BindingResource::Sampler(id) => {
|
binding_model::BindingResource::Sampler(id) => {
|
||||||
match decl.ty {
|
match decl.ty {
|
||||||
binding_model::BindingType::Sampler |
|
binding_model::BindingType::Sampler
|
||||||
binding_model::BindingType::ComparisonSampler => {}
|
| binding_model::BindingType::ComparisonSampler => {}
|
||||||
_ => panic!("Wrong binding type for a sampler: {:?}", decl.ty),
|
_ => panic!("Wrong binding type for a sampler: {:?}", decl.ty),
|
||||||
}
|
}
|
||||||
let sampler = used
|
let sampler = used
|
||||||
@ -1149,8 +1156,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
wgt::TextureUsage::SAMPLED,
|
wgt::TextureUsage::SAMPLED,
|
||||||
hal::image::Layout::ShaderReadOnlyOptimal,
|
hal::image::Layout::ShaderReadOnlyOptimal,
|
||||||
),
|
),
|
||||||
binding_model::BindingType::ReadonlyStorageTexture |
|
binding_model::BindingType::ReadonlyStorageTexture
|
||||||
binding_model::BindingType::WriteonlyStorageTexture => {
|
| binding_model::BindingType::WriteonlyStorageTexture => {
|
||||||
(wgt::TextureUsage::STORAGE, hal::image::Layout::General)
|
(wgt::TextureUsage::STORAGE, hal::image::Layout::General)
|
||||||
}
|
}
|
||||||
_ => panic!("Mismatched texture binding for {:?}", decl),
|
_ => panic!("Mismatched texture binding for {:?}", decl),
|
||||||
@ -1211,12 +1218,14 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
};
|
};
|
||||||
let ref_count = bind_group.life_guard.add_ref();
|
let ref_count = bind_group.life_guard.add_ref();
|
||||||
|
|
||||||
|
|
||||||
let id = hub
|
let id = hub
|
||||||
.bind_groups
|
.bind_groups
|
||||||
.register_identity(id_in, bind_group, &mut token);
|
.register_identity(id_in, bind_group, &mut token);
|
||||||
log::debug!("Bind group {:?} {:#?}",
|
log::debug!(
|
||||||
id, hub.bind_groups.read(&mut token).0[id].used);
|
"Bind group {:?} {:#?}",
|
||||||
|
id,
|
||||||
|
hub.bind_groups.read(&mut token).0[id].used
|
||||||
|
);
|
||||||
|
|
||||||
device
|
device
|
||||||
.trackers
|
.trackers
|
||||||
@ -1241,7 +1250,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||||
device_guard[device_id]
|
device_guard[device_id]
|
||||||
.lock_life(&mut token)
|
.lock_life(&mut token)
|
||||||
.suspected_resources.bind_groups.push(bind_group_id);
|
.suspected_resources
|
||||||
|
.bind_groups
|
||||||
|
.push(bind_group_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn device_create_shader_module<B: GfxBackend>(
|
pub fn device_create_shader_module<B: GfxBackend>(
|
||||||
@ -1256,12 +1267,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let device = &device_guard[device_id];
|
let device = &device_guard[device_id];
|
||||||
|
|
||||||
let spv = unsafe { slice::from_raw_parts(desc.code.bytes, desc.code.length) };
|
let spv = unsafe { slice::from_raw_parts(desc.code.bytes, desc.code.length) };
|
||||||
let raw = unsafe {
|
let raw = unsafe { device.raw.create_shader_module(spv).unwrap() };
|
||||||
device
|
|
||||||
.raw
|
|
||||||
.create_shader_module(spv)
|
|
||||||
.unwrap()
|
|
||||||
};
|
|
||||||
let shader = pipeline::ShaderModule {
|
let shader = pipeline::ShaderModule {
|
||||||
raw,
|
raw,
|
||||||
device_id: Stored {
|
device_id: Stored {
|
||||||
@ -1280,7 +1286,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||||
let (module, _) = hub.shader_modules.unregister(shader_module_id, &mut token);
|
let (module, _) = hub.shader_modules.unregister(shader_module_id, &mut token);
|
||||||
unsafe {
|
unsafe {
|
||||||
device_guard[module.device_id.value].raw.destroy_shader_module(module.raw);
|
device_guard[module.device_id.value]
|
||||||
|
.raw
|
||||||
|
.destroy_shader_module(module.raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1301,31 +1309,30 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
ref_count: device.life_guard.add_ref(),
|
ref_count: device.life_guard.add_ref(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let lowest_active_index = device
|
let lowest_active_index = device.lock_life(&mut token).lowest_active_submission();
|
||||||
.lock_life(&mut token)
|
|
||||||
.lowest_active_submission();
|
|
||||||
|
|
||||||
let mut command_buffer = device
|
let mut command_buffer = device.com_allocator.allocate(
|
||||||
.com_allocator
|
dev_stored,
|
||||||
.allocate(dev_stored, &device.raw, device.features, lowest_active_index);
|
&device.raw,
|
||||||
|
device.features,
|
||||||
|
lowest_active_index,
|
||||||
|
);
|
||||||
unsafe {
|
unsafe {
|
||||||
let raw_command_buffer = command_buffer.raw.last_mut().unwrap();
|
let raw_command_buffer = command_buffer.raw.last_mut().unwrap();
|
||||||
if !desc.label.is_null() {
|
if !desc.label.is_null() {
|
||||||
let label = ffi::CStr::from_ptr(desc.label).to_string_lossy();
|
let label = ffi::CStr::from_ptr(desc.label).to_string_lossy();
|
||||||
device.raw.set_command_buffer_name(raw_command_buffer, &label);
|
device
|
||||||
|
.raw
|
||||||
|
.set_command_buffer_name(raw_command_buffer, &label);
|
||||||
}
|
}
|
||||||
raw_command_buffer.begin_primary(
|
raw_command_buffer.begin_primary(hal::command::CommandBufferFlags::ONE_TIME_SUBMIT);
|
||||||
hal::command::CommandBufferFlags::ONE_TIME_SUBMIT,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hub.command_buffers
|
hub.command_buffers
|
||||||
.register_identity(id_in, command_buffer, &mut token)
|
.register_identity(id_in, command_buffer, &mut token)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn command_encoder_destroy<B: GfxBackend>(
|
pub fn command_encoder_destroy<B: GfxBackend>(&self, command_encoder_id: id::CommandEncoderId) {
|
||||||
&self, command_encoder_id: id::CommandEncoderId
|
|
||||||
) {
|
|
||||||
let hub = B::hub(self);
|
let hub = B::hub(self);
|
||||||
let mut token = Token::root();
|
let mut token = Token::root();
|
||||||
|
|
||||||
@ -1387,13 +1394,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
|
|
||||||
device
|
device
|
||||||
.lock_life(&mut token)
|
.lock_life(&mut token)
|
||||||
.suspected_resources.extend(&device.temp_suspected);
|
.suspected_resources
|
||||||
|
.extend(&device.temp_suspected);
|
||||||
device.com_allocator.discard(comb);
|
device.com_allocator.discard(comb);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn command_buffer_destroy<B: GfxBackend>(
|
pub fn command_buffer_destroy<B: GfxBackend>(&self, command_buffer_id: id::CommandBufferId) {
|
||||||
&self, command_buffer_id: id::CommandBufferId
|
|
||||||
) {
|
|
||||||
self.command_encoder_destroy::<B>(command_buffer_id)
|
self.command_encoder_destroy::<B>(command_buffer_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1497,9 +1503,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
// execute resource transitions
|
// execute resource transitions
|
||||||
let mut transit = device.com_allocator.extend(comb);
|
let mut transit = device.com_allocator.extend(comb);
|
||||||
unsafe {
|
unsafe {
|
||||||
transit.begin_primary(
|
transit.begin_primary(hal::command::CommandBufferFlags::ONE_TIME_SUBMIT);
|
||||||
hal::command::CommandBufferFlags::ONE_TIME_SUBMIT,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
log::trace!("Stitching command buffer {:?} before submission", cmb_id);
|
log::trace!("Stitching command buffer {:?} before submission", cmb_id);
|
||||||
command::CommandBuffer::insert_barriers(
|
command::CommandBuffer::insert_barriers(
|
||||||
@ -1530,7 +1534,6 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
signal_semaphores: signal_swapchain_semaphores
|
signal_semaphores: signal_swapchain_semaphores
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|sc_id| &swap_chain_guard[sc_id].semaphore),
|
.map(|sc_id| &swap_chain_guard[sc_id].semaphore),
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -1547,9 +1550,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let device = &device_guard[queue_id];
|
let device = &device_guard[queue_id];
|
||||||
|
|
||||||
let callbacks = device.maintain(self, false, &mut token);
|
let callbacks = device.maintain(self, false, &mut token);
|
||||||
device
|
device.lock_life(&mut token).track_submission(
|
||||||
.lock_life(&mut token)
|
submit_index,
|
||||||
.track_submission(submit_index, fence, &device.temp_suspected);
|
fence,
|
||||||
|
&device.temp_suspected,
|
||||||
|
);
|
||||||
|
|
||||||
// finally, return the command buffers to the allocator
|
// finally, return the command buffers to the allocator
|
||||||
for &cmb_id in command_buffer_ids {
|
for &cmb_id in command_buffer_ids {
|
||||||
@ -1681,7 +1686,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
samples: sc,
|
samples: sc,
|
||||||
ops: hal::pass::AttachmentOps::PRESERVE,
|
ops: hal::pass::AttachmentOps::PRESERVE,
|
||||||
stencil_ops: hal::pass::AttachmentOps::DONT_CARE,
|
stencil_ops: hal::pass::AttachmentOps::DONT_CARE,
|
||||||
layouts: hal::image::Layout::General .. hal::image::Layout::General,
|
layouts: hal::image::Layout::General..hal::image::Layout::General,
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
// We can ignore the resolves as the vulkan specs says:
|
// We can ignore the resolves as the vulkan specs says:
|
||||||
@ -1694,7 +1699,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
samples: sc,
|
samples: sc,
|
||||||
ops: hal::pass::AttachmentOps::PRESERVE,
|
ops: hal::pass::AttachmentOps::PRESERVE,
|
||||||
stencil_ops: hal::pass::AttachmentOps::PRESERVE,
|
stencil_ops: hal::pass::AttachmentOps::PRESERVE,
|
||||||
layouts: hal::image::Layout::General .. hal::image::Layout::General,
|
layouts: hal::image::Layout::General..hal::image::Layout::General,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1715,7 +1720,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let subpass = hal::pass::SubpassDesc {
|
let subpass = hal::pass::SubpassDesc {
|
||||||
colors: &color_ids[.. desc.color_states_length],
|
colors: &color_ids[..desc.color_states_length],
|
||||||
depth_stencil: depth_stencil_state.map(|_| &depth_id),
|
depth_stencil: depth_stencil_state.map(|_| &depth_id),
|
||||||
inputs: &[],
|
inputs: &[],
|
||||||
resolves: &[],
|
resolves: &[],
|
||||||
@ -1844,7 +1849,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
|
|
||||||
device_guard[device_id]
|
device_guard[device_id]
|
||||||
.lock_life(&mut token)
|
.lock_life(&mut token)
|
||||||
.suspected_resources.render_pipelines.push(render_pipeline_id);
|
.suspected_resources
|
||||||
|
.render_pipelines
|
||||||
|
.push(render_pipeline_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn device_create_compute_pipeline<B: GfxBackend>(
|
pub fn device_create_compute_pipeline<B: GfxBackend>(
|
||||||
@ -1906,7 +1913,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
.register_identity(id_in, pipeline, &mut token)
|
.register_identity(id_in, pipeline, &mut token)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute_pipeline_destroy<B: GfxBackend>(&self, compute_pipeline_id: id::ComputePipelineId) {
|
pub fn compute_pipeline_destroy<B: GfxBackend>(
|
||||||
|
&self,
|
||||||
|
compute_pipeline_id: id::ComputePipelineId,
|
||||||
|
) {
|
||||||
let hub = B::hub(self);
|
let hub = B::hub(self);
|
||||||
let mut token = Token::root();
|
let mut token = Token::root();
|
||||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||||
@ -1920,8 +1930,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
|
|
||||||
device_guard[device_id]
|
device_guard[device_id]
|
||||||
.lock_life(&mut token)
|
.lock_life(&mut token)
|
||||||
.suspected_resources.compute_pipelines.push(compute_pipeline_id);
|
.suspected_resources
|
||||||
|
.compute_pipelines
|
||||||
|
.push(compute_pipeline_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn device_create_swap_chain<B: GfxBackend>(
|
pub fn device_create_swap_chain<B: GfxBackend>(
|
||||||
@ -1980,7 +1991,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let num_frames = swap_chain::DESIRED_NUM_FRAMES
|
let num_frames = swap_chain::DESIRED_NUM_FRAMES
|
||||||
.max(*caps.image_count.start())
|
.max(*caps.image_count.start())
|
||||||
.min(*caps.image_count.end());
|
.min(*caps.image_count.end());
|
||||||
let mut config = swap_chain::swap_chain_descriptor_to_hal(&desc, num_frames, device.features);
|
let mut config =
|
||||||
|
swap_chain::swap_chain_descriptor_to_hal(&desc, num_frames, device.features);
|
||||||
if let Some(formats) = formats {
|
if let Some(formats) = formats {
|
||||||
assert!(
|
assert!(
|
||||||
formats.contains(&config.format),
|
formats.contains(&config.format),
|
||||||
@ -2100,14 +2112,16 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
operation.call_error();
|
operation.call_error();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resource::BufferMapState::Idle => resource::BufferMapState::Waiting(resource::BufferPendingMapping {
|
resource::BufferMapState::Idle => {
|
||||||
sub_range: hal::buffer::SubRange {
|
resource::BufferMapState::Waiting(resource::BufferPendingMapping {
|
||||||
offset: range.start,
|
sub_range: hal::buffer::SubRange {
|
||||||
size: Some(range.end - range.start),
|
offset: range.start,
|
||||||
},
|
size: Some(range.end - range.start),
|
||||||
op: operation,
|
},
|
||||||
parent_ref_count: buffer.life_guard.add_ref(),
|
op: operation,
|
||||||
}),
|
parent_ref_count: buffer.life_guard.add_ref(),
|
||||||
|
})
|
||||||
|
}
|
||||||
};
|
};
|
||||||
log::debug!("Buffer {:?} map state -> Waiting", buffer_id);
|
log::debug!("Buffer {:?} map state -> Waiting", buffer_id);
|
||||||
|
|
||||||
@ -2122,9 +2136,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
.buffers
|
.buffers
|
||||||
.change_replace(buffer_id, &ref_count, (), usage);
|
.change_replace(buffer_id, &ref_count, (), usage);
|
||||||
|
|
||||||
device
|
device.lock_life(&mut token).map(buffer_id, ref_count);
|
||||||
.lock_life(&mut token)
|
|
||||||
.map(buffer_id, ref_count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn buffer_unmap<B: GfxBackend>(&self, buffer_id: id::BufferId) {
|
pub fn buffer_unmap<B: GfxBackend>(&self, buffer_id: id::BufferId) {
|
||||||
@ -2136,9 +2148,6 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let buffer = &mut buffer_guard[buffer_id];
|
let buffer = &mut buffer_guard[buffer_id];
|
||||||
|
|
||||||
log::debug!("Buffer {:?} map state -> Idle", buffer_id);
|
log::debug!("Buffer {:?} map state -> Idle", buffer_id);
|
||||||
unmap_buffer(
|
unmap_buffer(&device_guard[buffer.device_id.value].raw, buffer);
|
||||||
&device_guard[buffer.device_id.value].raw,
|
|
||||||
buffer,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,40 +8,25 @@ use crate::{
|
|||||||
command::CommandBuffer,
|
command::CommandBuffer,
|
||||||
device::Device,
|
device::Device,
|
||||||
id::{
|
id::{
|
||||||
AdapterId,
|
AdapterId, BindGroupId, BindGroupLayoutId, BufferId, CommandBufferId, ComputePipelineId,
|
||||||
BindGroupId,
|
DeviceId, PipelineLayoutId, RenderPipelineId, SamplerId, ShaderModuleId, SurfaceId,
|
||||||
BindGroupLayoutId,
|
SwapChainId, TextureId, TextureViewId, TypedId,
|
||||||
BufferId,
|
|
||||||
CommandBufferId,
|
|
||||||
ComputePipelineId,
|
|
||||||
DeviceId,
|
|
||||||
PipelineLayoutId,
|
|
||||||
RenderPipelineId,
|
|
||||||
SamplerId,
|
|
||||||
ShaderModuleId,
|
|
||||||
SurfaceId,
|
|
||||||
SwapChainId,
|
|
||||||
TextureId,
|
|
||||||
TextureViewId,
|
|
||||||
TypedId,
|
|
||||||
},
|
},
|
||||||
instance::{Adapter, Instance, Surface},
|
instance::{Adapter, Instance, Surface},
|
||||||
pipeline::{ComputePipeline, RenderPipeline, ShaderModule},
|
pipeline::{ComputePipeline, RenderPipeline, ShaderModule},
|
||||||
resource::{Buffer, Sampler, Texture, TextureView},
|
resource::{Buffer, Sampler, Texture, TextureView},
|
||||||
swap_chain::SwapChain,
|
swap_chain::SwapChain,
|
||||||
Epoch,
|
Epoch, Index,
|
||||||
Index,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use wgt::Backend;
|
|
||||||
use parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
use parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||||
use vec_map::VecMap;
|
use vec_map::VecMap;
|
||||||
|
use wgt::Backend;
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::{fmt::Debug, iter, marker::PhantomData, ops};
|
use std::{fmt::Debug, iter, marker::PhantomData, ops};
|
||||||
|
|
||||||
|
|
||||||
/// A simple structure to manage identities of objects.
|
/// A simple structure to manage identities of objects.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct IdentityManager {
|
pub struct IdentityManager {
|
||||||
@ -136,11 +121,9 @@ impl<T, I: TypedId> Storage<T, I> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter(&self, backend: Backend) -> impl Iterator<Item = (I, &T)> {
|
pub fn iter(&self, backend: Backend) -> impl Iterator<Item = (I, &T)> {
|
||||||
self.map
|
self.map.iter().map(move |(index, (value, storage_epoch))| {
|
||||||
.iter()
|
(I::zip(index as Index, *storage_epoch, backend), value)
|
||||||
.map(move |(index, (value, storage_epoch))| {
|
})
|
||||||
(I::zip(index as Index, *storage_epoch, backend), value)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,7 +235,6 @@ impl<'a, T> Drop for Token<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub trait IdentityHandler<I>: Debug {
|
pub trait IdentityHandler<I>: Debug {
|
||||||
type Input: Clone + Debug;
|
type Input: Clone + Debug;
|
||||||
fn process(&self, id: Self::Input, backend: Backend) -> I;
|
fn process(&self, id: Self::Input, backend: Backend) -> I;
|
||||||
@ -281,35 +263,35 @@ impl<I: TypedId + Debug> IdentityHandlerFactory<I> for IdentityManagerFactory {
|
|||||||
type Filter = Mutex<IdentityManager>;
|
type Filter = Mutex<IdentityManager>;
|
||||||
fn spawn(&self, min_index: Index) -> Self::Filter {
|
fn spawn(&self, min_index: Index) -> Self::Filter {
|
||||||
let mut man = IdentityManager::default();
|
let mut man = IdentityManager::default();
|
||||||
man.free.extend(0 .. min_index);
|
man.free.extend(0..min_index);
|
||||||
man.epochs.extend(iter::repeat(1).take(min_index as usize));
|
man.epochs.extend(iter::repeat(1).take(min_index as usize));
|
||||||
Mutex::new(man)
|
Mutex::new(man)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait GlobalIdentityHandlerFactory:
|
pub trait GlobalIdentityHandlerFactory:
|
||||||
IdentityHandlerFactory<AdapterId> +
|
IdentityHandlerFactory<AdapterId>
|
||||||
IdentityHandlerFactory<DeviceId> +
|
+ IdentityHandlerFactory<DeviceId>
|
||||||
IdentityHandlerFactory<SwapChainId> +
|
+ IdentityHandlerFactory<SwapChainId>
|
||||||
IdentityHandlerFactory<PipelineLayoutId> +
|
+ IdentityHandlerFactory<PipelineLayoutId>
|
||||||
IdentityHandlerFactory<ShaderModuleId> +
|
+ IdentityHandlerFactory<ShaderModuleId>
|
||||||
IdentityHandlerFactory<BindGroupLayoutId> +
|
+ IdentityHandlerFactory<BindGroupLayoutId>
|
||||||
IdentityHandlerFactory<BindGroupId> +
|
+ IdentityHandlerFactory<BindGroupId>
|
||||||
IdentityHandlerFactory<CommandBufferId> +
|
+ IdentityHandlerFactory<CommandBufferId>
|
||||||
IdentityHandlerFactory<RenderPipelineId> +
|
+ IdentityHandlerFactory<RenderPipelineId>
|
||||||
IdentityHandlerFactory<ComputePipelineId> +
|
+ IdentityHandlerFactory<ComputePipelineId>
|
||||||
IdentityHandlerFactory<BufferId> +
|
+ IdentityHandlerFactory<BufferId>
|
||||||
IdentityHandlerFactory<TextureId> +
|
+ IdentityHandlerFactory<TextureId>
|
||||||
IdentityHandlerFactory<TextureViewId> +
|
+ IdentityHandlerFactory<TextureViewId>
|
||||||
IdentityHandlerFactory<SamplerId> +
|
+ IdentityHandlerFactory<SamplerId>
|
||||||
IdentityHandlerFactory<SurfaceId>
|
+ IdentityHandlerFactory<SurfaceId>
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl GlobalIdentityHandlerFactory for IdentityManagerFactory {}
|
impl GlobalIdentityHandlerFactory for IdentityManagerFactory {}
|
||||||
|
|
||||||
pub type Input<G, I> = <<G as IdentityHandlerFactory<I>>::Filter as IdentityHandler<I>>::Input;
|
pub type Input<G, I> = <<G as IdentityHandlerFactory<I>>::Filter as IdentityHandler<I>>::Input;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Registry<T, I: TypedId, F: IdentityHandlerFactory<I>> {
|
pub struct Registry<T, I: TypedId, F: IdentityHandlerFactory<I>> {
|
||||||
identity: F::Filter,
|
identity: F::Filter,
|
||||||
|
@ -5,15 +5,19 @@
|
|||||||
use crate::{Epoch, Index};
|
use crate::{Epoch, Index};
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde_crate::{Deserialize, Serialize};
|
use serde_crate::{Deserialize, Serialize};
|
||||||
use wgt::Backend;
|
|
||||||
use std::{fmt, marker::PhantomData, mem, num::NonZeroU64};
|
use std::{fmt, marker::PhantomData, mem, num::NonZeroU64};
|
||||||
|
use wgt::Backend;
|
||||||
|
|
||||||
const BACKEND_BITS: usize = 3;
|
const BACKEND_BITS: usize = 3;
|
||||||
const EPOCH_MASK: u32 = (1 << (32 - BACKEND_BITS)) - 1;
|
const EPOCH_MASK: u32 = (1 << (32 - BACKEND_BITS)) - 1;
|
||||||
type Dummy = crate::backend::Empty;
|
type Dummy = crate::backend::Empty;
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate="serde_crate"))]
|
#[cfg_attr(
|
||||||
|
feature = "serde",
|
||||||
|
derive(Serialize, Deserialize),
|
||||||
|
serde(crate = "serde_crate")
|
||||||
|
)]
|
||||||
pub struct Id<T>(NonZeroU64, PhantomData<T>);
|
pub struct Id<T>(NonZeroU64, PhantomData<T>);
|
||||||
|
|
||||||
// required for PeekPoke
|
// required for PeekPoke
|
||||||
@ -75,7 +79,7 @@ impl<T> Eq for Id<T> {}
|
|||||||
|
|
||||||
unsafe impl<T> peek_poke::Poke for Id<T> {
|
unsafe impl<T> peek_poke::Poke for Id<T> {
|
||||||
fn max_size() -> usize {
|
fn max_size() -> usize {
|
||||||
mem::size_of::<u64>()
|
mem::size_of::<u64>()
|
||||||
}
|
}
|
||||||
unsafe fn poke_into(&self, data: *mut u8) -> *mut u8 {
|
unsafe fn poke_into(&self, data: *mut u8) -> *mut u8 {
|
||||||
self.0.get().poke_into(data)
|
self.0.get().poke_into(data)
|
||||||
@ -112,7 +116,6 @@ impl<T> TypedId for Id<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub type AdapterId = Id<crate::instance::Adapter<Dummy>>;
|
pub type AdapterId = Id<crate::instance::Adapter<Dummy>>;
|
||||||
pub type SurfaceId = Id<crate::instance::Surface>;
|
pub type SurfaceId = Id<crate::instance::Surface>;
|
||||||
// Device
|
// Device
|
||||||
|
@ -17,20 +17,19 @@ use serde_crate::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use hal::{
|
use hal::{
|
||||||
self,
|
self,
|
||||||
adapter::{
|
adapter::{AdapterInfo as HalAdapterInfo, DeviceType as HalDeviceType, PhysicalDevice as _},
|
||||||
AdapterInfo as HalAdapterInfo,
|
|
||||||
DeviceType as HalDeviceType,
|
|
||||||
PhysicalDevice as _,
|
|
||||||
},
|
|
||||||
queue::QueueFamily as _,
|
queue::QueueFamily as _,
|
||||||
window::Surface as _,
|
window::Surface as _,
|
||||||
Instance as _,
|
Instance as _,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate="serde_crate"))]
|
#[cfg_attr(
|
||||||
|
feature = "serde",
|
||||||
|
derive(Serialize, Deserialize),
|
||||||
|
serde(crate = "serde_crate")
|
||||||
|
)]
|
||||||
pub struct RequestAdapterOptions {
|
pub struct RequestAdapterOptions {
|
||||||
pub power_preference: PowerPreference,
|
pub power_preference: PowerPreference,
|
||||||
pub compatible_surface: Option<SurfaceId>,
|
pub compatible_surface: Option<SurfaceId>,
|
||||||
@ -125,7 +124,11 @@ pub struct Adapter<B: hal::Backend> {
|
|||||||
|
|
||||||
/// Metadata about a backend adapter.
|
/// Metadata about a backend adapter.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate="serde_crate"))]
|
#[cfg_attr(
|
||||||
|
feature = "serde",
|
||||||
|
derive(Serialize, Deserialize),
|
||||||
|
serde(crate = "serde_crate")
|
||||||
|
)]
|
||||||
pub struct AdapterInfo {
|
pub struct AdapterInfo {
|
||||||
/// Adapter name
|
/// Adapter name
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -160,7 +163,11 @@ impl AdapterInfo {
|
|||||||
|
|
||||||
/// Supported physical device types
|
/// Supported physical device types
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate="serde_crate"))]
|
#[cfg_attr(
|
||||||
|
feature = "serde",
|
||||||
|
derive(Serialize, Deserialize),
|
||||||
|
serde(crate = "serde_crate")
|
||||||
|
)]
|
||||||
pub enum DeviceType {
|
pub enum DeviceType {
|
||||||
/// Other
|
/// Other
|
||||||
Other,
|
Other,
|
||||||
@ -300,13 +307,17 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let mut adapters_vk = match instance.vulkan {
|
let mut adapters_vk = match instance.vulkan {
|
||||||
Some(ref inst) if id_vulkan.is_some() => {
|
Some(ref inst) if id_vulkan.is_some() => {
|
||||||
let mut adapters = inst.enumerate_adapters();
|
let mut adapters = inst.enumerate_adapters();
|
||||||
if let Some(&Surface { vulkan: Some(ref surface), .. }) = compatible_surface {
|
if let Some(&Surface {
|
||||||
adapters.retain(|a|
|
vulkan: Some(ref surface),
|
||||||
|
..
|
||||||
|
}) = compatible_surface
|
||||||
|
{
|
||||||
|
adapters.retain(|a| {
|
||||||
a.queue_families
|
a.queue_families
|
||||||
.iter()
|
.iter()
|
||||||
.find(|qf| qf.queue_type().supports_graphics())
|
.find(|qf| qf.queue_type().supports_graphics())
|
||||||
.map_or(false, |qf| surface.supports_queue_family(qf))
|
.map_or(false, |qf| surface.supports_queue_family(qf))
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
|
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
|
||||||
adapters
|
adapters
|
||||||
@ -317,12 +328,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let mut adapters_mtl = if id_metal.is_some() {
|
let mut adapters_mtl = if id_metal.is_some() {
|
||||||
let mut adapters = instance.metal.enumerate_adapters();
|
let mut adapters = instance.metal.enumerate_adapters();
|
||||||
if let Some(surface) = compatible_surface {
|
if let Some(surface) = compatible_surface {
|
||||||
adapters.retain(|a|
|
adapters.retain(|a| {
|
||||||
a.queue_families
|
a.queue_families
|
||||||
.iter()
|
.iter()
|
||||||
.find(|qf| qf.queue_type().supports_graphics())
|
.find(|qf| qf.queue_type().supports_graphics())
|
||||||
.map_or(false, |qf| surface.metal.supports_queue_family(qf))
|
.map_or(false, |qf| surface.metal.supports_queue_family(qf))
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
|
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
|
||||||
adapters
|
adapters
|
||||||
@ -333,13 +344,17 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let mut adapters_dx12 = match instance.dx12 {
|
let mut adapters_dx12 = match instance.dx12 {
|
||||||
Some(ref inst) if id_dx12.is_some() => {
|
Some(ref inst) if id_dx12.is_some() => {
|
||||||
let mut adapters = inst.enumerate_adapters();
|
let mut adapters = inst.enumerate_adapters();
|
||||||
if let Some(&Surface { dx12: Some(ref surface), .. }) = compatible_surface {
|
if let Some(&Surface {
|
||||||
adapters.retain(|a|
|
dx12: Some(ref surface),
|
||||||
|
..
|
||||||
|
}) = compatible_surface
|
||||||
|
{
|
||||||
|
adapters.retain(|a| {
|
||||||
a.queue_families
|
a.queue_families
|
||||||
.iter()
|
.iter()
|
||||||
.find(|qf| qf.queue_type().supports_graphics())
|
.find(|qf| qf.queue_type().supports_graphics())
|
||||||
.map_or(false, |qf| surface.supports_queue_family(qf))
|
.map_or(false, |qf| surface.supports_queue_family(qf))
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
|
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
|
||||||
adapters
|
adapters
|
||||||
@ -350,12 +365,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let mut adapters_dx11 = if id_dx11.is_some() {
|
let mut adapters_dx11 = if id_dx11.is_some() {
|
||||||
let mut adapters = instance.dx11.enumerate_adapters();
|
let mut adapters = instance.dx11.enumerate_adapters();
|
||||||
if let Some(surface) = compatible_surface {
|
if let Some(surface) = compatible_surface {
|
||||||
adapters.retain(|a|
|
adapters.retain(|a| {
|
||||||
a.queue_families
|
a.queue_families
|
||||||
.iter()
|
.iter()
|
||||||
.find(|qf| qf.queue_type().supports_graphics())
|
.find(|qf| qf.queue_type().supports_graphics())
|
||||||
.map_or(false, |qf| surface.dx11.supports_queue_family(qf))
|
.map_or(false, |qf| surface.dx11.supports_queue_family(qf))
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
|
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
|
||||||
adapters
|
adapters
|
||||||
@ -388,14 +403,15 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let preferred_gpu = match desc.power_preference {
|
let preferred_gpu = match desc.power_preference {
|
||||||
PowerPreference::Default => {
|
PowerPreference::Default => match power::is_battery_discharging() {
|
||||||
match power::is_battery_discharging() {
|
Ok(false) => discrete.or(integrated).or(other).or(virt),
|
||||||
Ok(false) => discrete.or(integrated).or(other).or(virt),
|
Ok(true) => integrated.or(discrete).or(other).or(virt),
|
||||||
Ok(true) => integrated.or(discrete).or(other).or(virt),
|
Err(err) => {
|
||||||
Err(err) => {
|
log::debug!(
|
||||||
log::debug!("Power info unavailable, preferring integrated gpu ({})", err);
|
"Power info unavailable, preferring integrated gpu ({})",
|
||||||
integrated.or(discrete).or(other).or(virt)
|
err
|
||||||
}
|
);
|
||||||
|
integrated.or(discrete).or(other).or(virt)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PowerPreference::LowPower => integrated.or(other).or(discrete).or(virt),
|
PowerPreference::LowPower => integrated.or(other).or(discrete).or(virt),
|
||||||
@ -500,13 +516,15 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let device = {
|
let device = {
|
||||||
let (adapter_guard, _) = hub.adapters.read(&mut token);
|
let (adapter_guard, _) = hub.adapters.read(&mut token);
|
||||||
let adapter = &adapter_guard[adapter_id].raw;
|
let adapter = &adapter_guard[adapter_id].raw;
|
||||||
let wishful_features =
|
let wishful_features = hal::Features::VERTEX_STORES_AND_ATOMICS
|
||||||
hal::Features::VERTEX_STORES_AND_ATOMICS |
|
| hal::Features::FRAGMENT_STORES_AND_ATOMICS
|
||||||
hal::Features::FRAGMENT_STORES_AND_ATOMICS |
|
| hal::Features::NDC_Y_UP;
|
||||||
hal::Features::NDC_Y_UP;
|
|
||||||
let enabled_features = adapter.physical_device.features() & wishful_features;
|
let enabled_features = adapter.physical_device.features() & wishful_features;
|
||||||
if enabled_features != wishful_features {
|
if enabled_features != wishful_features {
|
||||||
log::warn!("Missing features: {:?}", wishful_features - enabled_features);
|
log::warn!(
|
||||||
|
"Missing features: {:?}",
|
||||||
|
wishful_features - enabled_features
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let family = adapter
|
let family = adapter
|
||||||
|
@ -103,8 +103,7 @@ impl LifeGuard {
|
|||||||
|
|
||||||
/// Returns `true` if the resource is still needed by the user.
|
/// Returns `true` if the resource is still needed by the user.
|
||||||
fn use_at(&self, submit_index: SubmissionIndex) -> bool {
|
fn use_at(&self, submit_index: SubmissionIndex) -> bool {
|
||||||
self.submission_index
|
self.submission_index.store(submit_index, Ordering::Release);
|
||||||
.store(submit_index, Ordering::Release);
|
|
||||||
self.ref_count.is_some()
|
self.ref_count.is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,13 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
device::RenderPassContext,
|
device::RenderPassContext,
|
||||||
id::{DeviceId, PipelineLayoutId, ShaderModuleId},
|
id::{DeviceId, PipelineLayoutId, ShaderModuleId},
|
||||||
LifeGuard,
|
LifeGuard, RawString, RefCount, Stored, U32Array,
|
||||||
RawString,
|
|
||||||
RefCount,
|
|
||||||
Stored,
|
|
||||||
U32Array
|
|
||||||
};
|
};
|
||||||
use wgt::{BufferAddress, ColorStateDescriptor, DepthStencilStateDescriptor, IndexFormat, InputStepMode, PrimitiveTopology, RasterizationStateDescriptor, VertexAttributeDescriptor};
|
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
|
use wgt::{
|
||||||
|
BufferAddress, ColorStateDescriptor, DepthStencilStateDescriptor, IndexFormat, InputStepMode,
|
||||||
|
PrimitiveTopology, RasterizationStateDescriptor, VertexAttributeDescriptor,
|
||||||
|
};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -40,7 +39,7 @@ pub struct ShaderModuleDescriptor {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ShaderModule<B: hal::Backend> {
|
pub struct ShaderModule<B: hal::Backend> {
|
||||||
pub(crate) raw: B::ShaderModule,
|
pub(crate) raw: B::ShaderModule,
|
||||||
pub(crate) device_id: Stored<DeviceId>
|
pub(crate) device_id: Stored<DeviceId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -19,13 +19,16 @@ impl fmt::Display for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "battery", any(
|
#[cfg(all(
|
||||||
target_os = "linux",
|
feature = "battery",
|
||||||
target_os = "macos",
|
any(
|
||||||
target_os = "windows",
|
target_os = "linux",
|
||||||
target_os = "dragonfly",
|
target_os = "macos",
|
||||||
target_os = "freebsd"
|
target_os = "windows",
|
||||||
)))]
|
target_os = "dragonfly",
|
||||||
|
target_os = "freebsd"
|
||||||
|
)
|
||||||
|
))]
|
||||||
mod platform {
|
mod platform {
|
||||||
use super::Error;
|
use super::Error;
|
||||||
use battery::{self, Manager, State};
|
use battery::{self, Manager, State};
|
||||||
@ -49,13 +52,16 @@ mod platform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(not(feature = "battery"), not(any(
|
#[cfg(any(
|
||||||
target_os = "linux",
|
not(feature = "battery"),
|
||||||
target_os = "macos",
|
not(any(
|
||||||
target_os = "windows",
|
target_os = "linux",
|
||||||
target_os = "dragonfly",
|
target_os = "macos",
|
||||||
target_os = "freebsd"
|
target_os = "windows",
|
||||||
))))]
|
target_os = "dragonfly",
|
||||||
|
target_os = "freebsd"
|
||||||
|
))
|
||||||
|
))]
|
||||||
mod platform {
|
mod platform {
|
||||||
use super::Error;
|
use super::Error;
|
||||||
|
|
||||||
|
@ -5,18 +5,11 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
id::{DeviceId, SwapChainId, TextureId},
|
id::{DeviceId, SwapChainId, TextureId},
|
||||||
track::DUMMY_SELECTOR,
|
track::DUMMY_SELECTOR,
|
||||||
LifeGuard,
|
LifeGuard, RefCount, Stored,
|
||||||
RefCount,
|
|
||||||
Stored,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use wgt::{
|
|
||||||
BufferAddress,
|
|
||||||
BufferUsage,
|
|
||||||
TextureFormat,
|
|
||||||
TextureUsage,
|
|
||||||
};
|
|
||||||
use gfx_memory::MemoryBlock;
|
use gfx_memory::MemoryBlock;
|
||||||
|
use wgt::{BufferAddress, BufferUsage, TextureFormat, TextureUsage};
|
||||||
|
|
||||||
use std::{borrow::Borrow, fmt};
|
use std::{borrow::Borrow, fmt};
|
||||||
|
|
||||||
@ -47,7 +40,7 @@ pub enum BufferMapOperation {
|
|||||||
Write {
|
Write {
|
||||||
callback: crate::device::BufferMapWriteCallback,
|
callback: crate::device::BufferMapWriteCallback,
|
||||||
userdata: *mut u8,
|
userdata: *mut u8,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: clarify if/why this is needed here
|
//TODO: clarify if/why this is needed here
|
||||||
@ -69,11 +62,15 @@ impl BufferMapOperation {
|
|||||||
match self {
|
match self {
|
||||||
BufferMapOperation::Read { callback, userdata } => {
|
BufferMapOperation::Read { callback, userdata } => {
|
||||||
log::error!("wgpu_buffer_map_read_async failed: buffer mapping is pending");
|
log::error!("wgpu_buffer_map_read_async failed: buffer mapping is pending");
|
||||||
unsafe { callback(BufferMapAsyncStatus::Error, std::ptr::null(), userdata); }
|
unsafe {
|
||||||
|
callback(BufferMapAsyncStatus::Error, std::ptr::null(), userdata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
BufferMapOperation::Write { callback, userdata } => {
|
BufferMapOperation::Write { callback, userdata } => {
|
||||||
log::error!("wgpu_buffer_map_write_async failed: buffer mapping is pending");
|
log::error!("wgpu_buffer_map_write_async failed: buffer mapping is pending");
|
||||||
unsafe { callback(BufferMapAsyncStatus::Error, std::ptr::null_mut(), userdata); }
|
unsafe {
|
||||||
|
callback(BufferMapAsyncStatus::Error, std::ptr::null_mut(), userdata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,15 +36,11 @@ use crate::{
|
|||||||
conv,
|
conv,
|
||||||
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Input, Token},
|
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Input, Token},
|
||||||
id::{DeviceId, SwapChainId, TextureViewId},
|
id::{DeviceId, SwapChainId, TextureViewId},
|
||||||
resource,
|
resource, Features, LifeGuard, Stored,
|
||||||
Features,
|
|
||||||
LifeGuard,
|
|
||||||
Stored,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use wgt::SwapChainDescriptor;
|
|
||||||
use hal::{self, device::Device as _, queue::CommandQueue as _, window::PresentationSurface as _};
|
use hal::{self, device::Device as _, queue::CommandQueue as _, window::PresentationSurface as _};
|
||||||
|
use wgt::SwapChainDescriptor;
|
||||||
|
|
||||||
const FRAME_TIMEOUT_MS: u64 = 1000;
|
const FRAME_TIMEOUT_MS: u64 = 1000;
|
||||||
pub const DESIRED_NUM_FRAMES: u32 = 3;
|
pub const DESIRED_NUM_FRAMES: u32 = 3;
|
||||||
@ -118,7 +114,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("acquire_image() failed ({:?}), reconfiguring swapchain", e);
|
log::warn!("acquire_image() failed ({:?}), reconfiguring swapchain", e);
|
||||||
let desc = swap_chain_descriptor_to_hal(&sc.desc, sc.num_frames, device.features);
|
let desc =
|
||||||
|
swap_chain_descriptor_to_hal(&sc.desc, sc.num_frames, device.features);
|
||||||
unsafe {
|
unsafe {
|
||||||
suf.configure_swapchain(&device.raw, desc).unwrap();
|
suf.configure_swapchain(&device.raw, desc).unwrap();
|
||||||
suf.acquire_image(FRAME_TIMEOUT_MS * 1_000_000).unwrap()
|
suf.acquire_image(FRAME_TIMEOUT_MS * 1_000_000).unwrap()
|
||||||
@ -144,8 +141,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
samples: 1,
|
samples: 1,
|
||||||
range: hal::image::SubresourceRange {
|
range: hal::image::SubresourceRange {
|
||||||
aspects: hal::format::Aspects::COLOR,
|
aspects: hal::format::Aspects::COLOR,
|
||||||
layers: 0 .. 1,
|
layers: 0..1,
|
||||||
levels: 0 .. 1,
|
levels: 0..1,
|
||||||
},
|
},
|
||||||
life_guard: LifeGuard::new(),
|
life_guard: LifeGuard::new(),
|
||||||
};
|
};
|
||||||
|
@ -59,7 +59,7 @@ impl ResourceState for BufferState {
|
|||||||
let pending = PendingTransition {
|
let pending = PendingTransition {
|
||||||
id,
|
id,
|
||||||
selector: (),
|
selector: (),
|
||||||
usage: old .. usage,
|
usage: old..usage,
|
||||||
};
|
};
|
||||||
self.last = match output {
|
self.last = match output {
|
||||||
None => pending.collapse()?,
|
None => pending.collapse()?,
|
||||||
@ -92,7 +92,7 @@ impl ResourceState for BufferState {
|
|||||||
let pending = PendingTransition {
|
let pending = PendingTransition {
|
||||||
id,
|
id,
|
||||||
selector: (),
|
selector: (),
|
||||||
usage: old .. new,
|
usage: old..new,
|
||||||
};
|
};
|
||||||
match output {
|
match output {
|
||||||
None => pending.collapse()?,
|
None => pending.collapse()?,
|
||||||
@ -114,7 +114,7 @@ impl ResourceState for BufferState {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{id::TypedId};
|
use crate::id::TypedId;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn change() {
|
fn change() {
|
||||||
|
@ -10,26 +10,16 @@ use crate::{
|
|||||||
conv,
|
conv,
|
||||||
hub::Storage,
|
hub::Storage,
|
||||||
id::{self, TypedId},
|
id::{self, TypedId},
|
||||||
resource,
|
resource, Epoch, FastHashMap, Index, RefCount,
|
||||||
Epoch,
|
|
||||||
FastHashMap,
|
|
||||||
Index,
|
|
||||||
RefCount,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Borrow,
|
borrow::Borrow, collections::hash_map::Entry, fmt, marker::PhantomData, ops, vec::Drain,
|
||||||
collections::hash_map::Entry,
|
|
||||||
fmt,
|
|
||||||
marker::PhantomData,
|
|
||||||
ops,
|
|
||||||
vec::Drain,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use buffer::BufferState;
|
pub use buffer::BufferState;
|
||||||
pub use texture::TextureState;
|
pub use texture::TextureState;
|
||||||
|
|
||||||
|
|
||||||
/// A single unit of state tracking. It keeps an initial
|
/// A single unit of state tracking. It keeps an initial
|
||||||
/// usage as well as the last/current one, similar to `Range`.
|
/// usage as well as the last/current one, similar to `Range`.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
@ -136,7 +126,8 @@ impl PendingTransition<BufferState> {
|
|||||||
) -> hal::memory::Barrier<'a, B> {
|
) -> hal::memory::Barrier<'a, B> {
|
||||||
log::trace!("\tbuffer -> {:?}", self);
|
log::trace!("\tbuffer -> {:?}", self);
|
||||||
hal::memory::Barrier::Buffer {
|
hal::memory::Barrier::Buffer {
|
||||||
states: conv::map_buffer_state(self.usage.start) .. conv::map_buffer_state(self.usage.end),
|
states: conv::map_buffer_state(self.usage.start)
|
||||||
|
..conv::map_buffer_state(self.usage.end),
|
||||||
target: &buf.raw,
|
target: &buf.raw,
|
||||||
range: hal::buffer::SubRange::WHOLE,
|
range: hal::buffer::SubRange::WHOLE,
|
||||||
families: None,
|
families: None,
|
||||||
@ -154,11 +145,11 @@ impl PendingTransition<TextureState> {
|
|||||||
let aspects = tex.full_range.aspects;
|
let aspects = tex.full_range.aspects;
|
||||||
hal::memory::Barrier::Image {
|
hal::memory::Barrier::Image {
|
||||||
states: conv::map_texture_state(self.usage.start, aspects)
|
states: conv::map_texture_state(self.usage.start, aspects)
|
||||||
.. conv::map_texture_state(self.usage.end, aspects),
|
..conv::map_texture_state(self.usage.end, aspects),
|
||||||
target: &tex.raw,
|
target: &tex.raw,
|
||||||
range: hal::image::SubresourceRange {
|
range: hal::image::SubresourceRange {
|
||||||
aspects,
|
aspects,
|
||||||
.. self.selector
|
..self.selector
|
||||||
},
|
},
|
||||||
families: None,
|
families: None,
|
||||||
}
|
}
|
||||||
@ -179,9 +170,7 @@ impl<S: ResourceState + fmt::Debug> fmt::Debug for ResourceTracker<S> {
|
|||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
self.map
|
self.map
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(&index, res)| {
|
.map(|(&index, res)| ((index, res.epoch), &res.state))
|
||||||
((index, res.epoch), &res.state)
|
|
||||||
})
|
|
||||||
.collect::<FastHashMap<_, _>>()
|
.collect::<FastHashMap<_, _>>()
|
||||||
.fmt(formatter)
|
.fmt(formatter)
|
||||||
}
|
}
|
||||||
@ -256,12 +245,7 @@ impl<S: ResourceState> ResourceTracker<S> {
|
|||||||
/// Initialize a resource to be used.
|
/// Initialize a resource to be used.
|
||||||
///
|
///
|
||||||
/// Returns false if the resource is already registered.
|
/// Returns false if the resource is already registered.
|
||||||
pub fn init(
|
pub fn init(&mut self, id: S::Id, ref_count: RefCount, state: S) -> Result<(), &S> {
|
||||||
&mut self,
|
|
||||||
id: S::Id,
|
|
||||||
ref_count: RefCount,
|
|
||||||
state: S,
|
|
||||||
) -> Result<(), &S> {
|
|
||||||
let (index, epoch, backend) = id.unzip();
|
let (index, epoch, backend) = id.unzip();
|
||||||
debug_assert_eq!(backend, self.backend);
|
debug_assert_eq!(backend, self.backend);
|
||||||
match self.map.entry(index) {
|
match self.map.entry(index) {
|
||||||
@ -273,9 +257,7 @@ impl<S: ResourceState> ResourceTracker<S> {
|
|||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Entry::Occupied(e) => {
|
Entry::Occupied(e) => Err(&e.into_mut().state),
|
||||||
Err(&e.into_mut().state)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,9 +338,7 @@ impl<S: ResourceState> ResourceTracker<S> {
|
|||||||
Entry::Occupied(e) => {
|
Entry::Occupied(e) => {
|
||||||
assert_eq!(e.get().epoch, new.epoch);
|
assert_eq!(e.get().epoch, new.epoch);
|
||||||
let id = S::Id::zip(index, new.epoch, self.backend);
|
let id = S::Id::zip(index, new.epoch, self.backend);
|
||||||
e.into_mut()
|
e.into_mut().state.merge(id, &new.state, None)?;
|
||||||
.state
|
|
||||||
.merge(id, &new.state, None)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -367,10 +347,7 @@ impl<S: ResourceState> ResourceTracker<S> {
|
|||||||
|
|
||||||
/// Merge another tracker, adding it's transitions to `self`.
|
/// Merge another tracker, adding it's transitions to `self`.
|
||||||
/// Transitions the current usage to the new one.
|
/// Transitions the current usage to the new one.
|
||||||
pub fn merge_replace<'a>(
|
pub fn merge_replace<'a>(&'a mut self, other: &'a Self) -> Drain<PendingTransition<S>> {
|
||||||
&'a mut self,
|
|
||||||
other: &'a Self,
|
|
||||||
) -> Drain<PendingTransition<S>> {
|
|
||||||
for (&index, new) in other.map.iter() {
|
for (&index, new) in other.map.iter() {
|
||||||
match self.map.entry(index) {
|
match self.map.entry(index) {
|
||||||
Entry::Vacant(e) => {
|
Entry::Vacant(e) => {
|
||||||
@ -424,7 +401,6 @@ impl<S: ResourceState> ResourceTracker<S> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<I: Copy + fmt::Debug + TypedId> ResourceState for PhantomData<I> {
|
impl<I: Copy + fmt::Debug + TypedId> ResourceState for PhantomData<I> {
|
||||||
type Id = I;
|
type Id = I;
|
||||||
type Selector = ();
|
type Selector = ();
|
||||||
@ -458,7 +434,6 @@ impl<I: Copy + fmt::Debug + TypedId> ResourceState for PhantomData<I> {
|
|||||||
|
|
||||||
pub const DUMMY_SELECTOR: () = ();
|
pub const DUMMY_SELECTOR: () = ();
|
||||||
|
|
||||||
|
|
||||||
/// A set of trackers for all relevant resources.
|
/// A set of trackers for all relevant resources.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TrackerSet {
|
pub struct TrackerSet {
|
||||||
@ -515,7 +490,9 @@ impl TrackerSet {
|
|||||||
self.views.merge_extend(&other.views).unwrap();
|
self.views.merge_extend(&other.views).unwrap();
|
||||||
self.bind_groups.merge_extend(&other.bind_groups).unwrap();
|
self.bind_groups.merge_extend(&other.bind_groups).unwrap();
|
||||||
self.samplers.merge_extend(&other.samplers).unwrap();
|
self.samplers.merge_extend(&other.samplers).unwrap();
|
||||||
self.compute_pipes.merge_extend(&other.compute_pipes).unwrap();
|
self.compute_pipes
|
||||||
|
.merge_extend(&other.compute_pipes)
|
||||||
|
.unwrap();
|
||||||
self.render_pipes.merge_extend(&other.render_pipes).unwrap();
|
self.render_pipes.merge_extend(&other.render_pipes).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,13 +4,7 @@
|
|||||||
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use std::{
|
use std::{cmp::Ordering, fmt::Debug, iter, ops::Range, slice::Iter};
|
||||||
cmp::Ordering,
|
|
||||||
fmt::Debug,
|
|
||||||
iter,
|
|
||||||
ops::Range,
|
|
||||||
slice::Iter,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Structure that keeps track of a I -> T mapping,
|
/// Structure that keeps track of a I -> T mapping,
|
||||||
/// optimized for a case where keys of the same values
|
/// optimized for a case where keys of the same values
|
||||||
@ -66,7 +60,7 @@ impl<I: Copy + PartialOrd, T: Copy + PartialEq> RangedStates<I, T> {
|
|||||||
for a in self.ranges.iter() {
|
for a in self.ranges.iter() {
|
||||||
assert!(a.0.start < a.0.end);
|
assert!(a.0.start < a.0.end);
|
||||||
}
|
}
|
||||||
for (a, b) in self.ranges.iter().zip(self.ranges[1 ..].iter()) {
|
for (a, b) in self.ranges.iter().zip(self.ranges[1..].iter()) {
|
||||||
assert!(a.0.end <= b.0.start);
|
assert!(a.0.end <= b.0.start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,7 +122,7 @@ impl<I: Copy + PartialOrd, T: Copy + PartialEq> RangedStates<I, T> {
|
|||||||
None => {
|
None => {
|
||||||
let pos = self.ranges.len();
|
let pos = self.ranges.len();
|
||||||
self.ranges.push((index.clone(), default));
|
self.ranges.push((index.clone(), default));
|
||||||
return &mut self.ranges[pos ..];
|
return &mut self.ranges[pos..];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -137,7 +131,7 @@ impl<I: Copy + PartialOrd, T: Copy + PartialEq> RangedStates<I, T> {
|
|||||||
if range.start < index.start {
|
if range.start < index.start {
|
||||||
self.ranges[start_pos].0.start = index.start;
|
self.ranges[start_pos].0.start = index.start;
|
||||||
self.ranges
|
self.ranges
|
||||||
.insert(start_pos, (range.start .. index.start, value));
|
.insert(start_pos, (range.start..index.start, value));
|
||||||
start_pos += 1;
|
start_pos += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,19 +140,19 @@ impl<I: Copy + PartialOrd, T: Copy + PartialEq> RangedStates<I, T> {
|
|||||||
loop {
|
loop {
|
||||||
let (range, value) = self.ranges[pos].clone();
|
let (range, value) = self.ranges[pos].clone();
|
||||||
if range.start >= index.end {
|
if range.start >= index.end {
|
||||||
self.ranges.insert(pos, (range_pos .. index.end, default));
|
self.ranges.insert(pos, (range_pos..index.end, default));
|
||||||
pos += 1;
|
pos += 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if range.start > range_pos {
|
if range.start > range_pos {
|
||||||
self.ranges.insert(pos, (range_pos .. range.start, default));
|
self.ranges.insert(pos, (range_pos..range.start, default));
|
||||||
pos += 1;
|
pos += 1;
|
||||||
range_pos = range.start;
|
range_pos = range.start;
|
||||||
}
|
}
|
||||||
if range.end >= index.end {
|
if range.end >= index.end {
|
||||||
if range.end != index.end {
|
if range.end != index.end {
|
||||||
self.ranges[pos].0.start = index.end;
|
self.ranges[pos].0.start = index.end;
|
||||||
self.ranges.insert(pos, (range_pos .. index.end, value));
|
self.ranges.insert(pos, (range_pos..index.end, value));
|
||||||
}
|
}
|
||||||
pos += 1;
|
pos += 1;
|
||||||
break;
|
break;
|
||||||
@ -166,16 +160,15 @@ impl<I: Copy + PartialOrd, T: Copy + PartialEq> RangedStates<I, T> {
|
|||||||
pos += 1;
|
pos += 1;
|
||||||
range_pos = range.end;
|
range_pos = range.end;
|
||||||
if pos == self.ranges.len() {
|
if pos == self.ranges.len() {
|
||||||
self.ranges.push((range_pos .. index.end, default));
|
self.ranges.push((range_pos..index.end, default));
|
||||||
pos += 1;
|
pos += 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&mut self.ranges[start_pos .. pos]
|
&mut self.ranges[start_pos..pos]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Helper method for isolation that checks the sanity of the results.
|
/// Helper method for isolation that checks the sanity of the results.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn sanely_isolated(&self, index: Range<I>, default: T) -> Vec<(Range<I>, T)> {
|
pub fn sanely_isolated(&self, index: Range<I>, default: T) -> Vec<(Range<I>, T)> {
|
||||||
@ -198,7 +191,6 @@ impl<I: Copy + PartialOrd, T: Copy + PartialEq> RangedStates<I, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// A custom iterator that goes through two `RangedStates` and process a merge.
|
/// A custom iterator that goes through two `RangedStates` and process a merge.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Merge<'a, I, T> {
|
pub struct Merge<'a, I, T> {
|
||||||
@ -218,32 +210,32 @@ impl<'a, I: Copy + Debug + Ord, T: Copy + Debug> Iterator for Merge<'a, I, T> {
|
|||||||
if self.base == rb.start {
|
if self.base == rb.start {
|
||||||
// right stream is starting
|
// right stream is starting
|
||||||
debug_assert!(self.base < ra.end);
|
debug_assert!(self.base < ra.end);
|
||||||
(self.base .. ra.end.min(rb.end), Some(*va) .. Some(*vb))
|
(self.base..ra.end.min(rb.end), Some(*va)..Some(*vb))
|
||||||
} else {
|
} else {
|
||||||
// right hasn't started yet
|
// right hasn't started yet
|
||||||
debug_assert!(self.base < rb.start);
|
debug_assert!(self.base < rb.start);
|
||||||
(self.base .. rb.start, Some(*va) .. None)
|
(self.base..rb.start, Some(*va)..None)
|
||||||
}
|
}
|
||||||
} else if rb.start < self.base {
|
} else if rb.start < self.base {
|
||||||
// in the middle of the right stream
|
// in the middle of the right stream
|
||||||
if self.base == ra.start {
|
if self.base == ra.start {
|
||||||
// left stream is starting
|
// left stream is starting
|
||||||
debug_assert!(self.base < rb.end);
|
debug_assert!(self.base < rb.end);
|
||||||
(self.base .. ra.end.min(rb.end), Some(*va) .. Some(*vb))
|
(self.base..ra.end.min(rb.end), Some(*va)..Some(*vb))
|
||||||
} else {
|
} else {
|
||||||
// left hasn't started yet
|
// left hasn't started yet
|
||||||
debug_assert!(self.base < ra.start);
|
debug_assert!(self.base < ra.start);
|
||||||
(self.base .. ra.start, None .. Some(*vb))
|
(self.base..ra.start, None..Some(*vb))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// no active streams
|
// no active streams
|
||||||
match ra.start.cmp(&rb.start) {
|
match ra.start.cmp(&rb.start) {
|
||||||
// both are starting
|
// both are starting
|
||||||
Ordering::Equal => (ra.start .. ra.end.min(rb.end), Some(*va) .. Some(*vb)),
|
Ordering::Equal => (ra.start..ra.end.min(rb.end), Some(*va)..Some(*vb)),
|
||||||
// only left is starting
|
// only left is starting
|
||||||
Ordering::Less => (ra.start .. rb.start.min(ra.end), Some(*va) .. None),
|
Ordering::Less => (ra.start..rb.start.min(ra.end), Some(*va)..None),
|
||||||
// only right is starting
|
// only right is starting
|
||||||
Ordering::Greater => (rb.start .. ra.start.min(rb.end), None .. Some(*vb)),
|
Ordering::Greater => (rb.start..ra.start.min(rb.end), None..Some(*vb)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.base = range.end;
|
self.base = range.end;
|
||||||
@ -257,17 +249,17 @@ impl<'a, I: Copy + Debug + Ord, T: Copy + Debug> Iterator for Merge<'a, I, T> {
|
|||||||
}
|
}
|
||||||
// only right stream
|
// only right stream
|
||||||
(None, Some(&(ref rb, vb))) => {
|
(None, Some(&(ref rb, vb))) => {
|
||||||
let range = self.base.max(rb.start) .. rb.end;
|
let range = self.base.max(rb.start)..rb.end;
|
||||||
self.base = rb.end;
|
self.base = rb.end;
|
||||||
let _ = self.sb.next();
|
let _ = self.sb.next();
|
||||||
Some((range, None .. Some(*vb)))
|
Some((range, None..Some(*vb)))
|
||||||
}
|
}
|
||||||
// only left stream
|
// only left stream
|
||||||
(Some(&(ref ra, va)), None) => {
|
(Some(&(ref ra, va)), None) => {
|
||||||
let range = self.base.max(ra.start) .. ra.end;
|
let range = self.base.max(ra.start)..ra.end;
|
||||||
self.base = ra.end;
|
self.base = ra.end;
|
||||||
let _ = self.sa.next();
|
let _ = self.sa.next();
|
||||||
Some((range, Some(*va) .. None))
|
Some((range, Some(*va)..None))
|
||||||
}
|
}
|
||||||
// done
|
// done
|
||||||
(None, None) => None,
|
(None, None) => None,
|
||||||
@ -292,104 +284,83 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sane_good() {
|
fn sane_good() {
|
||||||
let rs = RangedStates::from_slice(
|
let rs = RangedStates::from_slice(&[(1..4, 9u8), (4..5, 9)]);
|
||||||
&[(1 .. 4, 9u8), (4 .. 5, 9)],
|
|
||||||
);
|
|
||||||
rs.check_sanity();
|
rs.check_sanity();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn sane_empty() {
|
fn sane_empty() {
|
||||||
let rs = RangedStates::from_slice(
|
let rs = RangedStates::from_slice(&[(1..4, 9u8), (5..5, 9)]);
|
||||||
&[(1 .. 4, 9u8), (5 .. 5, 9)],
|
|
||||||
);
|
|
||||||
rs.check_sanity();
|
rs.check_sanity();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn sane_intersect() {
|
fn sane_intersect() {
|
||||||
let rs = RangedStates::from_slice(
|
let rs = RangedStates::from_slice(&[(1..4, 9u8), (3..5, 9)]);
|
||||||
&[(1 .. 4, 9u8), (3 .. 5, 9)],
|
|
||||||
);
|
|
||||||
rs.check_sanity();
|
rs.check_sanity();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn coalesce() {
|
fn coalesce() {
|
||||||
let mut rs = RangedStates::from_slice(
|
let mut rs = RangedStates::from_slice(&[(1..4, 9u8), (4..5, 9), (5..7, 1), (8..9, 1)]);
|
||||||
&[(1 .. 4, 9u8), (4 .. 5, 9), (5 .. 7, 1), (8 .. 9, 1)],
|
|
||||||
);
|
|
||||||
rs.coalesce();
|
rs.coalesce();
|
||||||
rs.check_sanity();
|
rs.check_sanity();
|
||||||
assert_eq!(
|
assert_eq!(rs.ranges.as_slice(), &[(1..5, 9), (5..7, 1), (8..9, 1),]);
|
||||||
rs.ranges.as_slice(),
|
|
||||||
&[(1 .. 5, 9), (5 .. 7, 1), (8 .. 9, 1),]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn query() {
|
fn query() {
|
||||||
let rs = RangedStates::from_slice(
|
let rs = RangedStates::from_slice(&[(1..4, 1u8), (5..7, 2)]);
|
||||||
&[(1 .. 4, 1u8), (5 .. 7, 2)],
|
assert_eq!(rs.query(&(0..1), |v| *v), None);
|
||||||
);
|
assert_eq!(rs.query(&(1..3), |v| *v), Some(Ok(1)));
|
||||||
assert_eq!(rs.query(&(0 .. 1), |v| *v), None);
|
assert_eq!(rs.query(&(1..6), |v| *v), Some(Err(())));
|
||||||
assert_eq!(rs.query(&(1 .. 3), |v| *v), Some(Ok(1)));
|
|
||||||
assert_eq!(rs.query(&(1 .. 6), |v| *v), Some(Err(())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn isolate() {
|
fn isolate() {
|
||||||
let rs = RangedStates::from_slice(
|
let rs = RangedStates::from_slice(&[(1..4, 9u8), (4..5, 9), (5..7, 1), (8..9, 1)]);
|
||||||
&[(1 .. 4, 9u8), (4 .. 5, 9), (5 .. 7, 1), (8 .. 9, 1)],
|
assert_eq!(&rs.sanely_isolated(4..5, 0), &[(4..5, 9u8),]);
|
||||||
);
|
|
||||||
assert_eq!(&rs.sanely_isolated(4 .. 5, 0), &[(4 .. 5, 9u8),]);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&rs.sanely_isolated(0 .. 6, 0),
|
&rs.sanely_isolated(0..6, 0),
|
||||||
&[(0 .. 1, 0), (1 .. 4, 9u8), (4 .. 5, 9), (5 .. 6, 1),]
|
&[(0..1, 0), (1..4, 9u8), (4..5, 9), (5..6, 1),]
|
||||||
);
|
);
|
||||||
|
assert_eq!(&rs.sanely_isolated(8..10, 1), &[(8..9, 1), (9..10, 1),]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&rs.sanely_isolated(8 .. 10, 1),
|
&rs.sanely_isolated(6..9, 0),
|
||||||
&[(8 .. 9, 1), (9 .. 10, 1),]
|
&[(6..7, 1), (7..8, 0), (8..9, 1),]
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
&rs.sanely_isolated(6 .. 9, 0),
|
|
||||||
&[(6 .. 7, 1), (7 .. 8, 0), (8 .. 9, 1),]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn merge_same() {
|
fn merge_same() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&easy_merge(&[(1 .. 4, 0u8),], &[(1 .. 4, 2u8),],),
|
&easy_merge(&[(1..4, 0u8),], &[(1..4, 2u8),],),
|
||||||
&[(1 .. 4, Some(0) .. Some(2)),]
|
&[(1..4, Some(0)..Some(2)),]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn merge_empty() {
|
fn merge_empty() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&easy_merge(&[(1 .. 2, 0u8),], &[],),
|
&easy_merge(&[(1..2, 0u8),], &[],),
|
||||||
&[(1 .. 2, Some(0) .. None),]
|
&[(1..2, Some(0)..None),]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&easy_merge(&[], &[(3 .. 4, 1u8),],),
|
&easy_merge(&[], &[(3..4, 1u8),],),
|
||||||
&[(3 .. 4, None .. Some(1)),]
|
&[(3..4, None..Some(1)),]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn merge_separate() {
|
fn merge_separate() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&easy_merge(
|
&easy_merge(&[(1..2, 0u8), (5..6, 1u8),], &[(2..4, 2u8),],),
|
||||||
&[(1 .. 2, 0u8), (5 .. 6, 1u8),],
|
|
||||||
&[(2 .. 4, 2u8),],
|
|
||||||
),
|
|
||||||
&[
|
&[
|
||||||
(1 .. 2, Some(0) .. None),
|
(1..2, Some(0)..None),
|
||||||
(2 .. 4, None .. Some(2)),
|
(2..4, None..Some(2)),
|
||||||
(5 .. 6, Some(1) .. None),
|
(5..6, Some(1)..None),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -397,37 +368,31 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn merge_subset() {
|
fn merge_subset() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&easy_merge(
|
&easy_merge(&[(1..6, 0u8),], &[(2..4, 2u8),],),
|
||||||
&[(1 .. 6, 0u8),],
|
|
||||||
&[(2 .. 4, 2u8),],
|
|
||||||
),
|
|
||||||
&[
|
&[
|
||||||
(1 .. 2, Some(0) .. None),
|
(1..2, Some(0)..None),
|
||||||
(2 .. 4, Some(0) .. Some(2)),
|
(2..4, Some(0)..Some(2)),
|
||||||
(4 .. 6, Some(0) .. None),
|
(4..6, Some(0)..None),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&easy_merge(&[(2 .. 4, 0u8),], &[(1 .. 4, 2u8),],),
|
&easy_merge(&[(2..4, 0u8),], &[(1..4, 2u8),],),
|
||||||
&[(1 .. 2, None .. Some(2)), (2 .. 4, Some(0) .. Some(2)),]
|
&[(1..2, None..Some(2)), (2..4, Some(0)..Some(2)),]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn merge_all() {
|
fn merge_all() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&easy_merge(
|
&easy_merge(&[(1..4, 0u8), (5..8, 1u8),], &[(2..6, 2u8), (7..9, 3u8),],),
|
||||||
&[(1 .. 4, 0u8), (5 .. 8, 1u8),],
|
|
||||||
&[(2 .. 6, 2u8), (7 .. 9, 3u8),],
|
|
||||||
),
|
|
||||||
&[
|
&[
|
||||||
(1 .. 2, Some(0) .. None),
|
(1..2, Some(0)..None),
|
||||||
(2 .. 4, Some(0) .. Some(2)),
|
(2..4, Some(0)..Some(2)),
|
||||||
(4 .. 5, None .. Some(2)),
|
(4..5, None..Some(2)),
|
||||||
(5 .. 6, Some(1) .. Some(2)),
|
(5..6, Some(1)..Some(2)),
|
||||||
(6 .. 7, Some(1) .. None),
|
(6..7, Some(1)..None),
|
||||||
(7 .. 8, Some(1) .. Some(3)),
|
(7..8, Some(1)..Some(3)),
|
||||||
(8 .. 9, None .. Some(3)),
|
(8..9, None..Some(3)),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,11 @@
|
|||||||
use super::{range::RangedStates, PendingTransition, ResourceState, Unit};
|
use super::{range::RangedStates, PendingTransition, ResourceState, Unit};
|
||||||
use crate::{device::MAX_MIP_LEVELS, id::TextureId};
|
use crate::{device::MAX_MIP_LEVELS, id::TextureId};
|
||||||
|
|
||||||
use wgt::TextureUsage;
|
|
||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
|
use wgt::TextureUsage;
|
||||||
|
|
||||||
use std::{iter, ops::Range};
|
use std::{iter, ops::Range};
|
||||||
|
|
||||||
|
|
||||||
//TODO: store `hal::image::State` here to avoid extra conversions
|
//TODO: store `hal::image::State` here to avoid extra conversions
|
||||||
type PlaneStates = RangedStates<hal::image::Layer, Unit<TextureUsage>>;
|
type PlaneStates = RangedStates<hal::image::Layer, Unit<TextureUsage>>;
|
||||||
|
|
||||||
@ -40,13 +39,10 @@ impl TextureState {
|
|||||||
debug_assert_eq!(range.levels.start, 0);
|
debug_assert_eq!(range.levels.start, 0);
|
||||||
TextureState {
|
TextureState {
|
||||||
mips: iter::repeat_with(|| {
|
mips: iter::repeat_with(|| {
|
||||||
PlaneStates::from_range(
|
PlaneStates::from_range(0..range.layers.end, Unit::new(TextureUsage::UNINITIALIZED))
|
||||||
0 .. range.layers.end,
|
})
|
||||||
Unit::new(TextureUsage::UNINITIALIZED),
|
.take(range.levels.end as usize)
|
||||||
)
|
.collect(),
|
||||||
})
|
|
||||||
.take(range.levels.end as usize)
|
|
||||||
.collect(),
|
|
||||||
full: true,
|
full: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +65,7 @@ impl ResourceState for TextureState {
|
|||||||
}
|
}
|
||||||
let mip_start = num_levels.min(selector.levels.start as usize);
|
let mip_start = num_levels.min(selector.levels.start as usize);
|
||||||
let mip_end = num_levels.min(selector.levels.end as usize);
|
let mip_end = num_levels.min(selector.levels.end as usize);
|
||||||
for mip in self.mips[mip_start .. mip_end].iter() {
|
for mip in self.mips[mip_start..mip_end].iter() {
|
||||||
match mip.query(&selector.layers, |unit| unit.last) {
|
match mip.query(&selector.layers, |unit| unit.last) {
|
||||||
None => {}
|
None => {}
|
||||||
Some(Ok(usage)) if result == Some(usage) => {}
|
Some(Ok(usage)) if result == Some(usage) => {}
|
||||||
@ -96,8 +92,7 @@ impl ResourceState for TextureState {
|
|||||||
self.mips.push(PlaneStates::empty());
|
self.mips.push(PlaneStates::empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (mip_id, mip) in self.mips
|
for (mip_id, mip) in self.mips[selector.levels.start as usize..selector.levels.end as usize]
|
||||||
[selector.levels.start as usize .. selector.levels.end as usize]
|
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
@ -115,10 +110,10 @@ impl ResourceState for TextureState {
|
|||||||
id,
|
id,
|
||||||
selector: hal::image::SubresourceRange {
|
selector: hal::image::SubresourceRange {
|
||||||
aspects: hal::format::Aspects::empty(),
|
aspects: hal::format::Aspects::empty(),
|
||||||
levels: level .. level + 1,
|
levels: level..level + 1,
|
||||||
layers: range.clone(),
|
layers: range.clone(),
|
||||||
},
|
},
|
||||||
usage: unit.last .. usage,
|
usage: unit.last..usage,
|
||||||
};
|
};
|
||||||
|
|
||||||
unit.last = match output {
|
unit.last = match output {
|
||||||
@ -175,9 +170,7 @@ impl ResourceState for TextureState {
|
|||||||
end: Some(end),
|
end: Some(end),
|
||||||
} => {
|
} => {
|
||||||
let to_usage = end.port();
|
let to_usage = end.port();
|
||||||
if start.last == to_usage
|
if start.last == to_usage && TextureUsage::ORDERED.contains(to_usage) {
|
||||||
&& TextureUsage::ORDERED.contains(to_usage)
|
|
||||||
{
|
|
||||||
Unit {
|
Unit {
|
||||||
first: start.first,
|
first: start.first,
|
||||||
last: end.last,
|
last: end.last,
|
||||||
@ -191,19 +184,17 @@ impl ResourceState for TextureState {
|
|||||||
id,
|
id,
|
||||||
selector: hal::image::SubresourceRange {
|
selector: hal::image::SubresourceRange {
|
||||||
aspects: hal::format::Aspects::empty(),
|
aspects: hal::format::Aspects::empty(),
|
||||||
levels: level .. level + 1,
|
levels: level..level + 1,
|
||||||
layers: layers.clone(),
|
layers: layers.clone(),
|
||||||
},
|
},
|
||||||
usage: start.last .. to_usage,
|
usage: start.last..to_usage,
|
||||||
};
|
};
|
||||||
|
|
||||||
match output {
|
match output {
|
||||||
None => {
|
None => Unit {
|
||||||
Unit {
|
first: start.first,
|
||||||
first: start.first,
|
last: pending.collapse()?,
|
||||||
last: pending.collapse()?,
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(ref mut out) => {
|
Some(ref mut out) => {
|
||||||
out.push(pending);
|
out.push(pending);
|
||||||
Unit {
|
Unit {
|
||||||
@ -229,7 +220,6 @@ impl ResourceState for TextureState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
//TODO: change() and merge() tests
|
//TODO: change() and merge() tests
|
||||||
@ -242,16 +232,16 @@ mod test {
|
|||||||
let mut ts = TextureState::default();
|
let mut ts = TextureState::default();
|
||||||
ts.mips.push(PlaneStates::empty());
|
ts.mips.push(PlaneStates::empty());
|
||||||
ts.mips.push(PlaneStates::from_slice(&[
|
ts.mips.push(PlaneStates::from_slice(&[
|
||||||
(1 .. 3, Unit::new(TextureUsage::SAMPLED)),
|
(1..3, Unit::new(TextureUsage::SAMPLED)),
|
||||||
(3 .. 5, Unit::new(TextureUsage::SAMPLED)),
|
(3..5, Unit::new(TextureUsage::SAMPLED)),
|
||||||
(5 .. 6, Unit::new(TextureUsage::STORAGE)),
|
(5..6, Unit::new(TextureUsage::STORAGE)),
|
||||||
]));
|
]));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ts.query(SubresourceRange {
|
ts.query(SubresourceRange {
|
||||||
aspects: Aspects::COLOR,
|
aspects: Aspects::COLOR,
|
||||||
levels: 1 .. 2,
|
levels: 1..2,
|
||||||
layers: 2 .. 5,
|
layers: 2..5,
|
||||||
}),
|
}),
|
||||||
// level 1 matches
|
// level 1 matches
|
||||||
Some(TextureUsage::SAMPLED),
|
Some(TextureUsage::SAMPLED),
|
||||||
@ -259,8 +249,8 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
ts.query(SubresourceRange {
|
ts.query(SubresourceRange {
|
||||||
aspects: Aspects::COLOR,
|
aspects: Aspects::COLOR,
|
||||||
levels: 0 .. 2,
|
levels: 0..2,
|
||||||
layers: 2 .. 5,
|
layers: 2..5,
|
||||||
}),
|
}),
|
||||||
// level 0 is empty, level 1 matches
|
// level 0 is empty, level 1 matches
|
||||||
Some(TextureUsage::SAMPLED),
|
Some(TextureUsage::SAMPLED),
|
||||||
@ -268,8 +258,8 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
ts.query(SubresourceRange {
|
ts.query(SubresourceRange {
|
||||||
aspects: Aspects::COLOR,
|
aspects: Aspects::COLOR,
|
||||||
levels: 1 .. 2,
|
levels: 1..2,
|
||||||
layers: 1 .. 5,
|
layers: 1..5,
|
||||||
}),
|
}),
|
||||||
// level 1 matches with gaps
|
// level 1 matches with gaps
|
||||||
Some(TextureUsage::SAMPLED),
|
Some(TextureUsage::SAMPLED),
|
||||||
@ -277,8 +267,8 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
ts.query(SubresourceRange {
|
ts.query(SubresourceRange {
|
||||||
aspects: Aspects::COLOR,
|
aspects: Aspects::COLOR,
|
||||||
levels: 1 .. 2,
|
levels: 1..2,
|
||||||
layers: 4 .. 6,
|
layers: 4..6,
|
||||||
}),
|
}),
|
||||||
// level 1 doesn't match
|
// level 1 doesn't match
|
||||||
None,
|
None,
|
||||||
|
@ -4,14 +4,10 @@
|
|||||||
|
|
||||||
use crate::GLOBAL;
|
use crate::GLOBAL;
|
||||||
|
|
||||||
pub use core::command::{
|
pub use core::command::{compute_ffi::*, render_ffi::*};
|
||||||
compute_ffi::*,
|
|
||||||
render_ffi::*,
|
|
||||||
};
|
|
||||||
|
|
||||||
use core::{gfx_select, id};
|
use core::{gfx_select, id};
|
||||||
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_command_encoder_finish(
|
pub extern "C" fn wgpu_command_encoder_finish(
|
||||||
encoder_id: id::CommandEncoderId,
|
encoder_id: id::CommandEncoderId,
|
||||||
@ -80,7 +76,6 @@ pub extern "C" fn wgpu_command_encoder_copy_texture_to_texture(
|
|||||||
copy_size))
|
copy_size))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// This function is unsafe because improper use may lead to memory
|
/// This function is unsafe because improper use may lead to memory
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
use crate::GLOBAL;
|
use crate::GLOBAL;
|
||||||
|
|
||||||
use wgt::{BackendBit, DeviceDescriptor, Limits};
|
|
||||||
use core::{gfx_select, hub::Token, id};
|
use core::{gfx_select, hub::Token, id};
|
||||||
|
use wgt::{BackendBit, DeviceDescriptor, Limits};
|
||||||
|
|
||||||
use std::{marker::PhantomData, slice};
|
use std::{marker::PhantomData, slice};
|
||||||
|
|
||||||
@ -30,13 +30,12 @@ pub fn wgpu_create_surface(raw_handle: raw_window_handle::RawWindowHandle) -> id
|
|||||||
},
|
},
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
Rwh::MacOS(h) => {
|
Rwh::MacOS(h) => {
|
||||||
let ns_view =
|
let ns_view = if h.ns_view.is_null() {
|
||||||
if h.ns_view.is_null() {
|
let ns_window = h.ns_window as *mut Object;
|
||||||
let ns_window = h.ns_window as *mut Object;
|
unsafe { msg_send![ns_window, contentView] }
|
||||||
unsafe { msg_send![ns_window, contentView] }
|
} else {
|
||||||
} else {
|
h.ns_view
|
||||||
h.ns_view
|
};
|
||||||
};
|
|
||||||
core::instance::Surface {
|
core::instance::Surface {
|
||||||
#[cfg(feature = "vulkan-portability")]
|
#[cfg(feature = "vulkan-portability")]
|
||||||
vulkan: instance
|
vulkan: instance
|
||||||
@ -47,7 +46,7 @@ pub fn wgpu_create_surface(raw_handle: raw_window_handle::RawWindowHandle) -> id
|
|||||||
.metal
|
.metal
|
||||||
.create_surface_from_nsview(ns_view, cfg!(debug_assertions)),
|
.create_surface_from_nsview(ns_view, cfg!(debug_assertions)),
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
#[cfg(all(unix, not(target_os = "ios"), not(target_os = "macos")))]
|
#[cfg(all(unix, not(target_os = "ios"), not(target_os = "macos")))]
|
||||||
Rwh::Xlib(h) => core::instance::Surface {
|
Rwh::Xlib(h) => core::instance::Surface {
|
||||||
vulkan: instance
|
vulkan: instance
|
||||||
@ -105,7 +104,8 @@ pub extern "C" fn wgpu_create_surface_from_wayland(
|
|||||||
) -> id::SurfaceId {
|
) -> id::SurfaceId {
|
||||||
use raw_window_handle::unix::WaylandHandle;
|
use raw_window_handle::unix::WaylandHandle;
|
||||||
wgpu_create_surface(raw_window_handle::RawWindowHandle::Wayland(WaylandHandle {
|
wgpu_create_surface(raw_window_handle::RawWindowHandle::Wayland(WaylandHandle {
|
||||||
surface, display,
|
surface,
|
||||||
|
display,
|
||||||
..WaylandHandle::empty()
|
..WaylandHandle::empty()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -184,10 +184,7 @@ pub extern "C" fn wgpu_adapter_destroy(adapter_id: id::AdapterId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_device_get_limits(
|
pub extern "C" fn wgpu_device_get_limits(_device_id: id::DeviceId, limits: &mut Limits) {
|
||||||
_device_id: id::DeviceId,
|
|
||||||
limits: &mut Limits,
|
|
||||||
) {
|
|
||||||
*limits = Limits::default(); // TODO
|
*limits = Limits::default(); // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,7 +206,8 @@ pub unsafe extern "C" fn wgpu_device_create_buffer_mapped(
|
|||||||
desc: &wgt::BufferDescriptor,
|
desc: &wgt::BufferDescriptor,
|
||||||
mapped_ptr_out: *mut *mut u8,
|
mapped_ptr_out: *mut *mut u8,
|
||||||
) -> id::BufferId {
|
) -> id::BufferId {
|
||||||
let (id, ptr) = gfx_select!(device_id => GLOBAL.device_create_buffer_mapped(device_id, desc, PhantomData));
|
let (id, ptr) =
|
||||||
|
gfx_select!(device_id => GLOBAL.device_create_buffer_mapped(device_id, desc, PhantomData));
|
||||||
*mapped_ptr_out = ptr;
|
*mapped_ptr_out = ptr;
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
@ -329,8 +327,7 @@ pub unsafe extern "C" fn wgpu_queue_submit(
|
|||||||
command_buffers: *const id::CommandBufferId,
|
command_buffers: *const id::CommandBufferId,
|
||||||
command_buffers_length: usize,
|
command_buffers_length: usize,
|
||||||
) {
|
) {
|
||||||
let command_buffer_ids =
|
let command_buffer_ids = slice::from_raw_parts(command_buffers, command_buffers_length);
|
||||||
slice::from_raw_parts(command_buffers, command_buffers_length);
|
|
||||||
gfx_select!(queue_id => GLOBAL.queue_submit(queue_id, command_buffer_ids))
|
gfx_select!(queue_id => GLOBAL.queue_submit(queue_id, command_buffer_ids))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,10 +374,7 @@ pub extern "C" fn wgpu_buffer_map_read_async(
|
|||||||
callback: core::device::BufferMapReadCallback,
|
callback: core::device::BufferMapReadCallback,
|
||||||
userdata: *mut u8,
|
userdata: *mut u8,
|
||||||
) {
|
) {
|
||||||
let operation = core::resource::BufferMapOperation::Read {
|
let operation = core::resource::BufferMapOperation::Read { callback, userdata };
|
||||||
callback,
|
|
||||||
userdata,
|
|
||||||
};
|
|
||||||
|
|
||||||
gfx_select!(buffer_id => GLOBAL.buffer_map_async(buffer_id, wgt::BufferUsage::MAP_READ, start .. start + size, operation))
|
gfx_select!(buffer_id => GLOBAL.buffer_map_async(buffer_id, wgt::BufferUsage::MAP_READ, start .. start + size, operation))
|
||||||
}
|
}
|
||||||
@ -393,10 +387,7 @@ pub extern "C" fn wgpu_buffer_map_write_async(
|
|||||||
callback: core::device::BufferMapWriteCallback,
|
callback: core::device::BufferMapWriteCallback,
|
||||||
userdata: *mut u8,
|
userdata: *mut u8,
|
||||||
) {
|
) {
|
||||||
let operation = core::resource::BufferMapOperation::Write {
|
let operation = core::resource::BufferMapOperation::Write { callback, userdata };
|
||||||
callback,
|
|
||||||
userdata,
|
|
||||||
};
|
|
||||||
|
|
||||||
gfx_select!(buffer_id => GLOBAL.buffer_map_async(buffer_id, wgt::BufferUsage::MAP_WRITE, start .. start + size, operation))
|
gfx_select!(buffer_id => GLOBAL.buffer_map_async(buffer_id, wgt::BufferUsage::MAP_WRITE, start .. start + size, operation))
|
||||||
}
|
}
|
||||||
@ -411,9 +402,7 @@ pub extern "C" fn wgpu_swap_chain_get_next_texture(
|
|||||||
swap_chain_id: id::SwapChainId,
|
swap_chain_id: id::SwapChainId,
|
||||||
) -> core::swap_chain::SwapChainOutput {
|
) -> core::swap_chain::SwapChainOutput {
|
||||||
gfx_select!(swap_chain_id => GLOBAL.swap_chain_get_next_texture(swap_chain_id, PhantomData))
|
gfx_select!(swap_chain_id => GLOBAL.swap_chain_get_next_texture(swap_chain_id, PhantomData))
|
||||||
.unwrap_or(core::swap_chain::SwapChainOutput {
|
.unwrap_or(core::swap_chain::SwapChainOutput { view_id: None })
|
||||||
view_id: None,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
use core::id;
|
use core::id;
|
||||||
|
|
||||||
|
|
||||||
pub type FactoryParam = *mut std::ffi::c_void;
|
pub type FactoryParam = *mut std::ffi::c_void;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -14,7 +13,9 @@ pub struct IdentityRecycler<I> {
|
|||||||
kind: &'static str,
|
kind: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: id::TypedId + Clone + std::fmt::Debug> core::hub::IdentityHandler<I> for IdentityRecycler<I> {
|
impl<I: id::TypedId + Clone + std::fmt::Debug> core::hub::IdentityHandler<I>
|
||||||
|
for IdentityRecycler<I>
|
||||||
|
{
|
||||||
type Input = I;
|
type Input = I;
|
||||||
fn process(&self, id: I, _backend: wgt::Backend) -> I {
|
fn process(&self, id: I, _backend: wgt::Backend) -> I {
|
||||||
log::debug!("process {} {:?}", self.kind, id);
|
log::debug!("process {} {:?}", self.kind, id);
|
||||||
|
@ -2,17 +2,11 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use core::{
|
use core::{hub::IdentityManager, id};
|
||||||
hub::IdentityManager,
|
|
||||||
id,
|
|
||||||
};
|
|
||||||
|
|
||||||
use wgt::Backend;
|
use wgt::Backend;
|
||||||
|
|
||||||
pub use core::command::{
|
pub use core::command::{compute_ffi::*, render_ffi::*};
|
||||||
compute_ffi::*,
|
|
||||||
render_ffi::*,
|
|
||||||
};
|
|
||||||
|
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
@ -21,7 +15,6 @@ use std::{ptr, slice};
|
|||||||
pub mod identity;
|
pub mod identity;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
struct IdentityHub {
|
struct IdentityHub {
|
||||||
adapters: IdentityManager,
|
adapters: IdentityManager,
|
||||||
@ -136,7 +129,10 @@ pub extern "C" fn wgpu_client_kill_adapter_id(client: &Client, id: id::AdapterId
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_client_make_device_id(client: &Client, adapter_id: id::AdapterId) -> id::DeviceId {
|
pub extern "C" fn wgpu_client_make_device_id(
|
||||||
|
client: &Client,
|
||||||
|
adapter_id: id::AdapterId,
|
||||||
|
) -> id::DeviceId {
|
||||||
let backend = adapter_id.backend();
|
let backend = adapter_id.backend();
|
||||||
client
|
client
|
||||||
.identities
|
.identities
|
||||||
@ -157,7 +153,10 @@ pub extern "C" fn wgpu_client_kill_device_id(client: &Client, id: id::DeviceId)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_client_make_buffer_id(client: &Client, device_id: id::DeviceId) -> id::BufferId {
|
pub extern "C" fn wgpu_client_make_buffer_id(
|
||||||
|
client: &Client,
|
||||||
|
device_id: id::DeviceId,
|
||||||
|
) -> id::BufferId {
|
||||||
let backend = device_id.backend();
|
let backend = device_id.backend();
|
||||||
client
|
client
|
||||||
.identities
|
.identities
|
||||||
@ -178,7 +177,10 @@ pub extern "C" fn wgpu_client_kill_buffer_id(client: &Client, id: id::BufferId)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_client_make_texture_id(client: &Client, device_id: id::DeviceId) -> id::TextureId {
|
pub extern "C" fn wgpu_client_make_texture_id(
|
||||||
|
client: &Client,
|
||||||
|
device_id: id::DeviceId,
|
||||||
|
) -> id::TextureId {
|
||||||
let backend = device_id.backend();
|
let backend = device_id.backend();
|
||||||
client
|
client
|
||||||
.identities
|
.identities
|
||||||
@ -189,10 +191,7 @@ pub extern "C" fn wgpu_client_make_texture_id(client: &Client, device_id: id::De
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_client_kill_texture_id(
|
pub extern "C" fn wgpu_client_kill_texture_id(client: &Client, id: id::TextureId) {
|
||||||
client: &Client,
|
|
||||||
id: id::TextureId,
|
|
||||||
) {
|
|
||||||
client
|
client
|
||||||
.identities
|
.identities
|
||||||
.lock()
|
.lock()
|
||||||
@ -201,9 +200,11 @@ pub extern "C" fn wgpu_client_kill_texture_id(
|
|||||||
.free(id)
|
.free(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_client_make_texture_view_id(client: &Client, device_id: id::DeviceId) -> id::TextureViewId {
|
pub extern "C" fn wgpu_client_make_texture_view_id(
|
||||||
|
client: &Client,
|
||||||
|
device_id: id::DeviceId,
|
||||||
|
) -> id::TextureViewId {
|
||||||
let backend = device_id.backend();
|
let backend = device_id.backend();
|
||||||
client
|
client
|
||||||
.identities
|
.identities
|
||||||
@ -214,10 +215,7 @@ pub extern "C" fn wgpu_client_make_texture_view_id(client: &Client, device_id: i
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_client_kill_texture_view_id(
|
pub extern "C" fn wgpu_client_kill_texture_view_id(client: &Client, id: id::TextureViewId) {
|
||||||
client: &Client,
|
|
||||||
id: id::TextureViewId,
|
|
||||||
) {
|
|
||||||
client
|
client
|
||||||
.identities
|
.identities
|
||||||
.lock()
|
.lock()
|
||||||
@ -227,7 +225,10 @@ pub extern "C" fn wgpu_client_kill_texture_view_id(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_client_make_sampler_id(client: &Client, device_id: id::DeviceId) -> id::SamplerId {
|
pub extern "C" fn wgpu_client_make_sampler_id(
|
||||||
|
client: &Client,
|
||||||
|
device_id: id::DeviceId,
|
||||||
|
) -> id::SamplerId {
|
||||||
let backend = device_id.backend();
|
let backend = device_id.backend();
|
||||||
client
|
client
|
||||||
.identities
|
.identities
|
||||||
@ -238,10 +239,7 @@ pub extern "C" fn wgpu_client_make_sampler_id(client: &Client, device_id: id::De
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_client_kill_sampler_id(
|
pub extern "C" fn wgpu_client_kill_sampler_id(client: &Client, id: id::SamplerId) {
|
||||||
client: &Client,
|
|
||||||
id: id::SamplerId,
|
|
||||||
) {
|
|
||||||
client
|
client
|
||||||
.identities
|
.identities
|
||||||
.lock()
|
.lock()
|
||||||
@ -265,10 +263,7 @@ pub extern "C" fn wgpu_client_make_encoder_id(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_client_kill_encoder_id(
|
pub extern "C" fn wgpu_client_kill_encoder_id(client: &Client, id: id::CommandEncoderId) {
|
||||||
client: &Client,
|
|
||||||
id: id::CommandEncoderId,
|
|
||||||
) {
|
|
||||||
client
|
client
|
||||||
.identities
|
.identities
|
||||||
.lock()
|
.lock()
|
||||||
@ -345,10 +340,7 @@ pub extern "C" fn wgpu_client_make_pipeline_layout_id(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_client_kill_pipeline_layout_id(
|
pub extern "C" fn wgpu_client_kill_pipeline_layout_id(client: &Client, id: id::PipelineLayoutId) {
|
||||||
client: &Client,
|
|
||||||
id: id::PipelineLayoutId,
|
|
||||||
) {
|
|
||||||
client
|
client
|
||||||
.identities
|
.identities
|
||||||
.lock()
|
.lock()
|
||||||
@ -372,10 +364,7 @@ pub extern "C" fn wgpu_client_make_bind_group_id(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_client_kill_bind_group_id(
|
pub extern "C" fn wgpu_client_kill_bind_group_id(client: &Client, id: id::BindGroupId) {
|
||||||
client: &Client,
|
|
||||||
id: id::BindGroupId,
|
|
||||||
) {
|
|
||||||
client
|
client
|
||||||
.identities
|
.identities
|
||||||
.lock()
|
.lock()
|
||||||
@ -399,10 +388,7 @@ pub extern "C" fn wgpu_client_make_shader_module_id(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_client_kill_shader_module_id(
|
pub extern "C" fn wgpu_client_kill_shader_module_id(client: &Client, id: id::ShaderModuleId) {
|
||||||
client: &Client,
|
|
||||||
id: id::ShaderModuleId,
|
|
||||||
) {
|
|
||||||
client
|
client
|
||||||
.identities
|
.identities
|
||||||
.lock()
|
.lock()
|
||||||
@ -426,10 +412,7 @@ pub extern "C" fn wgpu_client_make_compute_pipeline_id(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_client_kill_compute_pipeline_id(
|
pub extern "C" fn wgpu_client_kill_compute_pipeline_id(client: &Client, id: id::ComputePipelineId) {
|
||||||
client: &Client,
|
|
||||||
id: id::ComputePipelineId,
|
|
||||||
) {
|
|
||||||
client
|
client
|
||||||
.identities
|
.identities
|
||||||
.lock()
|
.lock()
|
||||||
@ -453,10 +436,7 @@ pub extern "C" fn wgpu_client_make_render_pipeline_id(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_client_kill_render_pipeline_id(
|
pub extern "C" fn wgpu_client_kill_render_pipeline_id(client: &Client, id: id::RenderPipelineId) {
|
||||||
client: &Client,
|
|
||||||
id: id::RenderPipelineId,
|
|
||||||
) {
|
|
||||||
client
|
client
|
||||||
.identities
|
.identities
|
||||||
.lock()
|
.lock()
|
||||||
|
@ -8,7 +8,6 @@ use core::{gfx_select, id};
|
|||||||
|
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
|
|
||||||
pub type Global = core::hub::Global<IdentityRecyclerFactory>;
|
pub type Global = core::hub::Global<IdentityRecyclerFactory>;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -71,10 +70,7 @@ pub extern "C" fn wgpu_server_adapter_request_device(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_server_adapter_destroy(
|
pub extern "C" fn wgpu_server_adapter_destroy(global: &Global, adapter_id: id::AdapterId) {
|
||||||
global: &Global,
|
|
||||||
adapter_id: id::AdapterId,
|
|
||||||
) {
|
|
||||||
gfx_select!(adapter_id => global.adapter_destroy(adapter_id))
|
gfx_select!(adapter_id => global.adapter_destroy(adapter_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,11 +119,8 @@ pub extern "C" fn wgpu_server_buffer_map_read(
|
|||||||
callback: core::device::BufferMapReadCallback,
|
callback: core::device::BufferMapReadCallback,
|
||||||
userdata: *mut u8,
|
userdata: *mut u8,
|
||||||
) {
|
) {
|
||||||
let operation = core::resource::BufferMapOperation::Read {
|
let operation = core::resource::BufferMapOperation::Read { callback, userdata };
|
||||||
callback,
|
|
||||||
userdata,
|
|
||||||
};
|
|
||||||
|
|
||||||
gfx_select!(buffer_id => global.buffer_map_async(
|
gfx_select!(buffer_id => global.buffer_map_async(
|
||||||
buffer_id,
|
buffer_id,
|
||||||
wgt::BufferUsage::MAP_READ,
|
wgt::BufferUsage::MAP_READ,
|
||||||
@ -161,10 +154,7 @@ pub extern "C" fn wgpu_server_encoder_finish(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_server_encoder_destroy(
|
pub extern "C" fn wgpu_server_encoder_destroy(global: &Global, self_id: id::CommandEncoderId) {
|
||||||
global: &Global,
|
|
||||||
self_id: id::CommandEncoderId,
|
|
||||||
) {
|
|
||||||
gfx_select!(self_id => global.command_encoder_destroy(self_id));
|
gfx_select!(self_id => global.command_encoder_destroy(self_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,10 +310,7 @@ pub extern "C" fn wgpu_server_device_create_bind_group(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_server_bind_group_destroy(
|
pub extern "C" fn wgpu_server_bind_group_destroy(global: &Global, self_id: id::BindGroupId) {
|
||||||
global: &Global,
|
|
||||||
self_id: id::BindGroupId,
|
|
||||||
) {
|
|
||||||
gfx_select!(self_id => global.bind_group_destroy(self_id));
|
gfx_select!(self_id => global.bind_group_destroy(self_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,10 +325,7 @@ pub extern "C" fn wgpu_server_device_create_shader_module(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_server_shader_module_destroy(
|
pub extern "C" fn wgpu_server_shader_module_destroy(global: &Global, self_id: id::ShaderModuleId) {
|
||||||
global: &Global,
|
|
||||||
self_id: id::ShaderModuleId,
|
|
||||||
) {
|
|
||||||
gfx_select!(self_id => global.shader_module_destroy(self_id));
|
gfx_select!(self_id => global.shader_module_destroy(self_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,18 +386,12 @@ pub extern "C" fn wgpu_server_texture_create_view(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_server_texture_destroy(
|
pub extern "C" fn wgpu_server_texture_destroy(global: &Global, self_id: id::TextureId) {
|
||||||
global: &Global,
|
|
||||||
self_id: id::TextureId,
|
|
||||||
) {
|
|
||||||
gfx_select!(self_id => global.texture_destroy(self_id));
|
gfx_select!(self_id => global.texture_destroy(self_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_server_texture_view_destroy(
|
pub extern "C" fn wgpu_server_texture_view_destroy(global: &Global, self_id: id::TextureViewId) {
|
||||||
global: &Global,
|
|
||||||
self_id: id::TextureViewId,
|
|
||||||
) {
|
|
||||||
gfx_select!(self_id => global.texture_view_destroy(self_id));
|
gfx_select!(self_id => global.texture_view_destroy(self_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,9 +406,6 @@ pub extern "C" fn wgpu_server_device_create_sampler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_server_sampler_destroy(
|
pub extern "C" fn wgpu_server_sampler_destroy(global: &Global, self_id: id::SamplerId) {
|
||||||
global: &Global,
|
|
||||||
self_id: id::SamplerId,
|
|
||||||
) {
|
|
||||||
gfx_select!(self_id => global.sampler_destroy(self_id));
|
gfx_select!(self_id => global.sampler_destroy(self_id));
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use std::{io, slice, ptr};
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
#[cfg(feature = "peek-poke")]
|
#[cfg(feature = "peek-poke")]
|
||||||
use peek_poke::{PeekPoke};
|
use peek_poke::PeekPoke;
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::{io, ptr, slice};
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
@ -557,9 +557,7 @@ pub struct CommandEncoderDescriptor {
|
|||||||
|
|
||||||
impl Default for CommandEncoderDescriptor {
|
impl Default for CommandEncoderDescriptor {
|
||||||
fn default() -> CommandEncoderDescriptor {
|
fn default() -> CommandEncoderDescriptor {
|
||||||
CommandEncoderDescriptor {
|
CommandEncoderDescriptor { label: ptr::null() }
|
||||||
label: ptr::null(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -731,11 +729,7 @@ pub struct Origin3d {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Origin3d {
|
impl Origin3d {
|
||||||
pub const ZERO: Self = Origin3d {
|
pub const ZERO: Self = Origin3d { x: 0, y: 0, z: 0 };
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
z: 0,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Origin3d {
|
impl Default for Origin3d {
|
||||||
|
Loading…
Reference in New Issue
Block a user