mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 14:55:05 +00:00
Formatting pass
This commit is contained in:
parent
26e5b4258d
commit
b414b9f373
@ -1,9 +1,5 @@
|
||||
use super::CommandBuffer;
|
||||
use crate::{
|
||||
hub::GfxBackend,
|
||||
track::TrackerSet,
|
||||
DeviceId, LifeGuard, Stored, SubmissionIndex,
|
||||
};
|
||||
use crate::{hub::GfxBackend, track::TrackerSet, DeviceId, LifeGuard, Stored, SubmissionIndex};
|
||||
|
||||
use hal::{command::RawCommandBuffer, pool::RawCommandPool, Device};
|
||||
use log::trace;
|
||||
|
@ -1,6 +1,11 @@
|
||||
use crate::{
|
||||
hub::GfxBackend,
|
||||
BindGroup, BindGroupId, BindGroupLayoutId, BufferAddress, PipelineLayoutId, Stored,
|
||||
BindGroup,
|
||||
BindGroupId,
|
||||
BindGroupLayoutId,
|
||||
BufferAddress,
|
||||
PipelineLayoutId,
|
||||
Stored,
|
||||
};
|
||||
|
||||
use log::trace;
|
||||
@ -188,7 +193,7 @@ impl Binder {
|
||||
},
|
||||
self.entries[index + 1 ..]
|
||||
.iter()
|
||||
.flat_map(|entry| entry.dynamic_offsets.as_slice())
|
||||
.flat_map(|entry| entry.dynamic_offsets.as_slice()),
|
||||
)
|
||||
})
|
||||
} else {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
gfx_select,
|
||||
command::bind::{Binder, LayoutChange},
|
||||
device::all_buffer_stages,
|
||||
gfx_select,
|
||||
hub::{GfxBackend, Token},
|
||||
track::{Stitch, TrackerSet},
|
||||
BindGroupId,
|
||||
@ -12,9 +12,9 @@ use crate::{
|
||||
CommandBufferId,
|
||||
ComputePassId,
|
||||
ComputePipelineId,
|
||||
BIND_BUFFER_ALIGNMENT,
|
||||
RawString,
|
||||
Stored,
|
||||
BIND_BUFFER_ALIGNMENT,
|
||||
};
|
||||
|
||||
use hal::{self, command::RawCommandBuffer};
|
||||
@ -104,7 +104,11 @@ pub fn compute_pass_set_bind_group<B: GfxBackend>(
|
||||
let (buffer_guard, mut token) = hub.buffers.read(&mut token);
|
||||
let (texture_guard, _) = hub.textures.read(&mut token);
|
||||
|
||||
trace!("Encoding barriers on binding of {:?} in pass {:?}", bind_group_id, pass_id);
|
||||
trace!(
|
||||
"Encoding barriers on binding of {:?} in pass {:?}",
|
||||
bind_group_id,
|
||||
pass_id
|
||||
);
|
||||
CommandBuffer::insert_barriers(
|
||||
&mut pass.raw,
|
||||
&mut pass.trackers,
|
||||
@ -114,9 +118,9 @@ pub fn compute_pass_set_bind_group<B: GfxBackend>(
|
||||
&*texture_guard,
|
||||
);
|
||||
|
||||
if let Some((pipeline_layout_id, follow_up_sets, follow_up_offsets)) =
|
||||
pass.binder
|
||||
.provide_entry(index as usize, bind_group_id, bind_group, offsets)
|
||||
if let Some((pipeline_layout_id, follow_up_sets, follow_up_offsets)) = pass
|
||||
.binder
|
||||
.provide_entry(index as usize, bind_group_id, bind_group, offsets)
|
||||
{
|
||||
let bind_groups = iter::once(bind_group.raw.raw())
|
||||
.chain(follow_up_sets.map(|bg_id| bind_group_guard[bg_id].raw.raw()));
|
||||
@ -170,9 +174,7 @@ pub extern "C" fn wgpu_compute_pass_insert_debug_marker(
|
||||
|
||||
// Compute-specific routines
|
||||
|
||||
pub fn compute_pass_dispatch<B: GfxBackend>(
|
||||
pass_id: ComputePassId, x: u32, y: u32, z: u32
|
||||
) {
|
||||
pub fn compute_pass_dispatch<B: GfxBackend>(pass_id: ComputePassId, x: u32, y: u32, z: u32) {
|
||||
let hub = B::hub();
|
||||
let mut token = Token::root();
|
||||
let (mut pass_guard, _) = hub.compute_passes.write(&mut token);
|
||||
@ -197,10 +199,12 @@ pub fn compute_pass_dispatch_indirect<B: GfxBackend>(
|
||||
let (mut pass_guard, _) = hub.compute_passes.write(&mut token);
|
||||
let pass = &mut pass_guard[pass_id];
|
||||
|
||||
let (src_buffer, src_pending) = pass
|
||||
.trackers
|
||||
.buffers
|
||||
.use_replace(&*buffer_guard, indirect_buffer_id, (), BufferUsage::INDIRECT);
|
||||
let (src_buffer, src_pending) = pass.trackers.buffers.use_replace(
|
||||
&*buffer_guard,
|
||||
indirect_buffer_id,
|
||||
(),
|
||||
BufferUsage::INDIRECT,
|
||||
);
|
||||
|
||||
let barriers = src_pending.map(|pending| hal::memory::Barrier::Buffer {
|
||||
states: pending.to_states(),
|
||||
|
@ -10,7 +10,6 @@ pub use self::render::*;
|
||||
pub use self::transfer::*;
|
||||
|
||||
use crate::{
|
||||
gfx_select,
|
||||
conv,
|
||||
device::{
|
||||
all_buffer_stages,
|
||||
@ -19,6 +18,7 @@ use crate::{
|
||||
RenderPassContext,
|
||||
RenderPassKey,
|
||||
},
|
||||
gfx_select,
|
||||
hub::{GfxBackend, Storage, Token},
|
||||
id::{Input, Output},
|
||||
resource::TexturePlacement,
|
||||
@ -41,23 +41,12 @@ use crate::{
|
||||
};
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use hal::{
|
||||
adapter::PhysicalDevice,
|
||||
command::RawCommandBuffer,
|
||||
Device as _
|
||||
};
|
||||
use hal::{adapter::PhysicalDevice, command::RawCommandBuffer, Device as _};
|
||||
use log::trace;
|
||||
|
||||
use std::{
|
||||
collections::hash_map::Entry,
|
||||
iter,
|
||||
mem,
|
||||
slice,
|
||||
ptr,
|
||||
thread::ThreadId,
|
||||
};
|
||||
#[cfg(not(feature = "remote"))]
|
||||
use std::marker::PhantomData;
|
||||
use std::{collections::hash_map::Entry, iter, mem, ptr, slice, thread::ThreadId};
|
||||
|
||||
|
||||
pub struct RenderBundle<B: hal::Backend> {
|
||||
@ -138,18 +127,18 @@ impl<B: GfxBackend> CommandBuffer<B> {
|
||||
debug_assert_eq!(B::VARIANT, base.backend());
|
||||
debug_assert_eq!(B::VARIANT, head.backend());
|
||||
|
||||
let buffer_barriers =
|
||||
base.buffers
|
||||
.merge_replace(&head.buffers, stitch)
|
||||
.map(|pending| {
|
||||
trace!("\tbuffer -> {:?}", pending);
|
||||
hal::memory::Barrier::Buffer {
|
||||
states: pending.to_states(),
|
||||
target: &buffer_guard[pending.id].raw,
|
||||
range: None .. None,
|
||||
families: None,
|
||||
}
|
||||
});
|
||||
let buffer_barriers = base
|
||||
.buffers
|
||||
.merge_replace(&head.buffers, stitch)
|
||||
.map(|pending| {
|
||||
trace!("\tbuffer -> {:?}", pending);
|
||||
hal::memory::Barrier::Buffer {
|
||||
states: pending.to_states(),
|
||||
target: &buffer_guard[pending.id].raw,
|
||||
range: None .. None,
|
||||
families: None,
|
||||
}
|
||||
});
|
||||
let texture_barriers = base
|
||||
.textures
|
||||
.merge_replace(&head.textures, stitch)
|
||||
@ -225,7 +214,10 @@ pub fn command_encoder_begin_render_pass<B: GfxBackend>(
|
||||
let cmb = &mut cmb_guard[encoder_id];
|
||||
let device = &device_guard[cmb.device_id.value];
|
||||
|
||||
let limits = adapter_guard[device.adapter_id].raw.physical_device.limits();
|
||||
let limits = adapter_guard[device.adapter_id]
|
||||
.raw
|
||||
.physical_device
|
||||
.limits();
|
||||
let samples_count_limit = limits.framebuffer_color_sample_counts;
|
||||
|
||||
let mut current_comb = device.com_allocator.extend(cmb);
|
||||
@ -248,24 +240,40 @@ pub fn command_encoder_begin_render_pass<B: GfxBackend>(
|
||||
unsafe { slice::from_raw_parts(desc.color_attachments, desc.color_attachments_length) };
|
||||
let depth_stencil_attachment = unsafe { desc.depth_stencil_attachment.as_ref() };
|
||||
|
||||
let sample_count = color_attachments.get(0).map(|at| view_guard[at.attachment].samples).unwrap_or(1);
|
||||
assert!(sample_count & samples_count_limit != 0, "Attachment sample_count must be supported by physical device limits");
|
||||
let sample_count = color_attachments
|
||||
.get(0)
|
||||
.map(|at| view_guard[at.attachment].samples)
|
||||
.unwrap_or(1);
|
||||
assert!(
|
||||
sample_count & samples_count_limit != 0,
|
||||
"Attachment sample_count must be supported by physical device limits"
|
||||
);
|
||||
for at in color_attachments.iter() {
|
||||
let sample_count_check = view_guard[at.attachment].samples;
|
||||
assert_eq!(sample_count_check, sample_count, "All attachments must have the same sample_count");
|
||||
assert_eq!(
|
||||
sample_count_check, sample_count,
|
||||
"All attachments must have the same sample_count"
|
||||
);
|
||||
|
||||
if let Some(resolve) = unsafe { at.resolve_target.as_ref() } {
|
||||
assert_eq!(view_guard[*resolve].samples, 1, "All target_resolves must have a sample_count of 1");
|
||||
assert_eq!(
|
||||
view_guard[*resolve].samples, 1,
|
||||
"All target_resolves must have a sample_count of 1"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
trace!("Encoding render pass begin in command buffer {:?}", encoder_id);
|
||||
trace!(
|
||||
"Encoding render pass begin in command buffer {:?}",
|
||||
encoder_id
|
||||
);
|
||||
let rp_key = {
|
||||
let trackers = &mut cmb.trackers;
|
||||
let swap_chain_links = &mut cmb.swap_chain_links;
|
||||
|
||||
let depth_stencil = depth_stencil_attachment.map(|at| {
|
||||
let view = trackers.views
|
||||
let view = trackers
|
||||
.views
|
||||
.use_extend(&*view_guard, at.attachment, (), ())
|
||||
.unwrap();
|
||||
if let Some(ex) = extent {
|
||||
@ -273,15 +281,16 @@ pub fn command_encoder_begin_render_pass<B: GfxBackend>(
|
||||
} else {
|
||||
extent = Some(view.extent);
|
||||
}
|
||||
let old_layout = match trackers.textures.query(
|
||||
view.texture_id.value,
|
||||
view.range.clone(),
|
||||
) {
|
||||
let old_layout = match trackers
|
||||
.textures
|
||||
.query(view.texture_id.value, view.range.clone())
|
||||
{
|
||||
Some(usage) => {
|
||||
conv::map_texture_state(
|
||||
usage,
|
||||
hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL,
|
||||
).1
|
||||
)
|
||||
.1
|
||||
}
|
||||
None => {
|
||||
// Required sub-resources have inconsistent states, we need to
|
||||
@ -317,7 +326,8 @@ pub fn command_encoder_begin_render_pass<B: GfxBackend>(
|
||||
let mut resolves = ArrayVec::new();
|
||||
|
||||
for at in color_attachments {
|
||||
let view = trackers.views
|
||||
let view = trackers
|
||||
.views
|
||||
.use_extend(&*view_guard, at.attachment, (), ())
|
||||
.unwrap();
|
||||
if let Some(ex) = extent {
|
||||
@ -338,13 +348,11 @@ pub fn command_encoder_begin_render_pass<B: GfxBackend>(
|
||||
swap_chain_links.push(link);
|
||||
}
|
||||
|
||||
let old_layout = match trackers.textures.query(
|
||||
view.texture_id.value,
|
||||
view.range.clone(),
|
||||
) {
|
||||
Some(usage) => {
|
||||
conv::map_texture_state(usage, hal::format::Aspects::COLOR).1
|
||||
}
|
||||
let old_layout = match trackers
|
||||
.textures
|
||||
.query(view.texture_id.value, view.range.clone())
|
||||
{
|
||||
Some(usage) => conv::map_texture_state(usage, hal::format::Aspects::COLOR).1,
|
||||
None => {
|
||||
// Required sub-resources have inconsistent states, we need to
|
||||
// issue individual barriers instead of relying on the render pass.
|
||||
@ -376,7 +384,8 @@ pub fn command_encoder_begin_render_pass<B: GfxBackend>(
|
||||
});
|
||||
|
||||
if let Some(resolve_target) = unsafe { at.resolve_target.as_ref() } {
|
||||
let view = trackers.views
|
||||
let view = trackers
|
||||
.views
|
||||
.use_extend(&*view_guard, *resolve_target, (), ())
|
||||
.unwrap();
|
||||
if let Some(ex) = extent {
|
||||
@ -397,10 +406,10 @@ pub fn command_encoder_begin_render_pass<B: GfxBackend>(
|
||||
swap_chain_links.push(link);
|
||||
}
|
||||
|
||||
let old_layout = match trackers.textures.query(
|
||||
view.texture_id.value,
|
||||
view.range.clone(),
|
||||
) {
|
||||
let old_layout = match trackers
|
||||
.textures
|
||||
.query(view.texture_id.value, view.range.clone())
|
||||
{
|
||||
Some(usage) => {
|
||||
conv::map_texture_state(usage, hal::format::Aspects::COLOR).1
|
||||
}
|
||||
@ -429,7 +438,10 @@ pub fn command_encoder_begin_render_pass<B: GfxBackend>(
|
||||
resolves.push(hal::pass::Attachment {
|
||||
format: Some(conv::map_texture_format(view.format)),
|
||||
samples: view.samples,
|
||||
ops: hal::pass::AttachmentOps::new(hal::pass::AttachmentLoadOp::DontCare, hal::pass::AttachmentStoreOp::Store),
|
||||
ops: hal::pass::AttachmentOps::new(
|
||||
hal::pass::AttachmentLoadOp::DontCare,
|
||||
hal::pass::AttachmentStoreOp::Store,
|
||||
),
|
||||
stencil_ops: hal::pass::AttachmentOps::DONT_CARE,
|
||||
layouts: old_layout .. hal::image::Layout::ColorAttachmentOptimal,
|
||||
});
|
||||
@ -466,14 +478,24 @@ pub fn command_encoder_begin_render_pass<B: GfxBackend>(
|
||||
|
||||
let mut resolve_ids = ArrayVec::<[_; crate::device::MAX_COLOR_TARGETS]>::new();
|
||||
let mut attachment_index = color_attachments.len();
|
||||
if color_attachments.iter().any(|at| at.resolve_target != ptr::null()) {
|
||||
if color_attachments
|
||||
.iter()
|
||||
.any(|at| at.resolve_target != ptr::null())
|
||||
{
|
||||
for (i, at) in color_attachments.iter().enumerate() {
|
||||
if at.resolve_target == ptr::null() {
|
||||
resolve_ids.push((hal::pass::ATTACHMENT_UNUSED, hal::image::Layout::ColorAttachmentOptimal));
|
||||
resolve_ids.push((
|
||||
hal::pass::ATTACHMENT_UNUSED,
|
||||
hal::image::Layout::ColorAttachmentOptimal,
|
||||
));
|
||||
} else {
|
||||
let sample_count_check = view_guard[color_attachments[i].attachment].samples;
|
||||
let sample_count_check =
|
||||
view_guard[color_attachments[i].attachment].samples;
|
||||
assert!(sample_count_check > 1, "RenderPassColorAttachmentDescriptor with a resolve_target must have an attachment with sample_count > 1");
|
||||
resolve_ids.push((attachment_index, hal::image::Layout::ColorAttachmentOptimal));
|
||||
resolve_ids.push((
|
||||
attachment_index,
|
||||
hal::image::Layout::ColorAttachmentOptimal,
|
||||
));
|
||||
attachment_index += 1;
|
||||
}
|
||||
}
|
||||
@ -505,9 +527,10 @@ pub fn command_encoder_begin_render_pass<B: GfxBackend>(
|
||||
let mut framebuffer_cache = device.framebuffers.lock();
|
||||
let fb_key = FramebufferKey {
|
||||
colors: color_attachments.iter().map(|at| at.attachment).collect(),
|
||||
resolves: color_attachments.iter().filter_map(|at|
|
||||
unsafe { at.resolve_target.as_ref() }.cloned()
|
||||
).collect(),
|
||||
resolves: color_attachments
|
||||
.iter()
|
||||
.filter_map(|at| unsafe { at.resolve_target.as_ref() }.cloned())
|
||||
.collect(),
|
||||
depth_stencil: depth_stencil_attachment.map(|at| at.attachment),
|
||||
};
|
||||
let framebuffer = match framebuffer_cache.entry(fb_key) {
|
||||
@ -547,15 +570,15 @@ pub fn command_encoder_begin_render_pass<B: GfxBackend>(
|
||||
use hal::format::ChannelType;
|
||||
//TODO: validate sign/unsign and normalized ranges of the color values
|
||||
let value = match key.format.unwrap().base_format().1 {
|
||||
ChannelType::Unorm |
|
||||
ChannelType::Snorm |
|
||||
ChannelType::Ufloat |
|
||||
ChannelType::Sfloat |
|
||||
ChannelType::Uscaled |
|
||||
ChannelType::Sscaled |
|
||||
ChannelType::Srgb => {
|
||||
hal::command::ClearColor::Sfloat(conv::map_color_f32(&at.clear_color))
|
||||
}
|
||||
ChannelType::Unorm
|
||||
| ChannelType::Snorm
|
||||
| ChannelType::Ufloat
|
||||
| ChannelType::Sfloat
|
||||
| ChannelType::Uscaled
|
||||
| ChannelType::Sscaled
|
||||
| ChannelType::Srgb => hal::command::ClearColor::Sfloat(
|
||||
conv::map_color_f32(&at.clear_color),
|
||||
),
|
||||
ChannelType::Sint => {
|
||||
hal::command::ClearColor::Sint(conv::map_color_i32(&at.clear_color))
|
||||
}
|
||||
@ -563,7 +586,9 @@ pub fn command_encoder_begin_render_pass<B: GfxBackend>(
|
||||
hal::command::ClearColor::Uint(conv::map_color_u32(&at.clear_color))
|
||||
}
|
||||
};
|
||||
Some(hal::command::ClearValueRaw::from(hal::command::ClearValue::Color(value)))
|
||||
Some(hal::command::ClearValueRaw::from(
|
||||
hal::command::ClearValue::Color(value),
|
||||
))
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -571,8 +596,11 @@ pub fn command_encoder_begin_render_pass<B: GfxBackend>(
|
||||
match (at.depth_load_op, at.stencil_load_op) {
|
||||
(LoadOp::Load, LoadOp::Load) => None,
|
||||
(LoadOp::Clear, _) | (_, LoadOp::Clear) => {
|
||||
let value = hal::command::ClearDepthStencil(at.clear_depth, at.clear_stencil);
|
||||
Some(hal::command::ClearValueRaw::from(hal::command::ClearValue::DepthStencil(value)))
|
||||
let value =
|
||||
hal::command::ClearDepthStencil(at.clear_depth, at.clear_stencil);
|
||||
Some(hal::command::ClearValueRaw::from(
|
||||
hal::command::ClearValue::DepthStencil(value),
|
||||
))
|
||||
}
|
||||
}
|
||||
}));
|
||||
@ -642,17 +670,15 @@ pub fn command_encoder_begin_compute_pass<B: GfxBackend>(
|
||||
let cmb = &mut cmb_guard[encoder_id];
|
||||
|
||||
let raw = cmb.raw.pop().unwrap();
|
||||
let trackers = mem::replace(
|
||||
&mut cmb.trackers,
|
||||
TrackerSet::new(encoder_id.backend()),
|
||||
);
|
||||
let trackers = mem::replace(&mut cmb.trackers, TrackerSet::new(encoder_id.backend()));
|
||||
let stored = Stored {
|
||||
value: encoder_id,
|
||||
ref_count: cmb.life_guard.ref_count.clone(),
|
||||
};
|
||||
|
||||
let pass = ComputePass::new(raw, stored, trackers);
|
||||
hub.compute_passes.register_identity(id_in, pass, &mut token)
|
||||
hub.compute_passes
|
||||
.register_identity(id_in, pass, &mut token)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "remote"))]
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::{
|
||||
gfx_select,
|
||||
command::bind::{Binder, LayoutChange},
|
||||
conv,
|
||||
device::{RenderPassContext, BIND_BUFFER_ALIGNMENT, MAX_VERTEX_BUFFERS},
|
||||
gfx_select,
|
||||
hub::{GfxBackend, Token},
|
||||
pipeline::{IndexFormat, InputStepMode, PipelineFlags},
|
||||
resource::BufferUsage,
|
||||
@ -101,7 +101,7 @@ impl VertexState {
|
||||
self.instance_limit = !0;
|
||||
for vbs in &self.inputs {
|
||||
if vbs.stride == 0 {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
let limit = (vbs.total_size / vbs.stride) as u32;
|
||||
match vbs.rate {
|
||||
@ -251,9 +251,9 @@ pub fn render_pass_set_bind_group<B: GfxBackend>(
|
||||
|
||||
pass.trackers.merge_extend(&bind_group.used);
|
||||
|
||||
if let Some((pipeline_layout_id, follow_up_sets, follow_up_offsets)) =
|
||||
pass.binder
|
||||
.provide_entry(index as usize, bind_group_id, bind_group, offsets)
|
||||
if let Some((pipeline_layout_id, follow_up_sets, follow_up_offsets)) = pass
|
||||
.binder
|
||||
.provide_entry(index as usize, bind_group_id, bind_group, offsets)
|
||||
{
|
||||
let bind_groups = iter::once(bind_group.raw.raw())
|
||||
.chain(follow_up_sets.map(|bg_id| bind_group_guard[bg_id].raw.raw()));
|
||||
@ -358,8 +358,12 @@ pub fn render_pass_set_vertex_buffers<B: GfxBackend>(
|
||||
let (buffer_guard, _) = hub.buffers.read(&mut token);
|
||||
|
||||
let pass = &mut pass_guard[pass_id];
|
||||
for (vbs, (&id, &offset)) in pass.vertex_state.inputs[start_slot as usize ..].iter_mut().zip(buffers.iter().zip(offsets)) {
|
||||
let buffer = pass.trackers
|
||||
for (vbs, (&id, &offset)) in pass.vertex_state.inputs[start_slot as usize ..]
|
||||
.iter_mut()
|
||||
.zip(buffers.iter().zip(offsets))
|
||||
{
|
||||
let buffer = pass
|
||||
.trackers
|
||||
.buffers
|
||||
.use_extend(&*buffer_guard, id, (), BufferUsage::VERTEX)
|
||||
.unwrap();
|
||||
@ -404,8 +408,14 @@ pub fn render_pass_draw<B: GfxBackend>(
|
||||
let pass = &mut pass_guard[pass_id];
|
||||
pass.is_ready().unwrap();
|
||||
|
||||
assert!(first_vertex + vertex_count <= pass.vertex_state.vertex_limit, "Vertex out of range!");
|
||||
assert!(first_instance + instance_count <= pass.vertex_state.instance_limit, "Instance out of range!");
|
||||
assert!(
|
||||
first_vertex + vertex_count <= pass.vertex_state.vertex_limit,
|
||||
"Vertex out of range!"
|
||||
);
|
||||
assert!(
|
||||
first_instance + instance_count <= pass.vertex_state.instance_limit,
|
||||
"Instance out of range!"
|
||||
);
|
||||
|
||||
unsafe {
|
||||
pass.raw.draw(
|
||||
@ -441,16 +451,16 @@ pub fn render_pass_draw_indirect<B: GfxBackend>(
|
||||
let buffer = pass
|
||||
.trackers
|
||||
.buffers
|
||||
.use_extend(&*buffer_guard, indirect_buffer_id, (), BufferUsage::INDIRECT)
|
||||
.use_extend(
|
||||
&*buffer_guard,
|
||||
indirect_buffer_id,
|
||||
(),
|
||||
BufferUsage::INDIRECT,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
pass.raw.draw_indirect(
|
||||
&buffer.raw,
|
||||
indirect_offset,
|
||||
1,
|
||||
0
|
||||
);
|
||||
pass.raw.draw_indirect(&buffer.raw, indirect_offset, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -478,8 +488,14 @@ pub fn render_pass_draw_indexed<B: GfxBackend>(
|
||||
pass.is_ready().unwrap();
|
||||
|
||||
//TODO: validate that base_vertex + max_index() is within the provided range
|
||||
assert!(first_index + index_count <= pass.index_state.limit, "Index out of range!");
|
||||
assert!(first_instance + instance_count <= pass.vertex_state.instance_limit, "Instance out of range!");
|
||||
assert!(
|
||||
first_index + index_count <= pass.index_state.limit,
|
||||
"Index out of range!"
|
||||
);
|
||||
assert!(
|
||||
first_instance + instance_count <= pass.vertex_state.instance_limit,
|
||||
"Instance out of range!"
|
||||
);
|
||||
|
||||
unsafe {
|
||||
pass.raw.draw_indexed(
|
||||
@ -517,16 +533,17 @@ pub fn render_pass_draw_indexed_indirect<B: GfxBackend>(
|
||||
let buffer = pass
|
||||
.trackers
|
||||
.buffers
|
||||
.use_extend(&*buffer_guard, indirect_buffer_id, (), BufferUsage::INDIRECT)
|
||||
.use_extend(
|
||||
&*buffer_guard,
|
||||
indirect_buffer_id,
|
||||
(),
|
||||
BufferUsage::INDIRECT,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
pass.raw.draw_indexed_indirect(
|
||||
&buffer.raw,
|
||||
indirect_offset,
|
||||
1,
|
||||
0
|
||||
);
|
||||
pass.raw
|
||||
.draw_indexed_indirect(&buffer.raw, indirect_offset, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -556,7 +573,10 @@ pub fn render_pass_set_pipeline<B: GfxBackend>(
|
||||
pass.context.compatible(&pipeline.pass_context),
|
||||
"The render pipeline is not compatible with the pass!"
|
||||
);
|
||||
assert_eq!(pipeline.sample_count, pass.sample_count, "The render pipeline and renderpass have mismatching sample_count");
|
||||
assert_eq!(
|
||||
pipeline.sample_count, pass.sample_count,
|
||||
"The render pipeline and renderpass have mismatching sample_count"
|
||||
);
|
||||
|
||||
pass.blend_color_status
|
||||
.require(pipeline.flags.contains(PipelineFlags::BLEND_COLOR));
|
||||
@ -620,11 +640,16 @@ pub fn render_pass_set_pipeline<B: GfxBackend>(
|
||||
}
|
||||
}
|
||||
// Update vertex buffer limits
|
||||
for (vbs, &(stride, rate)) in pass.vertex_state.inputs.iter_mut().zip(&pipeline.vertex_strides) {
|
||||
for (vbs, &(stride, rate)) in pass
|
||||
.vertex_state
|
||||
.inputs
|
||||
.iter_mut()
|
||||
.zip(&pipeline.vertex_strides)
|
||||
{
|
||||
vbs.stride = stride;
|
||||
vbs.rate = rate;
|
||||
}
|
||||
for vbs in pass.vertex_state.inputs[pipeline.vertex_strides.len() .. ].iter_mut() {
|
||||
for vbs in pass.vertex_state.inputs[pipeline.vertex_strides.len() ..].iter_mut() {
|
||||
vbs.stride = 0;
|
||||
vbs.rate = InputStepMode::Vertex;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
gfx_select,
|
||||
conv,
|
||||
device::{all_buffer_stages, all_image_stages},
|
||||
gfx_select,
|
||||
hub::{GfxBackend, Token},
|
||||
resource::TexturePlacement,
|
||||
swap_chain::SwapChainLink,
|
||||
@ -53,9 +53,7 @@ impl TextureCopyView {
|
||||
}
|
||||
}
|
||||
|
||||
fn to_sub_layers(
|
||||
&self, aspects: hal::format::Aspects
|
||||
) -> hal::image::SubresourceLayers {
|
||||
fn to_sub_layers(&self, aspects: hal::format::Aspects) -> hal::image::SubresourceLayers {
|
||||
let layer = self.array_layer as hal::image::Layer;
|
||||
hal::image::SubresourceLayers {
|
||||
aspects,
|
||||
@ -83,10 +81,10 @@ pub fn command_encoder_copy_buffer_to_buffer<B: GfxBackend>(
|
||||
// borrow the buffer tracker mutably...
|
||||
let mut barriers = Vec::new();
|
||||
|
||||
let (src_buffer, src_pending) = cmb
|
||||
.trackers
|
||||
.buffers
|
||||
.use_replace(&*buffer_guard, source, (), BufferUsage::COPY_SRC);
|
||||
let (src_buffer, src_pending) =
|
||||
cmb.trackers
|
||||
.buffers
|
||||
.use_replace(&*buffer_guard, source, (), BufferUsage::COPY_SRC);
|
||||
barriers.extend(src_pending.map(|pending| hal::memory::Barrier::Buffer {
|
||||
states: pending.to_states(),
|
||||
target: &src_buffer.raw,
|
||||
@ -94,10 +92,10 @@ pub fn command_encoder_copy_buffer_to_buffer<B: GfxBackend>(
|
||||
range: None .. None,
|
||||
}));
|
||||
|
||||
let (dst_buffer, dst_pending) = cmb
|
||||
.trackers
|
||||
.buffers
|
||||
.use_replace(&*buffer_guard, destination, (), BufferUsage::COPY_DST);
|
||||
let (dst_buffer, dst_pending) =
|
||||
cmb.trackers
|
||||
.buffers
|
||||
.use_replace(&*buffer_guard, destination, (), BufferUsage::COPY_DST);
|
||||
barriers.extend(dst_pending.map(|pending| hal::memory::Barrier::Buffer {
|
||||
states: pending.to_states(),
|
||||
target: &dst_buffer.raw,
|
||||
@ -153,10 +151,10 @@ pub fn command_encoder_copy_buffer_to_texture<B: GfxBackend>(
|
||||
let (texture_guard, _) = hub.textures.read(&mut token);
|
||||
let aspects = texture_guard[destination.texture].full_range.aspects;
|
||||
|
||||
let (src_buffer, src_pending) = cmb
|
||||
.trackers
|
||||
.buffers
|
||||
.use_replace(&*buffer_guard, source.buffer, (), BufferUsage::COPY_SRC);
|
||||
let (src_buffer, src_pending) =
|
||||
cmb.trackers
|
||||
.buffers
|
||||
.use_replace(&*buffer_guard, source.buffer, (), BufferUsage::COPY_SRC);
|
||||
let src_barriers = src_pending.map(|pending| hal::memory::Barrier::Buffer {
|
||||
states: pending.to_states(),
|
||||
target: &src_buffer.raw,
|
||||
@ -337,8 +335,8 @@ pub fn command_encoder_copy_texture_to_texture<B: GfxBackend>(
|
||||
// we can't hold both src_pending and dst_pending in scope because they
|
||||
// borrow the buffer tracker mutably...
|
||||
let mut barriers = Vec::new();
|
||||
let aspects = texture_guard[source.texture].full_range.aspects &
|
||||
texture_guard[destination.texture].full_range.aspects;
|
||||
let aspects = texture_guard[source.texture].full_range.aspects
|
||||
& texture_guard[destination.texture].full_range.aspects;
|
||||
|
||||
let (src_texture, src_pending) = cmb.trackers.textures.use_replace(
|
||||
&*texture_guard,
|
||||
|
@ -73,21 +73,26 @@ pub fn map_texture_usage(
|
||||
value
|
||||
}
|
||||
|
||||
pub fn map_binding_type(binding: &binding_model::BindGroupLayoutBinding) -> hal::pso::DescriptorType {
|
||||
pub fn map_binding_type(
|
||||
binding: &binding_model::BindGroupLayoutBinding,
|
||||
) -> hal::pso::DescriptorType {
|
||||
use crate::binding_model::BindingType as Bt;
|
||||
use hal::pso::DescriptorType as H;
|
||||
match binding.ty {
|
||||
Bt::UniformBuffer => if binding.dynamic {
|
||||
H::UniformBufferDynamic
|
||||
} else {
|
||||
H::UniformBuffer
|
||||
},
|
||||
Bt::StorageBuffer |
|
||||
Bt::ReadonlyStorageBuffer => if binding.dynamic {
|
||||
H::StorageBufferDynamic
|
||||
} else {
|
||||
H::StorageBuffer
|
||||
},
|
||||
Bt::UniformBuffer => {
|
||||
if binding.dynamic {
|
||||
H::UniformBufferDynamic
|
||||
} else {
|
||||
H::UniformBuffer
|
||||
}
|
||||
}
|
||||
Bt::StorageBuffer | Bt::ReadonlyStorageBuffer => {
|
||||
if binding.dynamic {
|
||||
H::StorageBufferDynamic
|
||||
} else {
|
||||
H::StorageBuffer
|
||||
}
|
||||
}
|
||||
Bt::Sampler => H::Sampler,
|
||||
Bt::SampledTexture => H::SampledImage,
|
||||
Bt::StorageTexture => H::StorageImage,
|
||||
@ -157,7 +162,7 @@ pub fn map_color_state_descriptor(
|
||||
};
|
||||
hal::pso::ColorBlendDesc {
|
||||
mask: map_color_write_flags(color_mask),
|
||||
blend: blend_state
|
||||
blend: blend_state,
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,19 +249,11 @@ pub fn map_depth_stencil_state_descriptor(
|
||||
{
|
||||
Some(hal::pso::StencilTest {
|
||||
faces: hal::pso::Sided {
|
||||
front: map_stencil_face(
|
||||
&desc.stencil_front,
|
||||
),
|
||||
back: map_stencil_face(
|
||||
&desc.stencil_back,
|
||||
),
|
||||
front: map_stencil_face(&desc.stencil_front),
|
||||
back: map_stencil_face(&desc.stencil_back),
|
||||
},
|
||||
read_masks: hal::pso::State::Static(
|
||||
hal::pso::Sided::new(desc.stencil_read_mask),
|
||||
),
|
||||
write_masks: hal::pso::State::Static(
|
||||
hal::pso::Sided::new(desc.stencil_write_mask),
|
||||
),
|
||||
read_masks: hal::pso::State::Static(hal::pso::Sided::new(desc.stencil_read_mask)),
|
||||
write_masks: hal::pso::State::Static(hal::pso::Sided::new(desc.stencil_write_mask)),
|
||||
reference_values: if desc.needs_stencil_reference() {
|
||||
hal::pso::State::Dynamic
|
||||
} else {
|
||||
@ -438,10 +435,22 @@ pub fn map_texture_dimension_size(
|
||||
}
|
||||
D2 => {
|
||||
assert_eq!(depth, 1);
|
||||
assert!(sample_size == 1 || sample_size == 2 || sample_size == 4
|
||||
|| sample_size == 8 || sample_size == 16 || sample_size == 32,
|
||||
"Invalid sample_count of {}", sample_size);
|
||||
H::D2(width, height, checked_u32_as_u16(array_size), sample_size as u8)
|
||||
assert!(
|
||||
sample_size == 1
|
||||
|| sample_size == 2
|
||||
|| sample_size == 4
|
||||
|| sample_size == 8
|
||||
|| sample_size == 16
|
||||
|| sample_size == 32,
|
||||
"Invalid sample_count of {}",
|
||||
sample_size
|
||||
);
|
||||
H::D2(
|
||||
width,
|
||||
height,
|
||||
checked_u32_as_u16(array_size),
|
||||
sample_size as u8,
|
||||
)
|
||||
}
|
||||
D3 => {
|
||||
assert_eq!(array_size, 1);
|
||||
@ -553,13 +562,28 @@ pub fn map_load_store_ops(
|
||||
}
|
||||
|
||||
pub fn map_color_f32(color: &Color) -> hal::pso::ColorValue {
|
||||
[color.r as f32, color.g as f32, color.b as f32, color.a as f32]
|
||||
[
|
||||
color.r as f32,
|
||||
color.g as f32,
|
||||
color.b as f32,
|
||||
color.a as f32,
|
||||
]
|
||||
}
|
||||
pub fn map_color_i32(color: &Color) -> [i32; 4] {
|
||||
[color.r as i32, color.g as i32, color.b as i32, color.a as i32]
|
||||
[
|
||||
color.r as i32,
|
||||
color.g as i32,
|
||||
color.b as i32,
|
||||
color.a as i32,
|
||||
]
|
||||
}
|
||||
pub fn map_color_u32(color: &Color) -> [u32; 4] {
|
||||
[color.r as u32, color.g as u32, color.b as u32, color.a as u32]
|
||||
[
|
||||
color.r as u32,
|
||||
color.g as u32,
|
||||
color.b as u32,
|
||||
color.a as u32,
|
||||
]
|
||||
}
|
||||
|
||||
pub fn map_filter(filter: resource::FilterMode) -> hal::image::Filter {
|
||||
|
@ -1,9 +1,11 @@
|
||||
#[cfg(not(feature = "remote"))]
|
||||
use crate::instance::Limits;
|
||||
use crate::{
|
||||
gfx_select,
|
||||
binding_model,
|
||||
command,
|
||||
conv,
|
||||
hub::{GLOBAL, GfxBackend, Token},
|
||||
gfx_select,
|
||||
hub::{GfxBackend, Token, GLOBAL},
|
||||
id::{Input, Output},
|
||||
pipeline,
|
||||
resource,
|
||||
@ -31,13 +33,9 @@ use crate::{
|
||||
SubmissionIndex,
|
||||
SurfaceId,
|
||||
SwapChainId,
|
||||
TextureDimension,
|
||||
TextureId,
|
||||
TextureViewId,
|
||||
TextureDimension,
|
||||
};
|
||||
#[cfg(not(feature = "remote"))]
|
||||
use crate::{
|
||||
instance::Limits,
|
||||
};
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
@ -52,20 +50,20 @@ use hal::{
|
||||
};
|
||||
use log::{info, trace};
|
||||
use parking_lot::Mutex;
|
||||
use rendy_descriptor::{DescriptorSet, DescriptorAllocator, DescriptorRanges};
|
||||
use rendy_descriptor::{DescriptorAllocator, DescriptorRanges, DescriptorSet};
|
||||
use rendy_memory::{Block, Heaps, MemoryBlock};
|
||||
|
||||
#[cfg(not(feature = "remote"))]
|
||||
use std::marker::PhantomData;
|
||||
use std::{
|
||||
collections::hash_map::Entry,
|
||||
ffi,
|
||||
iter,
|
||||
ptr,
|
||||
ops::Range,
|
||||
ptr,
|
||||
slice,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
#[cfg(not(feature = "remote"))]
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
||||
const CLEANUP_WAIT_MS: u64 = 5000;
|
||||
@ -112,7 +110,10 @@ pub(crate) struct AttachmentData<T> {
|
||||
impl<T: PartialEq> Eq for AttachmentData<T> {}
|
||||
impl<T> AttachmentData<T> {
|
||||
pub(crate) fn all(&self) -> impl Iterator<Item = &T> {
|
||||
self.colors.iter().chain(&self.resolves).chain(&self.depth_stencil)
|
||||
self.colors
|
||||
.iter()
|
||||
.chain(&self.resolves)
|
||||
.chain(&self.depth_stencil)
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,7 +223,7 @@ impl<B: GfxBackend> PendingResources<B> {
|
||||
let last_done = if done_count != 0 {
|
||||
self.active[done_count - 1].index
|
||||
} else {
|
||||
return 0
|
||||
return 0;
|
||||
};
|
||||
|
||||
for a in self.active.drain(.. done_count) {
|
||||
@ -261,11 +262,7 @@ impl<B: GfxBackend> PendingResources<B> {
|
||||
last_done
|
||||
}
|
||||
|
||||
fn triage_referenced(
|
||||
&mut self,
|
||||
trackers: &mut TrackerSet,
|
||||
mut token: &mut Token<Device<B>>,
|
||||
) {
|
||||
fn triage_referenced(&mut self, trackers: &mut TrackerSet, mut token: &mut Token<Device<B>>) {
|
||||
// Before destruction, a resource is expected to have the following strong refs:
|
||||
// - in resource itself
|
||||
// - in the device tracker
|
||||
@ -295,7 +292,7 @@ impl<B: GfxBackend> PendingResources<B> {
|
||||
let (life_guard, resource) = match resource_id {
|
||||
ResourceId::Buffer(id) => {
|
||||
if buffer_guard[id].pending_map_operation.is_some() {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
trackers.buffers.remove(id);
|
||||
let buf = buffer_guard.remove(id);
|
||||
@ -327,7 +324,10 @@ impl<B: GfxBackend> PendingResources<B> {
|
||||
let bind_group = bind_group_guard.remove(id);
|
||||
#[cfg(not(feature = "remote"))]
|
||||
hub.bind_groups.identity.lock().free(id);
|
||||
(bind_group.life_guard, NativeResource::DescriptorSet(bind_group.raw))
|
||||
(
|
||||
bind_group.life_guard,
|
||||
NativeResource::DescriptorSet(bind_group.raw),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
@ -412,7 +412,7 @@ impl<B: GfxBackend> PendingResources<B> {
|
||||
token: &mut Token<Device<B>>,
|
||||
) -> Vec<BufferMapPendingCallback> {
|
||||
if self.ready_to_map.is_empty() {
|
||||
return Vec::new()
|
||||
return Vec::new();
|
||||
}
|
||||
let (mut buffer_guard, _) = B::hub().buffers.write(token);
|
||||
self.ready_to_map
|
||||
@ -443,7 +443,8 @@ fn map_buffer<B: hal::Backend>(
|
||||
buffer_range: Range<BufferAddress>,
|
||||
kind: HostMap,
|
||||
) -> BufferMapResult {
|
||||
let is_coherent = buffer.memory
|
||||
let is_coherent = buffer
|
||||
.memory
|
||||
.properties()
|
||||
.contains(hal::memory::Properties::COHERENT);
|
||||
let (ptr, mapped_range) = {
|
||||
@ -454,10 +455,11 @@ fn map_buffer<B: hal::Backend>(
|
||||
if !is_coherent {
|
||||
match kind {
|
||||
HostMap::Read => unsafe {
|
||||
raw.invalidate_mapped_memory_ranges(
|
||||
iter::once((buffer.memory.memory(), mapped_range)),
|
||||
)
|
||||
.unwrap();
|
||||
raw.invalidate_mapped_memory_ranges(iter::once((
|
||||
buffer.memory.memory(),
|
||||
mapped_range,
|
||||
)))
|
||||
.unwrap();
|
||||
},
|
||||
HostMap::Write => {
|
||||
buffer.mapped_write_ranges.push(mapped_range);
|
||||
@ -495,30 +497,25 @@ impl<B: GfxBackend> Device<B> {
|
||||
life_guard.submission_index.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
let heaps = {
|
||||
let types = mem_props.memory_types
|
||||
.iter()
|
||||
.map(|mt| {
|
||||
use rendy_memory::{HeapsConfig, LinearConfig, DynamicConfig};
|
||||
let config = HeapsConfig {
|
||||
linear: if mt.properties.contains(hal::memory::Properties::CPU_VISIBLE) {
|
||||
Some(LinearConfig {
|
||||
linear_size: 0x10_00_00,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
},
|
||||
dynamic: Some(DynamicConfig {
|
||||
block_size_granularity: 0x1_00,
|
||||
max_chunk_size: 0x1_00_00_00,
|
||||
min_device_allocation: 0x1_00_00,
|
||||
}),
|
||||
};
|
||||
(mt.properties.into(), mt.heap_index as u32, config)
|
||||
});
|
||||
unsafe {
|
||||
Heaps::new(types, mem_props.memory_heaps.iter().cloned())
|
||||
}
|
||||
|
||||
let types = mem_props.memory_types.iter().map(|mt| {
|
||||
use rendy_memory::{DynamicConfig, HeapsConfig, LinearConfig};
|
||||
let config = HeapsConfig {
|
||||
linear: if mt.properties.contains(hal::memory::Properties::CPU_VISIBLE) {
|
||||
Some(LinearConfig {
|
||||
linear_size: 0x10_00_00,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
},
|
||||
dynamic: Some(DynamicConfig {
|
||||
block_size_granularity: 0x1_00,
|
||||
max_chunk_size: 0x1_00_00_00,
|
||||
min_device_allocation: 0x1_00_00,
|
||||
}),
|
||||
};
|
||||
(mt.properties.into(), mt.heap_index as u32, config)
|
||||
});
|
||||
unsafe { Heaps::new(types, mem_props.memory_heaps.iter().cloned()) }
|
||||
};
|
||||
|
||||
Device {
|
||||
@ -542,22 +539,23 @@ impl<B: GfxBackend> Device<B> {
|
||||
}
|
||||
}
|
||||
|
||||
fn maintain(
|
||||
&self, force_wait: bool, token: &mut Token<Self>,
|
||||
) -> Vec<BufferMapPendingCallback> {
|
||||
fn maintain(&self, force_wait: bool, token: &mut Token<Self>) -> Vec<BufferMapPendingCallback> {
|
||||
let mut pending = self.pending.lock();
|
||||
let mut trackers = self.trackers.lock();
|
||||
|
||||
pending.triage_referenced(&mut *trackers, token);
|
||||
pending.triage_mapped(token);
|
||||
pending.triage_framebuffers(&mut *self.framebuffers.lock(), token);
|
||||
let last_done = pending.cleanup(&self.raw, &self.mem_allocator, &self.desc_allocator, force_wait);
|
||||
let last_done = pending.cleanup(
|
||||
&self.raw,
|
||||
&self.mem_allocator,
|
||||
&self.desc_allocator,
|
||||
force_wait,
|
||||
);
|
||||
let callbacks = pending.handle_mapping(&self.raw, token);
|
||||
|
||||
unsafe {
|
||||
self.desc_allocator
|
||||
.lock()
|
||||
.cleanup(&self.raw);
|
||||
self.desc_allocator.lock().cleanup(&self.raw);
|
||||
}
|
||||
|
||||
if last_done != 0 {
|
||||
@ -586,14 +584,16 @@ impl<B: GfxBackend> Device<B> {
|
||||
}
|
||||
|
||||
fn create_buffer(
|
||||
&self, self_id: DeviceId, desc: &resource::BufferDescriptor
|
||||
&self,
|
||||
self_id: DeviceId,
|
||||
desc: &resource::BufferDescriptor,
|
||||
) -> resource::Buffer<B> {
|
||||
debug_assert_eq!(self_id.backend(), B::VARIANT);
|
||||
let (usage, _memory_properties) = conv::map_buffer_usage(desc.usage);
|
||||
|
||||
let rendy_usage = {
|
||||
use resource::BufferUsage as Bu;
|
||||
use rendy_memory::MemoryUsageValue as Muv;
|
||||
use resource::BufferUsage as Bu;
|
||||
|
||||
if !desc.usage.intersects(Bu::MAP_READ | Bu::MAP_WRITE) {
|
||||
Muv::Data
|
||||
@ -608,7 +608,8 @@ impl<B: GfxBackend> Device<B> {
|
||||
|
||||
let mut buffer = unsafe { self.raw.create_buffer(desc.size, usage).unwrap() };
|
||||
let requirements = unsafe { self.raw.get_buffer_requirements(&buffer) };
|
||||
let memory = self.mem_allocator
|
||||
let memory = self
|
||||
.mem_allocator
|
||||
.lock()
|
||||
.allocate(
|
||||
&self.raw,
|
||||
@ -645,7 +646,12 @@ impl<B: GfxBackend> Device<B> {
|
||||
desc: &resource::TextureDescriptor,
|
||||
) -> resource::Texture<B> {
|
||||
debug_assert_eq!(self_id.backend(), B::VARIANT);
|
||||
let kind = conv::map_texture_dimension_size(desc.dimension, desc.size, desc.array_layer_count, desc.sample_count);
|
||||
let kind = conv::map_texture_dimension_size(
|
||||
desc.dimension,
|
||||
desc.size,
|
||||
desc.array_layer_count,
|
||||
desc.sample_count,
|
||||
);
|
||||
let format = conv::map_texture_format(desc.format);
|
||||
let aspects = format.surface_desc().aspects;
|
||||
let usage = conv::map_texture_usage(desc.usage, aspects);
|
||||
@ -674,7 +680,8 @@ impl<B: GfxBackend> Device<B> {
|
||||
.unwrap();
|
||||
let requirements = unsafe { self.raw.get_image_requirements(&image) };
|
||||
|
||||
let memory = self.mem_allocator
|
||||
let memory = self
|
||||
.mem_allocator
|
||||
.lock()
|
||||
.allocate(
|
||||
&self.raw,
|
||||
@ -712,10 +719,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
|
||||
#[cfg(not(feature = "remote"))]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_device_get_limits(
|
||||
_device_id: DeviceId,
|
||||
limits: &mut Limits,
|
||||
) {
|
||||
pub extern "C" fn wgpu_device_get_limits(_device_id: DeviceId, limits: &mut Limits) {
|
||||
*limits = Limits::default(); // TODO
|
||||
}
|
||||
|
||||
@ -737,15 +741,12 @@ pub fn device_create_buffer<B: GfxBackend>(
|
||||
let buffer = device.create_buffer(device_id, desc);
|
||||
|
||||
let (id, id_out) = hub.buffers.new_identity(id_in);
|
||||
let ok = device.trackers
|
||||
.lock()
|
||||
.buffers
|
||||
.init(
|
||||
id,
|
||||
&buffer.life_guard.ref_count,
|
||||
(),
|
||||
resource::BufferUsage::empty(),
|
||||
);
|
||||
let ok = device.trackers.lock().buffers.init(
|
||||
id,
|
||||
&buffer.life_guard.ref_count,
|
||||
(),
|
||||
resource::BufferUsage::empty(),
|
||||
);
|
||||
assert!(ok);
|
||||
|
||||
hub.buffers.register(id, buffer, &mut token);
|
||||
@ -776,12 +777,7 @@ pub fn device_create_buffer_mapped<B: GfxBackend>(
|
||||
let device = &device_guard[device_id];
|
||||
let mut buffer = device.create_buffer(device_id, &desc);
|
||||
|
||||
match map_buffer(
|
||||
&device.raw,
|
||||
&mut buffer,
|
||||
0 .. desc.size,
|
||||
HostMap::Write,
|
||||
) {
|
||||
match map_buffer(&device.raw, &mut buffer, 0 .. desc.size, HostMap::Write) {
|
||||
Ok(ptr) => unsafe {
|
||||
*mapped_ptr_out = ptr;
|
||||
},
|
||||
@ -794,15 +790,12 @@ pub fn device_create_buffer_mapped<B: GfxBackend>(
|
||||
}
|
||||
|
||||
let (id, id_out) = hub.buffers.new_identity(id_in);
|
||||
let ok = device.trackers
|
||||
.lock()
|
||||
.buffers
|
||||
.init(
|
||||
id,
|
||||
&buffer.life_guard.ref_count,
|
||||
(),
|
||||
resource::BufferUsage::MAP_WRITE,
|
||||
);
|
||||
let ok = device.trackers.lock().buffers.init(
|
||||
id,
|
||||
&buffer.life_guard.ref_count,
|
||||
(),
|
||||
resource::BufferUsage::MAP_WRITE,
|
||||
);
|
||||
assert!(ok);
|
||||
|
||||
hub.buffers.register(id, buffer, &mut token);
|
||||
@ -849,20 +842,16 @@ pub fn device_create_texture<B: GfxBackend>(
|
||||
let texture = device.create_texture(device_id, desc);
|
||||
|
||||
let (id, id_out) = hub.textures.new_identity(id_in);
|
||||
let ok = device.trackers
|
||||
.lock()
|
||||
.textures
|
||||
.init(
|
||||
id,
|
||||
&texture.life_guard.ref_count,
|
||||
texture.full_range.clone(),
|
||||
resource::TextureUsage::UNINITIALIZED,
|
||||
);
|
||||
let ok = device.trackers.lock().textures.init(
|
||||
id,
|
||||
&texture.life_guard.ref_count,
|
||||
texture.full_range.clone(),
|
||||
resource::TextureUsage::UNINITIALIZED,
|
||||
);
|
||||
assert!(ok);
|
||||
|
||||
hub.textures.register(id, texture, &mut token);
|
||||
id_out
|
||||
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "remote"))]
|
||||
@ -877,7 +866,7 @@ pub extern "C" fn wgpu_device_create_texture(
|
||||
pub fn texture_create_view<B: GfxBackend>(
|
||||
texture_id: TextureId,
|
||||
desc: Option<&resource::TextureViewDescriptor>,
|
||||
id_in: Input<TextureViewId>
|
||||
id_in: Input<TextureViewId>,
|
||||
) -> Output<TextureViewId> {
|
||||
let hub = B::hub();
|
||||
let mut token = Token::root();
|
||||
@ -924,7 +913,8 @@ pub fn texture_create_view<B: GfxBackend>(
|
||||
};
|
||||
|
||||
let raw = unsafe {
|
||||
device.raw
|
||||
device
|
||||
.raw
|
||||
.create_image_view(
|
||||
&texture.raw,
|
||||
view_kind,
|
||||
@ -950,15 +940,11 @@ pub fn texture_create_view<B: GfxBackend>(
|
||||
};
|
||||
|
||||
let (id, id_out) = hub.texture_views.new_identity(id_in);
|
||||
let ok = device.trackers
|
||||
let ok = device
|
||||
.trackers
|
||||
.lock()
|
||||
.views
|
||||
.init(
|
||||
id,
|
||||
&view.life_guard.ref_count,
|
||||
(),
|
||||
(),
|
||||
);
|
||||
.init(id, &view.life_guard.ref_count, (), ());
|
||||
assert!(ok);
|
||||
|
||||
hub.texture_views.register(id, view, &mut token);
|
||||
@ -1092,13 +1078,11 @@ pub fn device_create_bind_group_layout<B: GfxBackend>(
|
||||
raw,
|
||||
bindings: bindings.to_vec(),
|
||||
desc_ranges: DescriptorRanges::from_bindings(&raw_bindings),
|
||||
dynamic_count: bindings
|
||||
.iter()
|
||||
.filter(|b| b.dynamic)
|
||||
.count(),
|
||||
dynamic_count: bindings.iter().filter(|b| b.dynamic).count(),
|
||||
};
|
||||
|
||||
hub.bind_group_layouts.register_identity(id_in, layout, &mut token)
|
||||
hub.bind_group_layouts
|
||||
.register_identity(id_in, layout, &mut token)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "remote"))]
|
||||
@ -1132,14 +1116,16 @@ pub fn device_create_pipeline_layout<B: GfxBackend>(
|
||||
device_guard[device_id]
|
||||
.raw
|
||||
.create_pipeline_layout(descriptor_set_layouts, &[])
|
||||
}.unwrap()
|
||||
}
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let layout = binding_model::PipelineLayout {
|
||||
raw: pipeline_layout,
|
||||
bind_group_layout_ids: bind_group_layout_ids.iter().cloned().collect(),
|
||||
};
|
||||
hub.pipeline_layouts.register_identity(id_in, layout, &mut token)
|
||||
hub.pipeline_layouts
|
||||
.register_identity(id_in, layout, &mut token)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "remote"))]
|
||||
@ -1168,7 +1154,8 @@ pub fn device_create_bind_group<B: GfxBackend>(
|
||||
|
||||
let desc_set = unsafe {
|
||||
let mut desc_sets = ArrayVec::<[_; 1]>::new();
|
||||
device.desc_allocator
|
||||
device
|
||||
.desc_allocator
|
||||
.lock()
|
||||
.allocate(
|
||||
&device.raw,
|
||||
@ -1248,13 +1235,13 @@ pub fn device_create_bind_group<B: GfxBackend>(
|
||||
resource::TextureUsage::SAMPLED,
|
||||
hal::image::Layout::ShaderReadOnlyOptimal,
|
||||
),
|
||||
binding_model::BindingType::StorageTexture => (
|
||||
resource::TextureUsage::STORAGE,
|
||||
hal::image::Layout::General,
|
||||
),
|
||||
binding_model::BindingType::StorageTexture => {
|
||||
(resource::TextureUsage::STORAGE, hal::image::Layout::General)
|
||||
}
|
||||
_ => panic!("Mismatched texture binding for {:?}", decl),
|
||||
};
|
||||
let view = used.views
|
||||
let view = used
|
||||
.views
|
||||
.use_extend(&*texture_view_guard, id, (), ())
|
||||
.unwrap();
|
||||
used.textures
|
||||
@ -1293,7 +1280,8 @@ pub fn device_create_bind_group<B: GfxBackend>(
|
||||
dynamic_count: bind_group_layout.dynamic_count,
|
||||
};
|
||||
let (id, id_out) = hub.bind_groups.new_identity(id_in);
|
||||
let ok = device.trackers
|
||||
let ok = device
|
||||
.trackers
|
||||
.lock()
|
||||
.bind_groups
|
||||
.init(id, &bind_group.life_guard.ref_count, (), ());
|
||||
@ -1318,10 +1306,13 @@ pub fn bind_group_destroy<B: GfxBackend>(bind_group_id: BindGroupId) {
|
||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||
let (bind_group_guard, _) = hub.bind_groups.read(&mut token);
|
||||
let bind_group = &bind_group_guard[bind_group_id];
|
||||
device_guard[bind_group.device_id.value].pending.lock().destroy(
|
||||
ResourceId::BindGroup(bind_group_id),
|
||||
bind_group.life_guard.ref_count.clone(),
|
||||
);
|
||||
device_guard[bind_group.device_id.value]
|
||||
.pending
|
||||
.lock()
|
||||
.destroy(
|
||||
ResourceId::BindGroup(bind_group_id),
|
||||
bind_group.life_guard.ref_count.clone(),
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -1332,7 +1323,7 @@ pub extern "C" fn wgpu_bind_group_destroy(bind_group_id: BindGroupId) {
|
||||
pub fn device_create_shader_module<B: GfxBackend>(
|
||||
device_id: DeviceId,
|
||||
desc: &pipeline::ShaderModuleDescriptor,
|
||||
id_in: Input<ShaderModuleId>
|
||||
id_in: Input<ShaderModuleId>,
|
||||
) -> Output<ShaderModuleId> {
|
||||
let hub = B::hub();
|
||||
let mut token = Token::root();
|
||||
@ -1349,7 +1340,8 @@ pub fn device_create_shader_module<B: GfxBackend>(
|
||||
},
|
||||
}
|
||||
};
|
||||
hub.shader_modules.register_identity(id_in, shader, &mut token)
|
||||
hub.shader_modules
|
||||
.register_identity(id_in, shader, &mut token)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "remote"))]
|
||||
@ -1384,7 +1376,8 @@ pub fn device_create_command_encoder<B: GfxBackend>(
|
||||
);
|
||||
}
|
||||
|
||||
hub.command_buffers.register_identity(id_in, comb, &mut token)
|
||||
hub.command_buffers
|
||||
.register_identity(id_in, comb, &mut token)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "remote"))]
|
||||
@ -1402,10 +1395,7 @@ pub extern "C" fn wgpu_device_get_queue(device_id: DeviceId) -> QueueId {
|
||||
device_id
|
||||
}
|
||||
|
||||
pub fn queue_submit<B: GfxBackend>(
|
||||
queue_id: QueueId,
|
||||
command_buffer_ids: &[CommandBufferId],
|
||||
) {
|
||||
pub fn queue_submit<B: GfxBackend>(queue_id: QueueId, command_buffer_ids: &[CommandBufferId]) {
|
||||
let hub = B::hub();
|
||||
|
||||
let (submit_index, fence) = {
|
||||
@ -1511,15 +1501,14 @@ pub fn queue_submit<B: GfxBackend>(
|
||||
let fence = device.raw.create_fence(false).unwrap();
|
||||
{
|
||||
let (command_buffer_guard, _) = hub.command_buffers.read(&mut token);
|
||||
let submission =
|
||||
hal::queue::Submission::<_, _, &[B::Semaphore]> {
|
||||
//TODO: may `OneShot` be enough?
|
||||
command_buffers: command_buffer_ids
|
||||
.iter()
|
||||
.flat_map(|&cmb_id| &command_buffer_guard[cmb_id].raw),
|
||||
wait_semaphores,
|
||||
signal_semaphores: &[], //TODO: signal `sem_present`?
|
||||
};
|
||||
let submission = hal::queue::Submission::<_, _, &[B::Semaphore]> {
|
||||
//TODO: may `OneShot` be enough?
|
||||
command_buffers: command_buffer_ids
|
||||
.iter()
|
||||
.flat_map(|&cmb_id| &command_buffer_guard[cmb_id].raw),
|
||||
wait_semaphores,
|
||||
signal_semaphores: &[], //TODO: signal `sem_present`?
|
||||
};
|
||||
|
||||
unsafe {
|
||||
device.queue_group.queues[0]
|
||||
@ -1577,8 +1566,11 @@ pub fn device_create_render_pipeline<B: GfxBackend>(
|
||||
let mut token = Token::root();
|
||||
|
||||
let sc = desc.sample_count;
|
||||
assert!(sc == 1 || sc == 2 || sc == 4 || sc == 8 || sc == 16 || sc == 32,
|
||||
"Invalid sample_count of {}", sc);
|
||||
assert!(
|
||||
sc == 1 || sc == 2 || sc == 4 || sc == 8 || sc == 16 || sc == 32,
|
||||
"Invalid sample_count of {}",
|
||||
sc
|
||||
);
|
||||
let sc = sc as u8;
|
||||
|
||||
let color_states =
|
||||
@ -1601,7 +1593,9 @@ pub fn device_create_render_pipeline<B: GfxBackend>(
|
||||
let mut vertex_buffers = Vec::with_capacity(desc_vbs.len());
|
||||
let mut attributes = Vec::new();
|
||||
for (i, vb_state) in desc_vbs.iter().enumerate() {
|
||||
vertex_strides.alloc().init((vb_state.stride, vb_state.step_mode));
|
||||
vertex_strides
|
||||
.alloc()
|
||||
.init((vb_state.stride, vb_state.step_mode));
|
||||
if vb_state.attributes_length == 0 {
|
||||
continue;
|
||||
}
|
||||
@ -1738,8 +1732,8 @@ pub fn device_create_render_pipeline<B: GfxBackend>(
|
||||
module: &shader_module_guard[desc.vertex_stage.module].raw,
|
||||
specialization: hal::pso::Specialization::EMPTY,
|
||||
};
|
||||
let fragment = unsafe { desc.fragment_stage.as_ref() }
|
||||
.map(|stage| hal::pso::EntryPoint::<B> {
|
||||
let fragment =
|
||||
unsafe { desc.fragment_stage.as_ref() }.map(|stage| hal::pso::EntryPoint::<B> {
|
||||
entry: unsafe { ffi::CStr::from_ptr(stage.entry_point) }
|
||||
.to_str()
|
||||
.to_owned()
|
||||
@ -1819,7 +1813,8 @@ pub fn device_create_render_pipeline<B: GfxBackend>(
|
||||
sample_count: sc,
|
||||
};
|
||||
|
||||
hub.render_pipelines.register_identity(id_in, pipeline, &mut token)
|
||||
hub.render_pipelines
|
||||
.register_identity(id_in, pipeline, &mut token)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "remote"))]
|
||||
@ -1834,7 +1829,7 @@ pub extern "C" fn wgpu_device_create_render_pipeline(
|
||||
pub fn device_create_compute_pipeline<B: GfxBackend>(
|
||||
device_id: DeviceId,
|
||||
desc: &pipeline::ComputePipelineDescriptor,
|
||||
id_in: Input<ComputePipelineId>
|
||||
id_in: Input<ComputePipelineId>,
|
||||
) -> Output<ComputePipelineId> {
|
||||
let hub = B::hub();
|
||||
let mut token = Token::root();
|
||||
@ -1879,7 +1874,8 @@ pub fn device_create_compute_pipeline<B: GfxBackend>(
|
||||
raw: raw_pipeline,
|
||||
layout_id: desc.layout,
|
||||
};
|
||||
hub.compute_pipelines.register_identity(id_in, pipeline, &mut token)
|
||||
hub.compute_pipelines
|
||||
.register_identity(id_in, pipeline, &mut token)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "remote"))]
|
||||
@ -2004,11 +2000,7 @@ pub fn device_create_swap_chain<B: GfxBackend>(
|
||||
command_pool,
|
||||
};
|
||||
|
||||
for ((i, image), (id_texture_in, id_view_in)) in images
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.zip(image_ids)
|
||||
{
|
||||
for ((i, image), (id_texture_in, id_view_in)) in images.into_iter().enumerate().zip(image_ids) {
|
||||
let kind = hal::image::Kind::D2(desc.width, desc.height, 1, 1);
|
||||
let range = hal::image::SubresourceRange {
|
||||
aspects: hal::format::Aspects::COLOR,
|
||||
@ -2072,9 +2064,7 @@ pub fn device_create_swap_chain<B: GfxBackend>(
|
||||
ref_count: view.life_guard.ref_count.clone(),
|
||||
value: id_view,
|
||||
};
|
||||
trackers
|
||||
.views
|
||||
.init(id_view, &view_id.ref_count, (), ());
|
||||
trackers.views.init(id_view, &view_id.ref_count, (), ());
|
||||
hub.texture_views.register(id_view, view, &mut token);
|
||||
|
||||
swap_chain.frames.alloc().init(swap_chain::Frame {
|
||||
|
@ -49,11 +49,7 @@ use vec_map::VecMap;
|
||||
|
||||
#[allow(unused)]
|
||||
use std::cell::Cell;
|
||||
use std::{
|
||||
marker::PhantomData,
|
||||
ops,
|
||||
sync::Arc,
|
||||
};
|
||||
use std::{marker::PhantomData, ops, sync::Arc};
|
||||
|
||||
|
||||
/// A simple structure to manage identities of objects.
|
||||
@ -236,9 +232,7 @@ impl<'a, T> Token<'a, T> {
|
||||
assert_ne!(old, 0, "Root token was dropped");
|
||||
active.set(old + 1);
|
||||
});
|
||||
Token {
|
||||
level: PhantomData,
|
||||
}
|
||||
Token { level: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
@ -249,9 +243,7 @@ impl Token<'static, Root> {
|
||||
assert_eq!(0, active.replace(1), "Root token is already active");
|
||||
});
|
||||
|
||||
Token {
|
||||
level: PhantomData,
|
||||
}
|
||||
Token { level: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
@ -289,16 +281,10 @@ impl<T, I: TypedId> Registry<T, I> {
|
||||
}
|
||||
|
||||
impl<T, I: TypedId + Copy> Registry<T, I> {
|
||||
pub fn register<A: Access<T>>(
|
||||
&self, id: I, value: T, _token: &mut Token<A>
|
||||
) {
|
||||
pub fn register<A: Access<T>>(&self, id: I, value: T, _token: &mut Token<A>) {
|
||||
let (index, epoch, backend) = id.unzip();
|
||||
debug_assert_eq!(backend, self.backend);
|
||||
let old = self
|
||||
.data
|
||||
.write()
|
||||
.map
|
||||
.insert(index as usize, (value, epoch));
|
||||
let old = self.data.write().map.insert(index as usize, (value, epoch));
|
||||
assert!(old.is_none());
|
||||
}
|
||||
|
||||
@ -315,16 +301,17 @@ impl<T, I: TypedId + Copy> Registry<T, I> {
|
||||
}
|
||||
|
||||
pub fn register_identity<A: Access<T>>(
|
||||
&self, id_in: Input<I>, value: T, token: &mut Token<A>
|
||||
&self,
|
||||
id_in: Input<I>,
|
||||
value: T,
|
||||
token: &mut Token<A>,
|
||||
) -> Output<I> {
|
||||
let (id, output) = self.new_identity(id_in);
|
||||
self.register(id, value, token);
|
||||
output
|
||||
}
|
||||
|
||||
pub fn unregister<A: Access<T>>(
|
||||
&self, id: I, _token: &mut Token<A>
|
||||
) -> (T, Token<T>) {
|
||||
pub fn unregister<A: Access<T>>(&self, id: I, _token: &mut Token<A>) -> (T, Token<T>) {
|
||||
let value = self.data.write().remove(id);
|
||||
//Note: careful about the order here!
|
||||
#[cfg(not(feature = "remote"))]
|
||||
@ -333,13 +320,15 @@ impl<T, I: TypedId + Copy> Registry<T, I> {
|
||||
}
|
||||
|
||||
pub fn read<A: Access<T>>(
|
||||
&self, _token: &mut Token<A>
|
||||
&self,
|
||||
_token: &mut Token<A>,
|
||||
) -> (RwLockReadGuard<Storage<T, I>>, Token<T>) {
|
||||
(self.data.read(), Token::new())
|
||||
}
|
||||
|
||||
pub fn write<A: Access<T>>(
|
||||
&self, _token: &mut Token<A>
|
||||
&self,
|
||||
_token: &mut Token<A>,
|
||||
) -> (RwLockWriteGuard<Storage<T, I>>, Token<T>) {
|
||||
(self.data.write(), Token::new())
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
use crate::{Backend, Epoch, Index};
|
||||
use std::{
|
||||
fmt,
|
||||
marker::PhantomData,
|
||||
};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{fmt, marker::PhantomData};
|
||||
|
||||
const BACKEND_BITS: usize = 3;
|
||||
type Dummy = crate::backend::Empty;
|
||||
@ -61,9 +58,7 @@ pub trait TypedId {
|
||||
impl<T> TypedId for Id<T> {
|
||||
fn zip(index: Index, epoch: Epoch, backend: Backend) -> Self {
|
||||
assert_eq!(0, epoch >> 32 - BACKEND_BITS);
|
||||
let v = index as u64 |
|
||||
((epoch as u64) << 32) |
|
||||
((backend as u64) << (64 - BACKEND_BITS));
|
||||
let v = index as u64 | ((epoch as u64) << 32) | ((backend as u64) << (64 - BACKEND_BITS));
|
||||
Id(v, PhantomData)
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
binding_model::MAX_BIND_GROUPS,
|
||||
device::BIND_BUFFER_ALIGNMENT,
|
||||
hub::{GLOBAL, GfxBackend, Token},
|
||||
hub::{GfxBackend, Token, GLOBAL},
|
||||
id::{Input, Output},
|
||||
AdapterId,
|
||||
Backend,
|
||||
@ -139,16 +139,16 @@ pub struct DeviceDescriptor {
|
||||
}
|
||||
|
||||
#[cfg(all(not(feature = "remote"), feature = "glutin"))]
|
||||
pub fn wgpu_create_gl_surface(windowed_context: back::glutin::RawContext<back::glutin::PossiblyCurrent>) -> SurfaceId {
|
||||
pub fn wgpu_create_gl_surface(
|
||||
windowed_context: back::glutin::RawContext<back::glutin::PossiblyCurrent>,
|
||||
) -> SurfaceId {
|
||||
let raw = back::Surface::from_context(windowed_context);
|
||||
let surface = SurfaceHandle::new(raw);
|
||||
GLOBAL.surfaces.register_local(surface, &mut Token::root())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "remote"))]
|
||||
pub fn wgpu_create_surface(
|
||||
raw_handle: raw_window_handle::RawWindowHandle,
|
||||
) -> SurfaceId {
|
||||
pub fn wgpu_create_surface(raw_handle: raw_window_handle::RawWindowHandle) -> SurfaceId {
|
||||
use raw_window_handle::RawWindowHandle as Rwh;
|
||||
|
||||
let instance = &GLOBAL.instance;
|
||||
@ -157,34 +157,42 @@ pub fn wgpu_create_surface(
|
||||
Rwh::IOS(h) => Surface {
|
||||
swap_chain: None,
|
||||
vulkan: None,
|
||||
metal: instance.metal.create_surface_from_uiview(h.ui_view, cfg!(debug_assertions)),
|
||||
metal: instance
|
||||
.metal
|
||||
.create_surface_from_uiview(h.ui_view, cfg!(debug_assertions)),
|
||||
},
|
||||
#[cfg(target_os = "macos")]
|
||||
Rwh::MacOS(h) => Surface {
|
||||
swap_chain: None,
|
||||
vulkan: instance.vulkan
|
||||
vulkan: instance
|
||||
.vulkan
|
||||
.as_ref()
|
||||
.map(|inst| inst.create_surface_from_nsview(h.ns_view)),
|
||||
metal: instance.metal.create_surface_from_nsview(h.ns_view, cfg!(debug_assertions)),
|
||||
metal: instance
|
||||
.metal
|
||||
.create_surface_from_nsview(h.ns_view, cfg!(debug_assertions)),
|
||||
},
|
||||
#[cfg(unix)]
|
||||
Rwh::X11(h) => Surface {
|
||||
swap_chain: None,
|
||||
vulkan: instance.vulkan
|
||||
vulkan: instance
|
||||
.vulkan
|
||||
.as_ref()
|
||||
.map(|inst| inst.create_surface_from_xlib(h.display as _, h.window as _)),
|
||||
},
|
||||
#[cfg(unix)]
|
||||
Rwh::Wayland(h) => Surface {
|
||||
swap_chain: None,
|
||||
vulkan: instance.vulkan
|
||||
vulkan: instance
|
||||
.vulkan
|
||||
.as_ref()
|
||||
.map(|inst| inst.create_surface_from_wayland(h.display, h.surface)),
|
||||
},
|
||||
#[cfg(windows)]
|
||||
Rwh::Windows(h) => Surface {
|
||||
swap_chain: None,
|
||||
vulkan: instance.vulkan
|
||||
vulkan: instance
|
||||
.vulkan
|
||||
.as_ref()
|
||||
.map(|inst| inst.create_surface_from_hwnd(std::ptr::null_mut(), h.hwnd)),
|
||||
//dx11: instance.dx11.create_surface_from_hwnd(h.hwnd),
|
||||
@ -196,7 +204,9 @@ pub fn wgpu_create_surface(
|
||||
};
|
||||
|
||||
let mut token = Token::root();
|
||||
GLOBAL.surfaces.register_identity(PhantomData, surface, &mut token)
|
||||
GLOBAL
|
||||
.surfaces
|
||||
.register_identity(PhantomData, surface, &mut token)
|
||||
}
|
||||
|
||||
#[cfg(all(not(feature = "remote"), unix))]
|
||||
@ -206,29 +216,32 @@ pub extern "C" fn wgpu_create_surface_from_xlib(
|
||||
window: u64,
|
||||
) -> SurfaceId {
|
||||
use raw_window_handle::unix::X11Handle;
|
||||
wgpu_create_surface(
|
||||
raw_window_handle::RawWindowHandle::X11(X11Handle {
|
||||
window,
|
||||
display: display as *mut _,
|
||||
.. X11Handle::empty()
|
||||
}),
|
||||
)
|
||||
wgpu_create_surface(raw_window_handle::RawWindowHandle::X11(X11Handle {
|
||||
window,
|
||||
display: display as *mut _,
|
||||
..X11Handle::empty()
|
||||
}))
|
||||
}
|
||||
|
||||
#[cfg(all(not(feature = "remote"), any(target_os = "ios", target_os = "macos")))]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_create_surface_from_metal_layer(
|
||||
layer: *mut std::ffi::c_void,
|
||||
) -> SurfaceId {
|
||||
pub extern "C" fn wgpu_create_surface_from_metal_layer(layer: *mut std::ffi::c_void) -> SurfaceId {
|
||||
let surface = Surface {
|
||||
swap_chain: None,
|
||||
vulkan: GLOBAL.instance.vulkan
|
||||
vulkan: GLOBAL
|
||||
.instance
|
||||
.vulkan
|
||||
.as_ref()
|
||||
.map(|inst| inst.create_surface_from_layer(h.ns_view)),
|
||||
metal: GLOBAL.instance.metal.create_surface_from_nsview(h.ns_view, cfg!(debug_assertions)),
|
||||
metal: GLOBAL
|
||||
.instance
|
||||
.metal
|
||||
.create_surface_from_nsview(h.ns_view, cfg!(debug_assertions)),
|
||||
};
|
||||
|
||||
GLOBAL.surfaces.register_identity(PhantomData, surface, &mut Token::root())
|
||||
GLOBAL
|
||||
.surfaces
|
||||
.register_identity(PhantomData, surface, &mut Token::root())
|
||||
}
|
||||
|
||||
#[cfg(all(not(feature = "remote"), windows))]
|
||||
@ -238,12 +251,12 @@ pub extern "C" fn wgpu_create_surface_from_windows_hwnd(
|
||||
hwnd: *mut std::ffi::c_void,
|
||||
) -> SurfaceId {
|
||||
use raw_window_handle::windows::Handle;
|
||||
wgpu_create_surface(
|
||||
raw_window_handle::RawWindowHandle::Windows(raw_window_handle::windows::Handle {
|
||||
wgpu_create_surface(raw_window_handle::RawWindowHandle::Windows(
|
||||
raw_window_handle::windows::Handle {
|
||||
hwnd,
|
||||
.. Handle::empty()
|
||||
}),
|
||||
)
|
||||
..Handle::empty()
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(all(not(feature = "remote"), feature = "gfx-backend-gl"))]
|
||||
@ -274,9 +287,7 @@ pub fn request_adapter(
|
||||
let id_metal = find_input(Backend::Metal);
|
||||
|
||||
let mut adapters_vk = match instance.vulkan {
|
||||
Some(ref inst) if id_vulkan.is_some() => {
|
||||
inst.enumerate_adapters()
|
||||
}
|
||||
Some(ref inst) if id_vulkan.is_some() => inst.enumerate_adapters(),
|
||||
_ => Vec::new(),
|
||||
};
|
||||
device_types.extend(adapters_vk.iter().map(|ad| ad.info.device_type.clone()));
|
||||
@ -309,7 +320,7 @@ pub fn request_adapter(
|
||||
discrete_first = discrete_first.or(Some(i));
|
||||
discrete_last = Some(i);
|
||||
}
|
||||
_ => {},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -356,9 +367,7 @@ pub fn request_adapter(
|
||||
|
||||
#[cfg(not(feature = "remote"))]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_request_adapter(
|
||||
desc: Option<&RequestAdapterOptions>,
|
||||
) -> AdapterId {
|
||||
pub extern "C" fn wgpu_request_adapter(desc: Option<&RequestAdapterOptions>) -> AdapterId {
|
||||
request_adapter(&desc.cloned().unwrap_or_default(), &[]).unwrap()
|
||||
}
|
||||
|
||||
@ -376,11 +385,13 @@ pub fn adapter_request_device<B: GfxBackend>(
|
||||
|
||||
let limits = adapter.physical_device.limits();
|
||||
assert_eq!(
|
||||
0, BIND_BUFFER_ALIGNMENT % limits.min_storage_buffer_offset_alignment,
|
||||
0,
|
||||
BIND_BUFFER_ALIGNMENT % limits.min_storage_buffer_offset_alignment,
|
||||
"Adapter storage buffer offset alignment not compatible with WGPU"
|
||||
);
|
||||
assert_eq!(
|
||||
0, BIND_BUFFER_ALIGNMENT % limits.min_uniform_buffer_offset_alignment,
|
||||
0,
|
||||
BIND_BUFFER_ALIGNMENT % limits.min_uniform_buffer_offset_alignment,
|
||||
"Adapter uniform buffer offset alignment not compatible with WGPU"
|
||||
);
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
pub mod backend {
|
||||
pub use gfx_backend_empty::Backend as Empty;
|
||||
pub use gfx_backend_vulkan::Backend as Vulkan;
|
||||
#[cfg(any(target_os = "ios", target_os = "macos"))]
|
||||
pub use gfx_backend_metal::Backend as Metal;
|
||||
pub use gfx_backend_vulkan::Backend as Vulkan;
|
||||
}
|
||||
|
||||
mod binding_model;
|
||||
@ -10,23 +10,23 @@ mod command;
|
||||
mod conv;
|
||||
mod device;
|
||||
mod hub;
|
||||
mod id;
|
||||
mod instance;
|
||||
mod pipeline;
|
||||
mod resource;
|
||||
mod swap_chain;
|
||||
mod track;
|
||||
mod id;
|
||||
|
||||
pub use self::binding_model::*;
|
||||
pub use self::command::*;
|
||||
pub use self::device::*;
|
||||
#[cfg(feature = "remote")]
|
||||
pub use self::hub::{Access, IdentityManager, Registry, Token};
|
||||
pub use self::id::*;
|
||||
pub use self::instance::*;
|
||||
pub use self::pipeline::*;
|
||||
pub use self::resource::*;
|
||||
pub use self::swap_chain::*;
|
||||
pub use self::id::*;
|
||||
pub use hal::pso::read_spirv;
|
||||
|
||||
#[cfg(feature = "glutin")]
|
||||
|
@ -2,10 +2,10 @@ use crate::{
|
||||
device::RenderPassContext,
|
||||
resource,
|
||||
BufferAddress,
|
||||
U32Array,
|
||||
PipelineLayoutId,
|
||||
RawString,
|
||||
ShaderModuleId,
|
||||
U32Array,
|
||||
};
|
||||
|
||||
use bitflags::bitflags;
|
||||
|
@ -217,9 +217,7 @@ impl<B: hal::Backend> TexturePlacement<B> {
|
||||
pub fn as_swap_chain(&self) -> &SwapChainLink<Mutex<SwapImageEpoch>> {
|
||||
match *self {
|
||||
TexturePlacement::SwapChain(ref link) => link,
|
||||
TexturePlacement::Memory(_) => {
|
||||
panic!("Expected swap chain link!")
|
||||
}
|
||||
TexturePlacement::Memory(_) => panic!("Expected swap chain link!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
gfx_select,
|
||||
conv,
|
||||
device::all_image_stages,
|
||||
gfx_select,
|
||||
hub::{GfxBackend, Token},
|
||||
resource,
|
||||
DeviceId,
|
||||
@ -118,9 +118,11 @@ pub fn swap_chain_get_next_texture<B: GfxBackend>(swap_chain_id: SwapChainId) ->
|
||||
let device = &device_guard[swap_chain.device_id.value];
|
||||
|
||||
let image_index = unsafe {
|
||||
swap_chain.raw
|
||||
swap_chain
|
||||
.raw
|
||||
.acquire_image(!0, Some(&swap_chain.sem_available), None)
|
||||
}.ok();
|
||||
}
|
||||
.ok();
|
||||
|
||||
#[cfg(not(feature = "remote"))]
|
||||
{
|
||||
@ -225,7 +227,8 @@ pub fn swap_chain_present<B: GfxBackend>(swap_chain_id: SwapChainId) {
|
||||
|
||||
trace!("transit {:?} to present", frame.texture_id.value);
|
||||
let mut trackers = device.trackers.lock();
|
||||
let barriers = trackers.textures
|
||||
let barriers = trackers
|
||||
.textures
|
||||
.change_replace(
|
||||
frame.texture_id.value,
|
||||
&texture.life_guard.ref_count,
|
||||
|
@ -1,9 +1,5 @@
|
||||
use crate::{
|
||||
conv,
|
||||
resource::BufferUsage,
|
||||
BufferId,
|
||||
};
|
||||
use super::{PendingTransition, ResourceState, Stitch, Unit};
|
||||
use crate::{conv, resource::BufferUsage, BufferId};
|
||||
use std::ops::Range;
|
||||
|
||||
//TODO: store `hal::buffer::State` here to avoid extra conversions
|
||||
@ -12,8 +8,7 @@ pub type BufferState = Unit<BufferUsage>;
|
||||
impl PendingTransition<BufferState> {
|
||||
/// Produce the gfx-hal buffer states corresponding to the transition.
|
||||
pub fn to_states(&self) -> Range<hal::buffer::State> {
|
||||
conv::map_buffer_state(self.usage.start) ..
|
||||
conv::map_buffer_state(self.usage.end)
|
||||
conv::map_buffer_state(self.usage.start) .. conv::map_buffer_state(self.usage.end)
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,10 +26,7 @@ impl ResourceState for BufferState {
|
||||
type Selector = ();
|
||||
type Usage = BufferUsage;
|
||||
|
||||
fn query(
|
||||
&self,
|
||||
_selector: Self::Selector,
|
||||
) -> Option<Self::Usage> {
|
||||
fn query(&self, _selector: Self::Selector) -> Option<Self::Usage> {
|
||||
Some(self.last)
|
||||
}
|
||||
|
||||
@ -57,10 +49,10 @@ impl ResourceState for BufferState {
|
||||
transitions.push(pending);
|
||||
usage
|
||||
}
|
||||
None => {
|
||||
if !old.is_empty() &&
|
||||
old != usage &&
|
||||
BufferUsage::WRITE_ALL.intersects(old | usage)
|
||||
None => {
|
||||
if !old.is_empty()
|
||||
&& old != usage
|
||||
&& BufferUsage::WRITE_ALL.intersects(old | usage)
|
||||
{
|
||||
return Err(pending);
|
||||
}
|
||||
@ -93,7 +85,7 @@ impl ResourceState for BufferState {
|
||||
transitions.push(pending);
|
||||
other.last
|
||||
}
|
||||
None => {
|
||||
None => {
|
||||
if !old.is_empty() && BufferUsage::WRITE_ALL.intersects(old | new) {
|
||||
return Err(pending);
|
||||
}
|
||||
@ -104,14 +96,13 @@ impl ResourceState for BufferState {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn optimize(&mut self) {
|
||||
}
|
||||
fn optimize(&mut self) {}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::{Backend, TypedId};
|
||||
use super::*;
|
||||
use crate::{Backend, TypedId};
|
||||
|
||||
#[test]
|
||||
fn change() {
|
||||
@ -121,7 +112,8 @@ mod test {
|
||||
};
|
||||
let id = TypedId::zip(0, 0, Backend::Empty);
|
||||
assert!(bs.change(id, (), BufferUsage::VERTEX, None).is_err());
|
||||
bs.change(id, (), BufferUsage::VERTEX, Some(&mut Vec::new())).unwrap();
|
||||
bs.change(id, (), BufferUsage::VERTEX, Some(&mut Vec::new()))
|
||||
.unwrap();
|
||||
bs.change(id, (), BufferUsage::INDEX, None).unwrap();
|
||||
assert_eq!(bs.last, BufferUsage::VERTEX | BufferUsage::INDEX);
|
||||
}
|
||||
|
@ -2,16 +2,7 @@ mod buffer;
|
||||
mod range;
|
||||
mod texture;
|
||||
|
||||
use crate::{
|
||||
hub::Storage,
|
||||
Backend,
|
||||
Epoch,
|
||||
Index,
|
||||
RefCount,
|
||||
TextureViewId,
|
||||
TypedId,
|
||||
BindGroupId,
|
||||
};
|
||||
use crate::{hub::Storage, Backend, BindGroupId, Epoch, Index, RefCount, TextureViewId, TypedId};
|
||||
|
||||
use hal::backend::FastHashMap;
|
||||
|
||||
@ -84,10 +75,7 @@ pub trait ResourceState: Clone + Default {
|
||||
/// Returns `None` if no sub-resources
|
||||
/// are intersecting with the selector, or their usage
|
||||
/// isn't consistent.
|
||||
fn query(
|
||||
&self,
|
||||
selector: Self::Selector,
|
||||
) -> Option<Self::Usage>;
|
||||
fn query(&self, selector: Self::Selector) -> Option<Self::Usage>;
|
||||
|
||||
/// Change the last usage of the selected sub-resources.
|
||||
///
|
||||
@ -197,9 +185,7 @@ impl<S: ResourceState> ResourceTracker<S> {
|
||||
let backend = self.backend;
|
||||
self.map
|
||||
.iter()
|
||||
.map(move |(&index, resource)| {
|
||||
S::Id::zip(index, resource.epoch, backend)
|
||||
})
|
||||
.map(move |(&index, resource)| S::Id::zip(index, resource.epoch, backend))
|
||||
}
|
||||
|
||||
/// Clear the tracked contents.
|
||||
@ -218,12 +204,7 @@ impl<S: ResourceState> ResourceTracker<S> {
|
||||
default: S::Usage,
|
||||
) -> bool {
|
||||
let mut state = S::default();
|
||||
match state.change(
|
||||
id,
|
||||
selector,
|
||||
default,
|
||||
None,
|
||||
) {
|
||||
match state.change(id, selector, default, None) {
|
||||
Ok(()) => (),
|
||||
Err(_) => unreachable!(),
|
||||
}
|
||||
@ -231,11 +212,14 @@ impl<S: ResourceState> ResourceTracker<S> {
|
||||
let (index, epoch, backend) = id.unzip();
|
||||
debug_assert_eq!(backend, self.backend);
|
||||
self.map
|
||||
.insert(index, Resource {
|
||||
ref_count: ref_count.clone(),
|
||||
state,
|
||||
epoch,
|
||||
})
|
||||
.insert(
|
||||
index,
|
||||
Resource {
|
||||
ref_count: ref_count.clone(),
|
||||
state,
|
||||
epoch,
|
||||
},
|
||||
)
|
||||
.is_none()
|
||||
}
|
||||
|
||||
@ -243,11 +227,7 @@ impl<S: ResourceState> ResourceTracker<S> {
|
||||
///
|
||||
/// Returns `Some(Usage)` only if this usage is consistent
|
||||
/// across the given selector.
|
||||
pub fn query(
|
||||
&mut self,
|
||||
id: S::Id,
|
||||
selector: S::Selector,
|
||||
) -> Option<S::Usage> {
|
||||
pub fn query(&mut self, id: S::Id, selector: S::Selector) -> Option<S::Usage> {
|
||||
let (index, epoch, backend) = id.unzip();
|
||||
debug_assert_eq!(backend, self.backend);
|
||||
let res = self.map.get(&index)?;
|
||||
@ -266,13 +246,11 @@ impl<S: ResourceState> ResourceTracker<S> {
|
||||
let (index, epoch, backend) = id.unzip();
|
||||
debug_assert_eq!(self_backend, backend);
|
||||
match map.entry(index) {
|
||||
Entry::Vacant(e) => {
|
||||
e.insert(Resource {
|
||||
ref_count: ref_count.clone(),
|
||||
state: S::default(),
|
||||
epoch,
|
||||
})
|
||||
}
|
||||
Entry::Vacant(e) => e.insert(Resource {
|
||||
ref_count: ref_count.clone(),
|
||||
state: S::default(),
|
||||
epoch,
|
||||
}),
|
||||
Entry::Occupied(e) => {
|
||||
assert_eq!(e.get().epoch, epoch);
|
||||
e.into_mut()
|
||||
@ -291,7 +269,8 @@ impl<S: ResourceState> ResourceTracker<S> {
|
||||
usage: S::Usage,
|
||||
) -> Result<(), PendingTransition<S>> {
|
||||
Self::get_or_insert(self.backend, &mut self.map, id, ref_count)
|
||||
.state.change(id, selector, usage, None)
|
||||
.state
|
||||
.change(id, selector, usage, None)
|
||||
}
|
||||
|
||||
/// Replace the usage of a specified resource.
|
||||
@ -303,16 +282,15 @@ impl<S: ResourceState> ResourceTracker<S> {
|
||||
usage: S::Usage,
|
||||
) -> Drain<PendingTransition<S>> {
|
||||
let res = Self::get_or_insert(self.backend, &mut self.map, id, ref_count);
|
||||
res.state.change(id, selector, usage, Some(&mut self.temp))
|
||||
res.state
|
||||
.change(id, selector, usage, Some(&mut self.temp))
|
||||
.ok(); //TODO: unwrap?
|
||||
self.temp.drain(..)
|
||||
}
|
||||
|
||||
/// Merge another tracker into `self` by extending the current states
|
||||
/// without any transitions.
|
||||
pub fn merge_extend(
|
||||
&mut self, other: &Self,
|
||||
) -> Result<(), PendingTransition<S>> {
|
||||
pub fn merge_extend(&mut self, other: &Self) -> Result<(), PendingTransition<S>> {
|
||||
debug_assert_eq!(self.backend, other.backend);
|
||||
for (&index, new) in other.map.iter() {
|
||||
match self.map.entry(index) {
|
||||
@ -322,7 +300,9 @@ impl<S: ResourceState> ResourceTracker<S> {
|
||||
Entry::Occupied(e) => {
|
||||
assert_eq!(e.get().epoch, new.epoch);
|
||||
let id = S::Id::zip(index, new.epoch, self.backend);
|
||||
e.into_mut().state.merge(id, &new.state, Stitch::Last, None)?;
|
||||
e.into_mut()
|
||||
.state
|
||||
.merge(id, &new.state, Stitch::Last, None)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -344,7 +324,8 @@ impl<S: ResourceState> ResourceTracker<S> {
|
||||
Entry::Occupied(e) => {
|
||||
assert_eq!(e.get().epoch, new.epoch);
|
||||
let id = S::Id::zip(index, new.epoch, self.backend);
|
||||
e.into_mut().state
|
||||
e.into_mut()
|
||||
.state
|
||||
.merge(id, &new.state, stitch, Some(&mut self.temp))
|
||||
.ok(); //TODO: unwrap?
|
||||
}
|
||||
@ -394,10 +375,7 @@ impl<I: Copy + Debug + TypedId> ResourceState for PhantomData<I> {
|
||||
type Selector = ();
|
||||
type Usage = ();
|
||||
|
||||
fn query(
|
||||
&self,
|
||||
_selector: Self::Selector,
|
||||
) -> Option<Self::Usage> {
|
||||
fn query(&self, _selector: Self::Selector) -> Option<Self::Usage> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
@ -421,8 +399,7 @@ impl<I: Copy + Debug + TypedId> ResourceState for PhantomData<I> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn optimize(&mut self) {
|
||||
}
|
||||
fn optimize(&mut self) {}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,10 +1,4 @@
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
fmt::Debug,
|
||||
iter::Peekable,
|
||||
ops::Range,
|
||||
slice::Iter,
|
||||
};
|
||||
use std::{cmp::Ordering, fmt::Debug, iter::Peekable, ops::Range, slice::Iter};
|
||||
|
||||
/// Structure that keeps track of a I -> T mapping,
|
||||
/// optimized for a case where keys of the same values
|
||||
@ -18,9 +12,7 @@ pub struct RangedStates<I, T> {
|
||||
|
||||
impl<I, T> Default for RangedStates<I, T> {
|
||||
fn default() -> Self {
|
||||
RangedStates {
|
||||
ranges: Vec::new(),
|
||||
}
|
||||
RangedStates { ranges: Vec::new() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,7 +48,7 @@ impl<I: Copy + PartialOrd, T: Copy + PartialEq> RangedStates<I, T> {
|
||||
for a in self.ranges.iter() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -88,14 +80,16 @@ impl<I: Copy + PartialOrd, T: Copy + PartialEq> RangedStates<I, T> {
|
||||
/// Returns `None` if no intersections are detected.
|
||||
/// Returns `Some(Err)` if the intersected values are inconsistent.
|
||||
pub fn query<U: PartialEq>(
|
||||
&self, index: &Range<I>, fun: impl Fn(&T) -> U
|
||||
&self,
|
||||
index: &Range<I>,
|
||||
fun: impl Fn(&T) -> U,
|
||||
) -> Option<Result<U, ()>> {
|
||||
let mut result = None;
|
||||
for &(ref range, ref value) in self.ranges.iter() {
|
||||
if range.end > index.start && range.start < index.end {
|
||||
let old = result.replace(fun(value));
|
||||
if old.is_some() && old != result {
|
||||
return Some(Err(()))
|
||||
return Some(Err(()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -111,10 +105,7 @@ impl<I: Copy + PartialOrd, T: Copy + PartialEq> RangedStates<I, T> {
|
||||
// 1. scan the ranges to figure out how many extra ones need to be inserted
|
||||
// 2. go through the ranges by moving them them to the right and inserting the missing ones
|
||||
|
||||
let mut start_pos = match self.ranges
|
||||
.iter()
|
||||
.position(|pair| pair.0.end > index.start)
|
||||
{
|
||||
let mut start_pos = match self.ranges.iter().position(|pair| pair.0.end > index.start) {
|
||||
Some(pos) => pos,
|
||||
None => {
|
||||
let pos = self.ranges.len();
|
||||
@ -127,7 +118,8 @@ impl<I: Copy + PartialOrd, T: Copy + PartialEq> RangedStates<I, T> {
|
||||
let (range, value) = self.ranges[start_pos].clone();
|
||||
if range.start < index.start {
|
||||
self.ranges[start_pos].0.start = index.start;
|
||||
self.ranges.insert(start_pos, (range.start .. index.start, value));
|
||||
self.ranges
|
||||
.insert(start_pos, (range.start .. index.start, value));
|
||||
start_pos += 1;
|
||||
}
|
||||
}
|
||||
@ -203,23 +195,30 @@ impl<'a, I: Copy + Debug + Ord, T: Copy + Debug> Iterator for Merge<'a, I, T> {
|
||||
match (self.sa.peek(), self.sb.peek()) {
|
||||
// we have both streams
|
||||
(Some(&(ref ra, va)), Some(&(ref rb, vb))) => {
|
||||
let (range, usage) = if ra.start < self.base { // in the middle of the left stream
|
||||
if self.base == rb.start { // right stream is starting
|
||||
let (range, usage) = if ra.start < self.base {
|
||||
// in the middle of the left stream
|
||||
if self.base == rb.start {
|
||||
// right stream is starting
|
||||
debug_assert!(self.base < ra.end);
|
||||
(self.base .. ra.end.min(rb.end), Some(*va) .. Some(*vb))
|
||||
} else { // right hasn't started yet
|
||||
} else {
|
||||
// right hasn't started yet
|
||||
debug_assert!(self.base < rb.start);
|
||||
(self.base .. rb.start, Some(*va) .. None)
|
||||
}
|
||||
} else if rb.start < self.base { // in the middle of the right stream
|
||||
if self.base == ra.start { // left stream is starting
|
||||
} else if rb.start < self.base {
|
||||
// in the middle of the right stream
|
||||
if self.base == ra.start {
|
||||
// left stream is starting
|
||||
debug_assert!(self.base < rb.end);
|
||||
(self.base .. ra.end.min(rb.end), Some(*va) .. Some(*vb))
|
||||
} else { // left hasn't started yet
|
||||
} else {
|
||||
// left hasn't started yet
|
||||
debug_assert!(self.base < ra.start);
|
||||
(self.base .. ra.start, None .. Some(*vb))
|
||||
}
|
||||
} else { // no active streams
|
||||
} else {
|
||||
// no active streams
|
||||
match ra.start.cmp(&rb.start) {
|
||||
// both are starting
|
||||
Ordering::Equal => (ra.start .. ra.end.min(rb.end), Some(*va) .. Some(*vb)),
|
||||
@ -262,160 +261,111 @@ impl<'a, I: Copy + Debug + Ord, T: Copy + Debug> Iterator for Merge<'a, I, T> {
|
||||
mod test {
|
||||
//TODO: randomized/fuzzy testing
|
||||
use super::RangedStates;
|
||||
use std::{ fmt::Debug, ops::Range };
|
||||
use std::{fmt::Debug, ops::Range};
|
||||
|
||||
fn easy_merge<T: PartialEq + Copy + Debug>(
|
||||
ra: Vec<(Range<usize>, T)>, rb: Vec<(Range<usize>, T)>
|
||||
ra: Vec<(Range<usize>, T)>,
|
||||
rb: Vec<(Range<usize>, T)>,
|
||||
) -> Vec<(Range<usize>, Range<Option<T>>)> {
|
||||
RangedStates { ranges: ra }.merge(&RangedStates { ranges: rb }, 0).collect()
|
||||
RangedStates { ranges: ra }
|
||||
.merge(&RangedStates { ranges: rb }, 0)
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sane_good() {
|
||||
let rs = RangedStates { ranges: vec![
|
||||
(1..4, 9u8),
|
||||
(4..5, 9),
|
||||
]};
|
||||
let rs = RangedStates {
|
||||
ranges: vec![(1 .. 4, 9u8), (4 .. 5, 9)],
|
||||
};
|
||||
rs.check_sanity();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn sane_empty() {
|
||||
let rs = RangedStates { ranges: vec![
|
||||
(1..4, 9u8),
|
||||
(5..5, 9),
|
||||
]};
|
||||
let rs = RangedStates {
|
||||
ranges: vec![(1 .. 4, 9u8), (5 .. 5, 9)],
|
||||
};
|
||||
rs.check_sanity();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn sane_intersect() {
|
||||
let rs = RangedStates { ranges: vec![
|
||||
(1..4, 9u8),
|
||||
(3..5, 9),
|
||||
]};
|
||||
let rs = RangedStates {
|
||||
ranges: vec![(1 .. 4, 9u8), (3 .. 5, 9)],
|
||||
};
|
||||
rs.check_sanity();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coalesce() {
|
||||
let mut rs = RangedStates { ranges: vec![
|
||||
(1..4, 9u8),
|
||||
(4..5, 9),
|
||||
(5..7, 1),
|
||||
(8..9, 1),
|
||||
]};
|
||||
let mut rs = RangedStates {
|
||||
ranges: vec![(1 .. 4, 9u8), (4 .. 5, 9), (5 .. 7, 1), (8 .. 9, 1)],
|
||||
};
|
||||
rs.coalesce();
|
||||
rs.check_sanity();
|
||||
assert_eq!(rs.ranges, vec![
|
||||
(1..5, 9),
|
||||
(5..7, 1),
|
||||
(8..9, 1),
|
||||
]);
|
||||
assert_eq!(rs.ranges, vec![(1 .. 5, 9), (5 .. 7, 1), (8 .. 9, 1),]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn query() {
|
||||
let rs = RangedStates { ranges: vec![
|
||||
(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(&(1..6), |v| *v), Some(Err(())));
|
||||
let rs = RangedStates {
|
||||
ranges: vec![(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(&(1 .. 6), |v| *v), Some(Err(())));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn isolate() {
|
||||
let rs = RangedStates { ranges: vec![
|
||||
(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(0..6, 0), &[
|
||||
(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!(&rs.sanely_isolated(6..9, 0), &[
|
||||
(6..7, 1),
|
||||
(7..8, 0),
|
||||
(8..9, 1),
|
||||
]);
|
||||
let rs = RangedStates {
|
||||
ranges: vec![(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(0 .. 6, 0),
|
||||
&[(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!(
|
||||
&rs.sanely_isolated(6 .. 9, 0),
|
||||
&[(6 .. 7, 1), (7 .. 8, 0), (8 .. 9, 1),]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merge_same() {
|
||||
assert_eq!(
|
||||
easy_merge(
|
||||
vec![
|
||||
(1..4, 0u8),
|
||||
],
|
||||
vec![
|
||||
(1..4, 2u8),
|
||||
],
|
||||
),
|
||||
vec![
|
||||
(1..4, Some(0)..Some(2)),
|
||||
]
|
||||
easy_merge(vec![(1 .. 4, 0u8),], vec![(1 .. 4, 2u8),],),
|
||||
vec![(1 .. 4, Some(0) .. Some(2)),]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merge_empty() {
|
||||
assert_eq!(
|
||||
easy_merge(
|
||||
vec![
|
||||
(1..2, 0u8),
|
||||
],
|
||||
vec![
|
||||
],
|
||||
),
|
||||
vec![
|
||||
(1..2, Some(0)..None),
|
||||
]
|
||||
easy_merge(vec![(1 .. 2, 0u8),], vec![],),
|
||||
vec![(1 .. 2, Some(0) .. None),]
|
||||
);
|
||||
assert_eq!(
|
||||
easy_merge(
|
||||
vec![
|
||||
],
|
||||
vec![
|
||||
(3..4, 1u8),
|
||||
],
|
||||
),
|
||||
vec![
|
||||
(3..4, None..Some(1)),
|
||||
]
|
||||
easy_merge(vec![], vec![(3 .. 4, 1u8),],),
|
||||
vec![(3 .. 4, None .. Some(1)),]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merge_separate() {
|
||||
assert_eq!(
|
||||
easy_merge(
|
||||
vec![
|
||||
(1..2, 0u8),
|
||||
(5..6, 1u8),
|
||||
],
|
||||
vec![
|
||||
(2..4, 2u8),
|
||||
],
|
||||
),
|
||||
easy_merge(vec![(1 .. 2, 0u8), (5 .. 6, 1u8),], vec![(2 .. 4, 2u8),],),
|
||||
vec![
|
||||
(1..2, Some(0)..None),
|
||||
(2..4, None..Some(2)),
|
||||
(5..6, Some(1)..None),
|
||||
(1 .. 2, Some(0) .. None),
|
||||
(2 .. 4, None .. Some(2)),
|
||||
(5 .. 6, Some(1) .. None),
|
||||
]
|
||||
);
|
||||
}
|
||||
@ -423,33 +373,16 @@ mod test {
|
||||
#[test]
|
||||
fn merge_subset() {
|
||||
assert_eq!(
|
||||
easy_merge(
|
||||
vec![
|
||||
(1..6, 0u8),
|
||||
],
|
||||
vec![
|
||||
(2..4, 2u8),
|
||||
],
|
||||
),
|
||||
easy_merge(vec![(1 .. 6, 0u8),], vec![(2 .. 4, 2u8),],),
|
||||
vec![
|
||||
(1..2, Some(0)..None),
|
||||
(2..4, Some(0)..Some(2)),
|
||||
(4..6, Some(0)..None),
|
||||
(1 .. 2, Some(0) .. None),
|
||||
(2 .. 4, Some(0) .. Some(2)),
|
||||
(4 .. 6, Some(0) .. None),
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
easy_merge(
|
||||
vec![
|
||||
(2..4, 0u8),
|
||||
],
|
||||
vec![
|
||||
(1..4, 2u8),
|
||||
],
|
||||
),
|
||||
vec![
|
||||
(1..2, None..Some(2)),
|
||||
(2..4, Some(0)..Some(2)),
|
||||
]
|
||||
easy_merge(vec![(2 .. 4, 0u8),], vec![(1 .. 4, 2u8),],),
|
||||
vec![(1 .. 2, None .. Some(2)), (2 .. 4, Some(0) .. Some(2)),]
|
||||
);
|
||||
}
|
||||
|
||||
@ -457,23 +390,17 @@ mod test {
|
||||
fn merge_all() {
|
||||
assert_eq!(
|
||||
easy_merge(
|
||||
vec![
|
||||
(1..4, 0u8),
|
||||
(5..8, 1u8),
|
||||
],
|
||||
vec![
|
||||
(2..6, 2u8),
|
||||
(7..9, 3u8),
|
||||
],
|
||||
vec![(1 .. 4, 0u8), (5 .. 8, 1u8),],
|
||||
vec![(2 .. 6, 2u8), (7 .. 9, 3u8),],
|
||||
),
|
||||
vec![
|
||||
(1..2, Some(0)..None),
|
||||
(2..4, Some(0)..Some(2)),
|
||||
(4..5, None..Some(2)),
|
||||
(5..6, Some(1)..Some(2)),
|
||||
(6..7, Some(1)..None),
|
||||
(7..8, Some(1)..Some(3)),
|
||||
(8..9, None..Some(3)),
|
||||
(1 .. 2, Some(0) .. None),
|
||||
(2 .. 4, Some(0) .. Some(2)),
|
||||
(4 .. 5, None .. Some(2)),
|
||||
(5 .. 6, Some(1) .. Some(2)),
|
||||
(6 .. 7, Some(1) .. None),
|
||||
(7 .. 8, Some(1) .. Some(3)),
|
||||
(8 .. 9, None .. Some(3)),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -1,10 +1,5 @@
|
||||
use crate::{
|
||||
conv,
|
||||
device::MAX_MIP_LEVELS,
|
||||
resource::TextureUsage,
|
||||
TextureId,
|
||||
};
|
||||
use super::{range::RangedStates, PendingTransition, ResourceState, Stitch, Unit};
|
||||
use crate::{conv, device::MAX_MIP_LEVELS, resource::TextureUsage, TextureId};
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
|
||||
@ -30,8 +25,8 @@ pub struct TextureState {
|
||||
impl PendingTransition<TextureState> {
|
||||
/// Produce the gfx-hal image states corresponding to the transition.
|
||||
pub fn to_states(&self) -> Range<hal::image::State> {
|
||||
conv::map_texture_state(self.usage.start, self.selector.aspects) ..
|
||||
conv::map_texture_state(self.usage.end, self.selector.aspects)
|
||||
conv::map_texture_state(self.usage.start, self.selector.aspects)
|
||||
.. conv::map_texture_state(self.usage.end, self.selector.aspects)
|
||||
}
|
||||
|
||||
//TODO: make this less awkward!
|
||||
@ -42,7 +37,9 @@ impl PendingTransition<TextureState> {
|
||||
///
|
||||
/// When a transition is generated, returns the specified `replace` usage.
|
||||
fn record(
|
||||
self, output: Option<&mut &mut Vec<Self>>, replace: TextureUsage
|
||||
self,
|
||||
output: Option<&mut &mut Vec<Self>>,
|
||||
replace: TextureUsage,
|
||||
) -> Result<TextureUsage, Self> {
|
||||
let u = self.usage.clone();
|
||||
match output {
|
||||
@ -51,9 +48,9 @@ impl PendingTransition<TextureState> {
|
||||
Ok(replace)
|
||||
}
|
||||
None => {
|
||||
if !u.start.is_empty() &&
|
||||
u.start != u.end &&
|
||||
TextureUsage::WRITE_ALL.intersects(u.start | u.end)
|
||||
if !u.start.is_empty()
|
||||
&& u.start != u.end
|
||||
&& TextureUsage::WRITE_ALL.intersects(u.start | u.end)
|
||||
{
|
||||
Err(self)
|
||||
} else {
|
||||
@ -69,10 +66,7 @@ impl ResourceState for TextureState {
|
||||
type Selector = hal::image::SubresourceRange;
|
||||
type Usage = TextureUsage;
|
||||
|
||||
fn query(
|
||||
&self,
|
||||
selector: Self::Selector,
|
||||
) -> Option<Self::Usage> {
|
||||
fn query(&self, selector: Self::Selector) -> Option<Self::Usage> {
|
||||
let mut result = None;
|
||||
let num_levels = self.mips.len();
|
||||
let mip_start = num_levels.min(selector.levels.start as usize);
|
||||
@ -84,7 +78,7 @@ impl ResourceState for TextureState {
|
||||
(hal::format::Aspects::STENCIL, &mip.stencil),
|
||||
] {
|
||||
if !selector.aspects.contains(aspect) {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
match plane_states.query(&selector.layers, |unit| unit.last) {
|
||||
None => {}
|
||||
@ -92,8 +86,7 @@ impl ResourceState for TextureState {
|
||||
Some(Ok(usage)) if result.is_none() => {
|
||||
result = Some(usage);
|
||||
}
|
||||
Some(Ok(_)) |
|
||||
Some(Err(())) => return None,
|
||||
Some(Ok(_)) | Some(Err(())) => return None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -110,8 +103,8 @@ impl ResourceState for TextureState {
|
||||
while self.mips.len() < selector.levels.end as usize {
|
||||
self.mips.push(MipState::default());
|
||||
}
|
||||
for (mip_id, mip) in self
|
||||
.mips[selector.levels.start as usize .. selector.levels.end as usize]
|
||||
for (mip_id, mip) in self.mips
|
||||
[selector.levels.start as usize .. selector.levels.end as usize]
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
{
|
||||
@ -122,12 +115,12 @@ impl ResourceState for TextureState {
|
||||
(hal::format::Aspects::STENCIL, &mut mip.stencil),
|
||||
] {
|
||||
if !selector.aspects.contains(aspect) {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
let layers = plane_states.isolate(&selector.layers, Unit::new(usage));
|
||||
for &mut (ref range, ref mut unit) in layers {
|
||||
if unit.last == usage && TextureUsage::ORDERED.contains(usage) {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
let pending = PendingTransition {
|
||||
id,
|
||||
@ -159,28 +152,50 @@ impl ResourceState for TextureState {
|
||||
self.mips.push(MipState::default());
|
||||
}
|
||||
|
||||
for (mip_id, (mip_self, mip_other)) in self.mips
|
||||
.iter_mut()
|
||||
.zip(&other.mips)
|
||||
.enumerate()
|
||||
{
|
||||
for (mip_id, (mip_self, mip_other)) in self.mips.iter_mut().zip(&other.mips).enumerate() {
|
||||
let level = mip_id as hal::image::Level;
|
||||
for &mut (aspects, ref mut planes_self, planes_other) in &mut [
|
||||
(hal::format::Aspects::COLOR, &mut mip_self.color, &mip_other.color),
|
||||
(hal::format::Aspects::DEPTH, &mut mip_self.depth, &mip_other.depth),
|
||||
(hal::format::Aspects::STENCIL, &mut mip_self.stencil, &mip_other.stencil),
|
||||
(
|
||||
hal::format::Aspects::COLOR,
|
||||
&mut mip_self.color,
|
||||
&mip_other.color,
|
||||
),
|
||||
(
|
||||
hal::format::Aspects::DEPTH,
|
||||
&mut mip_self.depth,
|
||||
&mip_other.depth,
|
||||
),
|
||||
(
|
||||
hal::format::Aspects::STENCIL,
|
||||
&mut mip_self.stencil,
|
||||
&mip_other.stencil,
|
||||
),
|
||||
] {
|
||||
temp.extend(planes_self.merge(planes_other, 0));
|
||||
planes_self.clear();
|
||||
|
||||
for (layers, states) in temp.drain(..) {
|
||||
let unit = match states {
|
||||
Range { start: None, end: None } => unreachable!(),
|
||||
Range { start: Some(start), end: None } => start,
|
||||
Range { start: None, end: Some(end) } => end,
|
||||
Range { start: Some(start), end: Some(end) } => {
|
||||
Range {
|
||||
start: None,
|
||||
end: None,
|
||||
} => unreachable!(),
|
||||
Range {
|
||||
start: Some(start),
|
||||
end: None,
|
||||
} => start,
|
||||
Range {
|
||||
start: None,
|
||||
end: Some(end),
|
||||
} => end,
|
||||
Range {
|
||||
start: Some(start),
|
||||
end: Some(end),
|
||||
} => {
|
||||
let mut final_usage = end.select(stitch);
|
||||
if start.last != final_usage || !TextureUsage::ORDERED.contains(final_usage) {
|
||||
if start.last != final_usage
|
||||
|| !TextureUsage::ORDERED.contains(final_usage)
|
||||
{
|
||||
let pending = PendingTransition {
|
||||
id,
|
||||
selector: hal::image::SubresourceRange {
|
||||
@ -221,10 +236,7 @@ mod test {
|
||||
//TODO: change() and merge() tests
|
||||
//use crate::TypedId;
|
||||
use super::*;
|
||||
use hal::{
|
||||
format::Aspects,
|
||||
image::SubresourceRange,
|
||||
};
|
||||
use hal::{format::Aspects, image::SubresourceRange};
|
||||
|
||||
#[test]
|
||||
fn query() {
|
||||
@ -232,15 +244,15 @@ mod test {
|
||||
ts.mips.push(MipState::default());
|
||||
ts.mips.push(MipState::default());
|
||||
ts.mips[1].color = PlaneStates::new(&[
|
||||
(1..3, Unit::new(TextureUsage::SAMPLED)),
|
||||
(3..5, Unit::new(TextureUsage::SAMPLED)),
|
||||
(5..6, Unit::new(TextureUsage::STORAGE)),
|
||||
(1 .. 3, Unit::new(TextureUsage::SAMPLED)),
|
||||
(3 .. 5, Unit::new(TextureUsage::SAMPLED)),
|
||||
(5 .. 6, Unit::new(TextureUsage::STORAGE)),
|
||||
]);
|
||||
assert_eq!(
|
||||
ts.query(SubresourceRange {
|
||||
aspects: Aspects::COLOR,
|
||||
levels: 1..2,
|
||||
layers: 2..5,
|
||||
levels: 1 .. 2,
|
||||
layers: 2 .. 5,
|
||||
}),
|
||||
// level 1 matches
|
||||
Some(TextureUsage::SAMPLED),
|
||||
@ -248,8 +260,8 @@ mod test {
|
||||
assert_eq!(
|
||||
ts.query(SubresourceRange {
|
||||
aspects: Aspects::DEPTH,
|
||||
levels: 1..2,
|
||||
layers: 2..5,
|
||||
levels: 1 .. 2,
|
||||
layers: 2 .. 5,
|
||||
}),
|
||||
// no depth found
|
||||
None,
|
||||
@ -257,8 +269,8 @@ mod test {
|
||||
assert_eq!(
|
||||
ts.query(SubresourceRange {
|
||||
aspects: Aspects::COLOR,
|
||||
levels: 0..2,
|
||||
layers: 2..5,
|
||||
levels: 0 .. 2,
|
||||
layers: 2 .. 5,
|
||||
}),
|
||||
// level 0 is empty, level 1 matches
|
||||
Some(TextureUsage::SAMPLED),
|
||||
@ -266,8 +278,8 @@ mod test {
|
||||
assert_eq!(
|
||||
ts.query(SubresourceRange {
|
||||
aspects: Aspects::COLOR,
|
||||
levels: 1..2,
|
||||
layers: 1..5,
|
||||
levels: 1 .. 2,
|
||||
layers: 1 .. 5,
|
||||
}),
|
||||
// level 1 matches with gaps
|
||||
Some(TextureUsage::SAMPLED),
|
||||
@ -275,8 +287,8 @@ mod test {
|
||||
assert_eq!(
|
||||
ts.query(SubresourceRange {
|
||||
aspects: Aspects::COLOR,
|
||||
levels: 1..2,
|
||||
layers: 4..6,
|
||||
levels: 1 .. 2,
|
||||
layers: 4 .. 6,
|
||||
}),
|
||||
// level 1 doesn't match
|
||||
None,
|
||||
|
@ -128,7 +128,7 @@ pub extern "C" fn wgpu_initialize() -> Infrastructure {
|
||||
pub extern "C" fn wgpu_terminate(client: *mut Client) {
|
||||
let client = unsafe { Box::from_raw(client) };
|
||||
let msg = GlobalMessage::Terminate;
|
||||
let _ = client.channel.send(msg);
|
||||
let _ = client.channel.send(msg);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -142,10 +142,7 @@ pub extern "C" fn wgpu_client_request_adapter(
|
||||
#[cfg(any(target_os = "ios", target_os = "macos"))]
|
||||
identities.metal.adapters.alloc(),
|
||||
];
|
||||
let msg = GlobalMessage::RequestAdapter(
|
||||
desc.clone(),
|
||||
ids,
|
||||
);
|
||||
let msg = GlobalMessage::RequestAdapter(desc.clone(), ids);
|
||||
client.channel.send(msg).unwrap();
|
||||
unimplemented!()
|
||||
}
|
||||
@ -156,15 +153,13 @@ pub extern "C" fn wgpu_client_adapter_create_device(
|
||||
adapter_id: wgn::AdapterId,
|
||||
desc: &wgn::DeviceDescriptor,
|
||||
) -> wgn::DeviceId {
|
||||
let device_id = client.identities
|
||||
let device_id = client
|
||||
.identities
|
||||
.lock()
|
||||
.select(adapter_id.backend())
|
||||
.devices.alloc();
|
||||
let msg = GlobalMessage::AdapterRequestDevice(
|
||||
adapter_id,
|
||||
desc.clone(),
|
||||
device_id,
|
||||
);
|
||||
.devices
|
||||
.alloc();
|
||||
let msg = GlobalMessage::AdapterRequestDevice(adapter_id, desc.clone(), device_id);
|
||||
client.channel.send(msg).unwrap();
|
||||
device_id
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{GlobalMessage};
|
||||
use crate::GlobalMessage;
|
||||
|
||||
use ipc_channel::ipc::IpcReceiver;
|
||||
use wgn;
|
||||
|
Loading…
Reference in New Issue
Block a user