mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-25 08:13:27 +00:00
Epoch tracking of indices
This commit is contained in:
parent
ea18c8fa85
commit
e16ceafb81
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1400,6 +1400,7 @@ dependencies = [
|
||||
name = "wgpu-native"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx-backend-dx11 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx-backend-dx12 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1411,6 +1412,7 @@ dependencies = [
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winit 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
use log::info;
|
||||
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn cast_slice<T>(data: &[T]) -> &[u8] {
|
||||
use std::mem::size_of;
|
||||
use std::slice::from_raw_parts;
|
||||
|
@ -1 +1,2 @@
|
||||
newline_style = "Native"
|
||||
spaces_around_ranges = true
|
||||
|
@ -153,7 +153,9 @@ typedef enum {
|
||||
WGPUVertexFormat_IntR8G8B8A8 = 4,
|
||||
} WGPUVertexFormat;
|
||||
|
||||
typedef uint32_t WGPUId;
|
||||
typedef struct WGPUBufferMapAsyncStatus WGPUBufferMapAsyncStatus;
|
||||
|
||||
typedef struct WGPUId WGPUId;
|
||||
|
||||
typedef WGPUId WGPUDeviceId;
|
||||
|
||||
@ -169,6 +171,10 @@ typedef struct {
|
||||
|
||||
typedef WGPUId WGPUBufferId;
|
||||
|
||||
typedef void (*WGPUBufferMapReadCallback)(WGPUBufferMapAsyncStatus status, const uint8_t *data, uint8_t *userdata);
|
||||
|
||||
typedef void (*WGPUBufferMapWriteCallback)(WGPUBufferMapAsyncStatus status, uint8_t *data, uint8_t *userdata);
|
||||
|
||||
typedef WGPUId WGPUCommandBufferId;
|
||||
|
||||
typedef struct {
|
||||
@ -553,11 +559,25 @@ WGPUDeviceId wgpu_adapter_create_device(WGPUAdapterId adapter_id, const WGPUDevi
|
||||
|
||||
void wgpu_buffer_destroy(WGPUBufferId buffer_id);
|
||||
|
||||
void wgpu_buffer_map_read_async(WGPUBufferId buffer_id,
|
||||
uint32_t start,
|
||||
uint32_t size,
|
||||
WGPUBufferMapReadCallback callback,
|
||||
uint8_t *userdata);
|
||||
|
||||
void wgpu_buffer_map_write_async(WGPUBufferId buffer_id,
|
||||
uint32_t start,
|
||||
uint32_t size,
|
||||
WGPUBufferMapWriteCallback callback,
|
||||
uint8_t *userdata);
|
||||
|
||||
void wgpu_buffer_set_sub_data(WGPUBufferId buffer_id,
|
||||
uint32_t start,
|
||||
uint32_t count,
|
||||
const uint8_t *data);
|
||||
|
||||
void wgpu_buffer_unmap(WGPUBufferId buffer_id);
|
||||
|
||||
void wgpu_command_buffer_copy_buffer_to_buffer(WGPUCommandBufferId command_buffer_id,
|
||||
WGPUBufferId src,
|
||||
uint32_t src_offset,
|
||||
|
@ -22,6 +22,7 @@ remote = ["serde"]
|
||||
metal-auto-capture = ["gfx-backend-metal/auto-capture"]
|
||||
|
||||
[dependencies]
|
||||
arrayvec = "0.4"
|
||||
bitflags = "1.0"
|
||||
lazy_static = "1.1.0"
|
||||
log = "0.4"
|
||||
@ -34,4 +35,5 @@ gfx-backend-dx12 = { version = "0.1.0", optional = true }
|
||||
gfx-backend-metal = { version = "0.1.0", optional = true }
|
||||
#rendy-memory = { git = "https://github.com/rustgd/rendy", rev = "ce7dd7f", features = ["gfx-hal"] }
|
||||
serde = { version = "1.0", features = ["serde_derive"], optional = true }
|
||||
vec_map = "0.8"
|
||||
winit = { version = "0.18", optional = true }
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::track::TrackerSet;
|
||||
use crate::{
|
||||
LifeGuard, WeaklyStored,
|
||||
LifeGuard,
|
||||
BindGroupLayoutId, BufferId, SamplerId, TextureViewId,
|
||||
};
|
||||
|
||||
@ -50,7 +50,7 @@ pub struct PipelineLayoutDescriptor {
|
||||
|
||||
pub struct PipelineLayout<B: hal::Backend> {
|
||||
pub(crate) raw: B::PipelineLayout,
|
||||
pub(crate) bind_group_layout_ids: Vec<WeaklyStored<BindGroupLayoutId>>,
|
||||
pub(crate) bind_group_layout_ids: Vec<BindGroupLayoutId>,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@ -82,7 +82,7 @@ pub struct BindGroupDescriptor {
|
||||
|
||||
pub struct BindGroup<B: hal::Backend> {
|
||||
pub(crate) raw: B::DescriptorSet,
|
||||
pub(crate) layout_id: WeaklyStored<BindGroupLayoutId>,
|
||||
pub(crate) layout_id: BindGroupLayoutId,
|
||||
pub(crate) life_guard: LifeGuard,
|
||||
pub(crate) used: TrackerSet,
|
||||
}
|
||||
|
@ -1,17 +1,17 @@
|
||||
use crate::{
|
||||
BindGroupHandle, Stored, WeaklyStored,
|
||||
BindGroupHandle, Stored,
|
||||
BindGroupId, BindGroupLayoutId, PipelineLayoutId,
|
||||
};
|
||||
|
||||
|
||||
pub struct BindGroupPair {
|
||||
layout_id: WeaklyStored<BindGroupLayoutId>,
|
||||
layout_id: BindGroupLayoutId,
|
||||
group_id: Stored<BindGroupId>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct BindGroupEntry {
|
||||
expected_layout_id: Option<WeaklyStored<BindGroupLayoutId>>,
|
||||
expected_layout_id: Option<BindGroupLayoutId>,
|
||||
provided: Option<BindGroupPair>,
|
||||
}
|
||||
|
||||
@ -38,12 +38,12 @@ impl BindGroupEntry {
|
||||
pub fn expect_layout(
|
||||
&mut self, bind_group_layout_id: BindGroupLayoutId,
|
||||
) -> Option<BindGroupId> {
|
||||
let some = Some(WeaklyStored(bind_group_layout_id));
|
||||
let some = Some(bind_group_layout_id);
|
||||
if self.expected_layout_id != some {
|
||||
self.expected_layout_id = some;
|
||||
match self.provided {
|
||||
Some(BindGroupPair { ref layout_id, ref group_id })
|
||||
if layout_id.0 == bind_group_layout_id => Some(group_id.value),
|
||||
Some(BindGroupPair { layout_id, ref group_id })
|
||||
if layout_id == bind_group_layout_id => Some(group_id.value),
|
||||
Some(_) | None => None,
|
||||
}
|
||||
} else {
|
||||
@ -54,7 +54,7 @@ impl BindGroupEntry {
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Binder {
|
||||
pub(crate) pipeline_layout_id: Option<WeaklyStored<PipelineLayoutId>>, //TODO: strongly `Stored`
|
||||
pub(crate) pipeline_layout_id: Option<PipelineLayoutId>, //TODO: strongly `Stored`
|
||||
pub(crate) entries: Vec<BindGroupEntry>,
|
||||
}
|
||||
|
||||
@ -70,7 +70,7 @@ impl Binder {
|
||||
) -> Option<PipelineLayoutId> {
|
||||
self.ensure_length(index + 1);
|
||||
if self.entries[index].provide(bind_group_id, bind_group) {
|
||||
self.pipeline_layout_id.as_ref().map(|&WeaklyStored(id)| id)
|
||||
self.pipeline_layout_id.as_ref().cloned()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -112,18 +112,18 @@ pub extern "C" fn wgpu_compute_pass_set_pipeline(
|
||||
}
|
||||
|
||||
let pipeline_layout_guard = HUB.pipeline_layouts.read();
|
||||
let pipeline_layout = pipeline_layout_guard.get(pipeline.layout_id.0);
|
||||
let pipeline_layout = pipeline_layout_guard.get(pipeline.layout_id);
|
||||
let bing_group_guard = HUB.bind_groups.read();
|
||||
|
||||
pass.binder.pipeline_layout_id = Some(pipeline.layout_id.clone());
|
||||
pass.binder.ensure_length(pipeline_layout.bind_group_layout_ids.len());
|
||||
|
||||
for (index, (entry, bgl_id)) in pass.binder.entries
|
||||
for (index, (entry, &bgl_id)) in pass.binder.entries
|
||||
.iter_mut()
|
||||
.zip(&pipeline_layout.bind_group_layout_ids)
|
||||
.enumerate()
|
||||
{
|
||||
if let Some(bg_id) = entry.expect_layout(bgl_id.0) {
|
||||
if let Some(bg_id) = entry.expect_layout(bgl_id) {
|
||||
let bind_group = bing_group_guard.get(bg_id);
|
||||
unsafe {
|
||||
pass.raw.bind_compute_descriptor_sets(
|
||||
|
@ -22,7 +22,7 @@ use crate::{
|
||||
BufferId, CommandBufferId, CommandEncoderId, DeviceId,
|
||||
TextureId, TextureViewId,
|
||||
BufferUsageFlags, TextureUsageFlags, Color,
|
||||
LifeGuard, Stored, WeaklyStored,
|
||||
LifeGuard, Stored,
|
||||
CommandBufferHandle,
|
||||
};
|
||||
#[cfg(feature = "local")]
|
||||
@ -294,9 +294,9 @@ pub fn command_encoder_begin_render_pass(
|
||||
let fb_key = FramebufferKey {
|
||||
attachments: color_attachments
|
||||
.iter()
|
||||
.map(|at| WeaklyStored(at.attachment))
|
||||
.map(|at| at.attachment)
|
||||
.chain(
|
||||
depth_stencil_attachment.map(|at| WeaklyStored(at.attachment)),
|
||||
depth_stencil_attachment.map(|at| at.attachment),
|
||||
)
|
||||
.collect(),
|
||||
};
|
||||
@ -308,7 +308,7 @@ pub fn command_encoder_begin_render_pass(
|
||||
.key()
|
||||
.attachments
|
||||
.iter()
|
||||
.map(|&WeaklyStored(id)| &view_guard.get(id).raw);
|
||||
.map(|&id| &view_guard.get(id).raw);
|
||||
|
||||
unsafe {
|
||||
device
|
||||
@ -374,7 +374,7 @@ pub extern "C" fn wgpu_command_encoder_begin_render_pass(
|
||||
desc: RenderPassDescriptor,
|
||||
) -> RenderPassId {
|
||||
let pass = command_encoder_begin_render_pass(command_encoder_id, desc);
|
||||
HUB.render_passes.register(pass)
|
||||
HUB.render_passes.register_local(pass)
|
||||
}
|
||||
|
||||
pub fn command_encoder_begin_compute_pass(
|
||||
@ -398,5 +398,5 @@ pub extern "C" fn wgpu_command_encoder_begin_compute_pass(
|
||||
command_encoder_id: CommandEncoderId,
|
||||
) -> ComputePassId {
|
||||
let pass = command_encoder_begin_compute_pass(command_encoder_id);
|
||||
HUB.compute_passes.register(pass)
|
||||
HUB.compute_passes.register_local(pass)
|
||||
}
|
||||
|
@ -224,18 +224,18 @@ pub extern "C" fn wgpu_render_pass_set_pipeline(
|
||||
}
|
||||
|
||||
let pipeline_layout_guard = HUB.pipeline_layouts.read();
|
||||
let pipeline_layout = pipeline_layout_guard.get(pipeline.layout_id.0);
|
||||
let pipeline_layout = pipeline_layout_guard.get(pipeline.layout_id);
|
||||
let bing_group_guard = HUB.bind_groups.read();
|
||||
|
||||
pass.binder.pipeline_layout_id = Some(pipeline.layout_id.clone());
|
||||
pass.binder.ensure_length(pipeline_layout.bind_group_layout_ids.len());
|
||||
|
||||
for (index, (entry, bgl_id)) in pass.binder.entries
|
||||
for (index, (entry, &bgl_id)) in pass.binder.entries
|
||||
.iter_mut()
|
||||
.zip(&pipeline_layout.bind_group_layout_ids)
|
||||
.enumerate()
|
||||
{
|
||||
if let Some(bg_id) = entry.expect_layout(bgl_id.0) {
|
||||
if let Some(bg_id) = entry.expect_layout(bgl_id) {
|
||||
let bind_group = bing_group_guard.get(bg_id);
|
||||
unsafe {
|
||||
pass.raw.bind_graphics_descriptor_sets(
|
||||
|
@ -2,7 +2,7 @@ use crate::{binding_model, command, conv, pipeline, resource, swap_chain};
|
||||
use crate::hub::HUB;
|
||||
use crate::track::{TrackerSet, TrackPermit};
|
||||
use crate::{
|
||||
LifeGuard, RefCount, Stored, SubmissionIndex, WeaklyStored,
|
||||
LifeGuard, RefCount, Stored, SubmissionIndex,
|
||||
BufferMapAsyncStatus, BufferMapOperation,
|
||||
};
|
||||
use crate::{
|
||||
@ -15,6 +15,7 @@ use crate::{
|
||||
ShaderModuleId, CommandEncoderId, RenderPipelineId, ComputePipelineId,
|
||||
};
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use back;
|
||||
use hal::backend::FastHashMap;
|
||||
use hal::command::RawCommandBuffer;
|
||||
@ -34,6 +35,8 @@ use std::collections::hash_map::Entry;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
|
||||
type AttachmentVec<T> = ArrayVec<[T; 5]>;
|
||||
|
||||
pub fn all_buffer_stages() -> hal::pso::PipelineStage {
|
||||
use hal::pso::PipelineStage as Ps;
|
||||
Ps::DRAW_INDIRECT |
|
||||
@ -57,13 +60,13 @@ pub fn all_image_stages() -> hal::pso::PipelineStage {
|
||||
|
||||
#[derive(Hash, PartialEq)]
|
||||
pub(crate) struct RenderPassKey {
|
||||
pub attachments: Vec<hal::pass::Attachment>,
|
||||
pub attachments: AttachmentVec<hal::pass::Attachment>,
|
||||
}
|
||||
impl Eq for RenderPassKey {}
|
||||
|
||||
#[derive(Hash, PartialEq)]
|
||||
pub(crate) struct FramebufferKey {
|
||||
pub attachments: Vec<WeaklyStored<TextureViewId>>,
|
||||
pub attachments: AttachmentVec<TextureViewId>,
|
||||
}
|
||||
impl Eq for FramebufferKey {}
|
||||
|
||||
@ -222,7 +225,7 @@ impl DestroyedResources<back::Backend> {
|
||||
let mut buffer_guard = HUB.buffers.write();
|
||||
|
||||
for buffer_id in self.ready_to_map.drain(..) {
|
||||
let mut buffer = buffer_guard.get_mut(buffer_id);
|
||||
let buffer = buffer_guard.get_mut(buffer_id);
|
||||
let mut operation = None;
|
||||
std::mem::swap(&mut operation, &mut buffer.pending_map_operation);
|
||||
match operation {
|
||||
@ -254,7 +257,7 @@ impl DestroyedResources<back::Backend> {
|
||||
|
||||
pub struct Device<B: hal::Backend> {
|
||||
pub(crate) raw: B::Device,
|
||||
adapter_id: WeaklyStored<AdapterId>,
|
||||
adapter_id: AdapterId,
|
||||
pub(crate) queue_group: hal::QueueGroup<B, hal::General>,
|
||||
//mem_allocator: Heaps<B::Memory>,
|
||||
pub(crate) com_allocator: command::CommandAllocator<B>,
|
||||
@ -270,7 +273,7 @@ pub struct Device<B: hal::Backend> {
|
||||
impl<B: hal::Backend> Device<B> {
|
||||
pub(crate) fn new(
|
||||
raw: B::Device,
|
||||
adapter_id: WeaklyStored<AdapterId>,
|
||||
adapter_id: AdapterId,
|
||||
queue_group: hal::QueueGroup<B, hal::General>,
|
||||
mem_props: hal::MemoryProperties,
|
||||
) -> Self {
|
||||
@ -431,7 +434,7 @@ pub extern "C" fn wgpu_device_create_buffer(
|
||||
) -> BufferId {
|
||||
let buffer = device_create_buffer(device_id, desc);
|
||||
let ref_count = buffer.life_guard.ref_count.clone();
|
||||
let id = HUB.buffers.register(buffer);
|
||||
let id = HUB.buffers.register_local(buffer);
|
||||
device_track_buffer(device_id, id, ref_count);
|
||||
id
|
||||
}
|
||||
@ -543,7 +546,7 @@ pub extern "C" fn wgpu_device_create_texture(
|
||||
) -> TextureId {
|
||||
let texture = device_create_texture(device_id, desc);
|
||||
let ref_count = texture.life_guard.ref_count.clone();
|
||||
let id = HUB.textures.register(texture);
|
||||
let id = HUB.textures.register_local(texture);
|
||||
device_track_texture(device_id, id, ref_count);
|
||||
id
|
||||
}
|
||||
@ -617,7 +620,7 @@ pub extern "C" fn wgpu_texture_create_view(
|
||||
let view = texture_create_view(texture_id, desc);
|
||||
let texture_id = view.texture_id.value;
|
||||
let ref_count = view.life_guard.ref_count.clone();
|
||||
let id = HUB.texture_views.register(view);
|
||||
let id = HUB.texture_views.register_local(view);
|
||||
device_track_view(texture_id, id, ref_count);
|
||||
id
|
||||
}
|
||||
@ -671,7 +674,7 @@ pub extern "C" fn wgpu_texture_create_default_view(texture_id: TextureId) -> Tex
|
||||
let view = texture_create_default_view(texture_id);
|
||||
let texture_id = view.texture_id.value;
|
||||
let ref_count = view.life_guard.ref_count.clone();
|
||||
let id = HUB.texture_views.register(view);
|
||||
let id = HUB.texture_views.register_local(view);
|
||||
device_track_view(texture_id, id, ref_count);
|
||||
id
|
||||
}
|
||||
@ -757,7 +760,7 @@ pub extern "C" fn wgpu_device_create_sampler(
|
||||
device_id: DeviceId, desc: &resource::SamplerDescriptor
|
||||
) -> SamplerId {
|
||||
let sampler = device_create_sampler(device_id, desc);
|
||||
HUB.samplers.register(sampler)
|
||||
HUB.samplers.register_local(sampler)
|
||||
}
|
||||
|
||||
|
||||
@ -799,7 +802,7 @@ pub extern "C" fn wgpu_device_create_bind_group_layout(
|
||||
desc: &binding_model::BindGroupLayoutDescriptor,
|
||||
) -> BindGroupLayoutId {
|
||||
let layout = device_create_bind_group_layout(device_id, desc);
|
||||
HUB.bind_group_layouts.register(layout)
|
||||
HUB.bind_group_layouts.register_local(layout)
|
||||
}
|
||||
|
||||
pub fn device_create_pipeline_layout(
|
||||
@ -829,7 +832,6 @@ pub fn device_create_pipeline_layout(
|
||||
bind_group_layout_ids: bind_group_layout_ids
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(WeaklyStored)
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
@ -841,7 +843,7 @@ pub extern "C" fn wgpu_device_create_pipeline_layout(
|
||||
desc: &binding_model::PipelineLayoutDescriptor,
|
||||
) -> PipelineLayoutId {
|
||||
let layout = device_create_pipeline_layout(device_id, desc);
|
||||
HUB.pipeline_layouts.register(layout)
|
||||
HUB.pipeline_layouts.register_local(layout)
|
||||
}
|
||||
|
||||
pub fn device_create_bind_group(
|
||||
@ -916,7 +918,7 @@ pub fn device_create_bind_group(
|
||||
|
||||
binding_model::BindGroup {
|
||||
raw: desc_set,
|
||||
layout_id: WeaklyStored(desc.layout),
|
||||
layout_id: desc.layout,
|
||||
life_guard: LifeGuard::new(),
|
||||
used,
|
||||
}
|
||||
@ -929,7 +931,7 @@ pub extern "C" fn wgpu_device_create_bind_group(
|
||||
desc: &binding_model::BindGroupDescriptor,
|
||||
) -> BindGroupId {
|
||||
let bind_group = device_create_bind_group(device_id, desc);
|
||||
HUB.bind_groups.register(bind_group)
|
||||
HUB.bind_groups.register_local(bind_group)
|
||||
}
|
||||
|
||||
|
||||
@ -957,7 +959,7 @@ pub extern "C" fn wgpu_device_create_shader_module(
|
||||
desc: &pipeline::ShaderModuleDescriptor,
|
||||
) -> ShaderModuleId {
|
||||
let module = device_create_shader_module(device_id, desc);
|
||||
HUB.shader_modules.register(module)
|
||||
HUB.shader_modules.register_local(module)
|
||||
}
|
||||
|
||||
pub fn device_create_command_encoder(
|
||||
@ -988,7 +990,7 @@ pub extern "C" fn wgpu_device_create_command_encoder(
|
||||
desc: &command::CommandEncoderDescriptor,
|
||||
) -> CommandEncoderId {
|
||||
let cmb = device_create_command_encoder(device_id, desc);
|
||||
HUB.command_buffers.register(cmb)
|
||||
HUB.command_buffers.register_local(cmb)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -1084,7 +1086,7 @@ pub extern "C" fn wgpu_queue_submit(
|
||||
.flat_map(|link| {
|
||||
//TODO: check the epoch
|
||||
surface_guard
|
||||
.get(link.swap_chain_id.0)
|
||||
.get(link.swap_chain_id)
|
||||
.swap_chain
|
||||
.as_ref()
|
||||
.map(|swap_chain| (
|
||||
@ -1339,7 +1341,7 @@ pub fn device_create_render_pipeline(
|
||||
|
||||
pipeline::RenderPipeline {
|
||||
raw: pipeline,
|
||||
layout_id: WeaklyStored(desc.layout),
|
||||
layout_id: desc.layout,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1350,7 +1352,7 @@ pub extern "C" fn wgpu_device_create_render_pipeline(
|
||||
desc: &pipeline::RenderPipelineDescriptor,
|
||||
) -> RenderPipelineId {
|
||||
let pipeline = device_create_render_pipeline(device_id, desc);
|
||||
HUB.render_pipelines.register(pipeline)
|
||||
HUB.render_pipelines.register_local(pipeline)
|
||||
}
|
||||
|
||||
pub fn device_create_compute_pipeline(
|
||||
@ -1397,7 +1399,7 @@ pub fn device_create_compute_pipeline(
|
||||
|
||||
pipeline::ComputePipeline {
|
||||
raw: pipeline,
|
||||
layout_id: WeaklyStored(desc.layout),
|
||||
layout_id: desc.layout,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1408,7 +1410,7 @@ pub extern "C" fn wgpu_device_create_compute_pipeline(
|
||||
desc: &pipeline::ComputePipelineDescriptor,
|
||||
) -> ComputePipelineId {
|
||||
let pipeline = device_create_compute_pipeline(device_id, desc);
|
||||
HUB.compute_pipelines.register(pipeline)
|
||||
HUB.compute_pipelines.register_local(pipeline)
|
||||
}
|
||||
|
||||
pub fn device_create_swap_chain(
|
||||
@ -1425,7 +1427,7 @@ pub fn device_create_swap_chain(
|
||||
|
||||
let (caps, formats, _present_modes, _composite_alphas) = {
|
||||
let adapter_guard = HUB.adapters.read();
|
||||
let adapter = adapter_guard.get(device.adapter_id.0);
|
||||
let adapter = adapter_guard.get(device.adapter_id);
|
||||
assert!(surface.raw.supports_queue_family(&adapter.queue_families[0]));
|
||||
surface.raw.compatibility(&adapter.physical_device)
|
||||
};
|
||||
@ -1556,13 +1558,13 @@ pub fn swap_chain_populate_textures(
|
||||
.unwrap()
|
||||
};
|
||||
texture.swap_chain_link = Some(swap_chain::SwapChainLink {
|
||||
swap_chain_id: WeaklyStored(swap_chain_id), //TODO: strongly
|
||||
swap_chain_id, //TODO: strongly
|
||||
epoch: Mutex::new(0),
|
||||
image_index: i as hal::SwapImageIndex,
|
||||
});
|
||||
let texture_id = Stored {
|
||||
ref_count: texture.life_guard.ref_count.clone(),
|
||||
value: HUB.textures.register(texture),
|
||||
value: HUB.textures.register_local(texture),
|
||||
};
|
||||
trackers.textures.query(
|
||||
texture_id.value,
|
||||
@ -1581,7 +1583,7 @@ pub fn swap_chain_populate_textures(
|
||||
};
|
||||
let view_id = Stored {
|
||||
ref_count: view.life_guard.ref_count.clone(),
|
||||
value: HUB.texture_views.register(view),
|
||||
value: HUB.texture_views.register_local(view),
|
||||
};
|
||||
trackers.views.query(
|
||||
view_id.value,
|
||||
|
@ -7,56 +7,89 @@ use crate::{
|
||||
SurfaceHandle,
|
||||
};
|
||||
|
||||
use hal::backend::FastHashMap;
|
||||
use lazy_static::lazy_static;
|
||||
use parking_lot::RwLock;
|
||||
#[cfg(feature = "local")]
|
||||
use parking_lot::Mutex;
|
||||
use vec_map::VecMap;
|
||||
|
||||
use std::ops;
|
||||
use std::sync::Arc;
|
||||
|
||||
//TODO: use Vec instead of HashMap
|
||||
//TODO: track epochs of indices
|
||||
|
||||
pub type Id = u32;
|
||||
pub(crate) type Index = u32;
|
||||
pub(crate) type Epoch = u32;
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq)]
|
||||
pub struct Id(Index, Epoch);
|
||||
|
||||
pub trait NewId {
|
||||
fn new(index: Index, epoch: Epoch) -> Self;
|
||||
fn index(&self) -> Index;
|
||||
fn epoch(&self) -> Epoch;
|
||||
}
|
||||
|
||||
impl NewId for Id {
|
||||
fn new(index: Index, epoch: Epoch) -> Self {
|
||||
Id(index, epoch)
|
||||
}
|
||||
|
||||
fn index(&self) -> Index {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn epoch(&self) -> Epoch {
|
||||
self.1
|
||||
}
|
||||
}
|
||||
|
||||
/// A simple structure to manage identities of objects.
|
||||
#[derive(Default)]
|
||||
pub struct IdentityManager {
|
||||
last_id: Id,
|
||||
free: Vec<Id>,
|
||||
free: Vec<Index>,
|
||||
epochs: Vec<Epoch>,
|
||||
}
|
||||
|
||||
impl IdentityManager {
|
||||
pub fn alloc(&mut self) -> Id {
|
||||
match self.free.pop() {
|
||||
Some(id) => id,
|
||||
Some(index) => {
|
||||
Id(index, self.epochs[index as usize])
|
||||
}
|
||||
None => {
|
||||
self.last_id += 1;
|
||||
assert_ne!(self.last_id, 0);
|
||||
self.last_id
|
||||
let id = Id(self.epochs.len() as Index, 1);
|
||||
self.epochs.push(id.1);
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn free(&mut self, id: Id) {
|
||||
debug_assert!(id <= self.last_id && !self.free.contains(&id));
|
||||
self.free.push(id);
|
||||
pub fn free(&mut self, Id(index, epoch): Id) {
|
||||
// avoid doing this check in release
|
||||
if cfg!(debug_assertions) {
|
||||
assert!(!self.free.contains(&index));
|
||||
}
|
||||
let pe = &mut self.epochs[index as usize];
|
||||
assert_eq!(*pe, epoch);
|
||||
*pe += 1;
|
||||
self.free.push(index);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Storage<T> {
|
||||
//TODO: consider concurrent hashmap?
|
||||
map: FastHashMap<Id, T>,
|
||||
map: VecMap<(T, Epoch)>,
|
||||
}
|
||||
|
||||
impl<T> Storage<T> {
|
||||
pub fn get(&self, id: Id) -> &T {
|
||||
self.map.get(&id).unwrap()
|
||||
let (ref value, epoch) = self.map[id.0 as usize];
|
||||
assert_eq!(epoch, id.1);
|
||||
value
|
||||
}
|
||||
pub fn get_mut(&mut self, id: Id) -> &mut T {
|
||||
self.map.get_mut(&id).unwrap()
|
||||
let (ref mut value, epoch) = self.map[id.0 as usize];
|
||||
assert_eq!(epoch, id.1);
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,7 +105,7 @@ impl<T> Default for Registry<T> {
|
||||
#[cfg(feature = "local")]
|
||||
identity: Mutex::new(IdentityManager::default()),
|
||||
data: RwLock::new(Storage {
|
||||
map: FastHashMap::default(),
|
||||
map: VecMap::new(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
@ -92,26 +125,26 @@ impl<T> ops::DerefMut for Registry<T> {
|
||||
}
|
||||
|
||||
impl<T> Registry<T> {
|
||||
#[cfg(feature = "local")]
|
||||
pub fn register(&self, value: T) -> Id {
|
||||
let id = self.identity.lock().alloc();
|
||||
let old = self.data.write().map.insert(id, value);
|
||||
pub fn register(&self, id: Id, value: T) {
|
||||
let old = self.data.write().map.insert(id.0 as usize, (value, id.1));
|
||||
assert!(old.is_none());
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Registry<T> {
|
||||
#[cfg(feature = "local")]
|
||||
pub fn register_local(&self, value: T) -> Id {
|
||||
let id = self.identity.lock().alloc();
|
||||
self.register(id, value);
|
||||
id
|
||||
}
|
||||
|
||||
pub fn unregister(&self, id: Id) -> T {
|
||||
#[cfg(feature = "local")]
|
||||
self.identity.lock().free(id);
|
||||
self.data.write().map.remove(&id).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "remote")]
|
||||
impl<T> Registry<T> {
|
||||
pub fn register(&self, id: Id, value: T) {
|
||||
let old = self.data.write().map.insert(id, value);
|
||||
assert!(old.is_none());
|
||||
let (value, epoch) = self.data.write().map.remove(id.0 as usize).unwrap();
|
||||
assert_eq!(epoch, id.1);
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::hub::HUB;
|
||||
use crate::{
|
||||
WeaklyStored,
|
||||
AdapterHandle, DeviceHandle, SurfaceHandle,
|
||||
AdapterId, InstanceId,
|
||||
};
|
||||
@ -48,7 +47,7 @@ pub fn create_instance() -> ::back::Instance {
|
||||
#[cfg(feature = "local")]
|
||||
pub extern "C" fn wgpu_create_instance() -> InstanceId {
|
||||
let inst = create_instance();
|
||||
HUB.instances.register(inst)
|
||||
HUB.instances.register_local(inst)
|
||||
}
|
||||
|
||||
#[cfg(feature = "local")]
|
||||
@ -62,7 +61,7 @@ pub extern "C" fn wgpu_instance_create_surface_from_winit(
|
||||
.get(instance_id)
|
||||
.create_surface(window);
|
||||
let surface = SurfaceHandle::new(raw);
|
||||
HUB.surfaces.register(surface)
|
||||
HUB.surfaces.register_local(surface)
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
@ -90,7 +89,7 @@ pub extern "C" fn wgpu_instance_create_surface_from_xlib(
|
||||
window: u64,
|
||||
) -> SurfaceId {
|
||||
let surface = instance_create_surface_from_xlib(instance_id, display, window);
|
||||
HUB.surfaces.register(surface)
|
||||
HUB.surfaces.register_local(surface)
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
@ -116,7 +115,7 @@ pub extern "C" fn wgpu_instance_create_surface_from_macos_layer(
|
||||
layer: *mut std::ffi::c_void,
|
||||
) -> SurfaceId {
|
||||
let surface = instance_create_surface_from_macos_layer(instance_id, layer);
|
||||
HUB.surfaces.register(surface)
|
||||
HUB.surfaces.register_local(surface)
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
@ -152,7 +151,7 @@ pub extern "C" fn wgpu_instance_create_surface_from_windows_hwnd(
|
||||
hwnd: *mut std::ffi::c_void,
|
||||
) -> SurfaceId {
|
||||
let surface = instance_create_surface_from_windows_hwnd(instance_id, hinstance, hwnd);
|
||||
HUB.surfaces.register(surface)
|
||||
HUB.surfaces.register_local(surface)
|
||||
}
|
||||
|
||||
pub fn instance_get_adapter(
|
||||
@ -184,7 +183,7 @@ pub extern "C" fn wgpu_instance_get_adapter(
|
||||
desc: &AdapterDescriptor,
|
||||
) -> AdapterId {
|
||||
let adapter = instance_get_adapter(instance_id, desc);
|
||||
HUB.adapters.register(adapter)
|
||||
HUB.adapters.register_local(adapter)
|
||||
}
|
||||
|
||||
pub fn adapter_create_device(
|
||||
@ -195,7 +194,7 @@ pub fn adapter_create_device(
|
||||
let adapter = adapter_guard.get_mut(adapter_id);
|
||||
let (raw, queue_group) = adapter.open_with::<_, hal::General>(1, |_qf| true).unwrap();
|
||||
let mem_props = adapter.physical_device.memory_properties();
|
||||
DeviceHandle::new(raw, WeaklyStored(adapter_id), queue_group, mem_props)
|
||||
DeviceHandle::new(raw, adapter_id, queue_group, mem_props)
|
||||
}
|
||||
|
||||
#[cfg(feature = "local")]
|
||||
@ -205,5 +204,5 @@ pub extern "C" fn wgpu_adapter_create_device(
|
||||
desc: &DeviceDescriptor,
|
||||
) -> DeviceId {
|
||||
let device = adapter_create_device(adapter_id, desc);
|
||||
HUB.devices.register(device)
|
||||
HUB.devices.register_local(device)
|
||||
}
|
||||
|
@ -100,9 +100,6 @@ struct Stored<T> {
|
||||
ref_count: RefCount,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
struct WeaklyStored<T>(T);
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::resource;
|
||||
use crate::{
|
||||
ByteArray, PipelineLayoutId, ShaderModuleId, WeaklyStored,
|
||||
ByteArray, PipelineLayoutId, ShaderModuleId,
|
||||
};
|
||||
|
||||
use bitflags::bitflags;
|
||||
@ -181,7 +181,7 @@ pub struct ComputePipelineDescriptor {
|
||||
|
||||
pub struct ComputePipeline<B: hal::Backend> {
|
||||
pub(crate) raw: B::ComputePipeline,
|
||||
pub(crate) layout_id: WeaklyStored<PipelineLayoutId>,
|
||||
pub(crate) layout_id: PipelineLayoutId,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@ -235,5 +235,5 @@ pub struct RenderPipelineDescriptor {
|
||||
|
||||
pub struct RenderPipeline<B: hal::Backend> {
|
||||
pub(crate) raw: B::GraphicsPipeline,
|
||||
pub(crate) layout_id: WeaklyStored<PipelineLayoutId>,
|
||||
pub(crate) layout_id: PipelineLayoutId,
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
Extent3d, Stored, WeaklyStored,
|
||||
Extent3d, Stored,
|
||||
DeviceId, SwapChainId, TextureId, TextureViewId,
|
||||
};
|
||||
use crate::{conv, resource};
|
||||
@ -17,7 +17,7 @@ use std::{iter, mem};
|
||||
pub type SwapImageEpoch = u16;
|
||||
|
||||
pub(crate) struct SwapChainLink<E> {
|
||||
pub swap_chain_id: WeaklyStored<SwapChainId>, //TODO: strongly
|
||||
pub swap_chain_id: SwapChainId, //TODO: strongly
|
||||
pub epoch: E,
|
||||
pub image_index: hal::SwapImageIndex,
|
||||
}
|
||||
|
@ -1,19 +1,19 @@
|
||||
use crate::hub::{Id, Storage};
|
||||
use crate::hub::{NewId, Id, Index, Epoch, Storage};
|
||||
use crate::resource::{BufferUsageFlags, TextureUsageFlags};
|
||||
use crate::{
|
||||
RefCount, WeaklyStored,
|
||||
RefCount,
|
||||
BufferId, TextureId, TextureViewId,
|
||||
};
|
||||
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::hash::Hash;
|
||||
use std::mem;
|
||||
use std::ops::{BitOr, Range};
|
||||
|
||||
use bitflags::bitflags;
|
||||
use hal::backend::FastHashMap;
|
||||
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ops::{BitOr, Range};
|
||||
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[allow(unused)]
|
||||
@ -72,16 +72,19 @@ struct Track<U> {
|
||||
ref_count: RefCount,
|
||||
init: U,
|
||||
last: U,
|
||||
epoch: Epoch,
|
||||
}
|
||||
|
||||
//TODO: consider having `I` as an associated type of `U`?
|
||||
pub struct Tracker<I, U> {
|
||||
map: FastHashMap<WeaklyStored<I>, Track<U>>,
|
||||
map: FastHashMap<Index, Track<U>>,
|
||||
_phantom: PhantomData<I>,
|
||||
}
|
||||
pub type BufferTracker = Tracker<BufferId, BufferUsageFlags>;
|
||||
pub type TextureTracker = Tracker<TextureId, TextureUsageFlags>;
|
||||
pub struct DummyTracker<I> {
|
||||
map: FastHashMap<WeaklyStored<I>, RefCount>,
|
||||
map: FastHashMap<Index, (RefCount, Epoch)>,
|
||||
_phantom: PhantomData<I>,
|
||||
}
|
||||
pub type TextureViewTracker = DummyTracker<TextureViewId>;
|
||||
|
||||
@ -102,67 +105,88 @@ impl TrackerSet {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Clone + Hash + Eq> DummyTracker<I> {
|
||||
impl<I: NewId> DummyTracker<I> {
|
||||
pub fn new() -> Self {
|
||||
DummyTracker {
|
||||
map: FastHashMap::default(),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove an id from the tracked map.
|
||||
pub(crate) fn remove(&mut self, id: I) -> bool {
|
||||
self.map.remove(&WeaklyStored(id)).is_some()
|
||||
match self.map.remove(&id.index()) {
|
||||
Some((_, epoch)) => {
|
||||
assert_eq!(epoch, id.epoch());
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the last usage on a resource.
|
||||
pub(crate) fn query(&mut self, id: I, ref_count: &RefCount) -> bool {
|
||||
match self.map.entry(WeaklyStored(id)) {
|
||||
match self.map.entry(id.index()) {
|
||||
Entry::Vacant(e) => {
|
||||
e.insert(ref_count.clone());
|
||||
e.insert((ref_count.clone(), id.epoch()));
|
||||
true
|
||||
}
|
||||
Entry::Occupied(_) => false,
|
||||
Entry::Occupied(e) => {
|
||||
assert_eq!(e.get().1, id.epoch());
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Consume another tacker.
|
||||
pub fn consume(&mut self, other: &Self) {
|
||||
for (id, ref_count) in &other.map {
|
||||
self.query(id.0.clone(), ref_count);
|
||||
for (&index, &(ref ref_count, epoch)) in &other.map {
|
||||
self.query(I::new(index, epoch), ref_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Clone + Hash + Eq, U: Copy + GenericUsage + BitOr<Output = U> + PartialEq> Tracker<I, U> {
|
||||
impl<I: NewId, U: Copy + GenericUsage + BitOr<Output = U> + PartialEq> Tracker<I, U> {
|
||||
pub fn new() -> Self {
|
||||
Tracker {
|
||||
map: FastHashMap::default(),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove an id from the tracked map.
|
||||
pub(crate) fn remove(&mut self, id: I) -> bool {
|
||||
self.map.remove(&WeaklyStored(id)).is_some()
|
||||
match self.map.remove(&id.index()) {
|
||||
Some(track) => {
|
||||
assert_eq!(track.epoch, id.epoch());
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the last usage on a resource.
|
||||
pub(crate) fn query(&mut self, id: I, ref_count: &RefCount, default: U) -> Query<U> {
|
||||
match self.map.entry(WeaklyStored(id)) {
|
||||
match self.map.entry(id.index()) {
|
||||
Entry::Vacant(e) => {
|
||||
e.insert(Track {
|
||||
ref_count: ref_count.clone(),
|
||||
init: default,
|
||||
last: default,
|
||||
epoch: id.epoch(),
|
||||
});
|
||||
Query {
|
||||
usage: default,
|
||||
initialized: true,
|
||||
}
|
||||
}
|
||||
Entry::Occupied(e) => Query {
|
||||
usage: e.get().last,
|
||||
initialized: false,
|
||||
},
|
||||
Entry::Occupied(e) => {
|
||||
assert_eq!(e.get().epoch, id.epoch());
|
||||
Query {
|
||||
usage: e.get().last,
|
||||
initialized: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,16 +198,18 @@ impl<I: Clone + Hash + Eq, U: Copy + GenericUsage + BitOr<Output = U> + PartialE
|
||||
usage: U,
|
||||
permit: TrackPermit,
|
||||
) -> Result<Tracktion<U>, U> {
|
||||
match self.map.entry(WeaklyStored(id)) {
|
||||
match self.map.entry(id.index()) {
|
||||
Entry::Vacant(e) => {
|
||||
e.insert(Track {
|
||||
ref_count: ref_count.clone(),
|
||||
init: usage,
|
||||
last: usage,
|
||||
epoch: id.epoch(),
|
||||
});
|
||||
Ok(Tracktion::Init)
|
||||
}
|
||||
Entry::Occupied(mut e) => {
|
||||
assert_eq!(e.get().epoch, id.epoch());
|
||||
let old = e.get().last;
|
||||
if usage == old {
|
||||
Ok(Tracktion::Keep)
|
||||
@ -201,37 +227,43 @@ impl<I: Clone + Hash + Eq, U: Copy + GenericUsage + BitOr<Output = U> + PartialE
|
||||
}
|
||||
|
||||
/// Consume another tacker, adding it's transitions to `self`.
|
||||
/// Transitions the current usage to the new one.
|
||||
pub fn consume_by_replace<'a>(&'a mut self, other: &'a Self) -> impl 'a + Iterator<Item = (I, Range<U>)> {
|
||||
other.map.iter().flat_map(move |(id, new)| {
|
||||
match self.map.entry(WeaklyStored(id.0.clone())) {
|
||||
other.map.iter().flat_map(move |(&index, new)| {
|
||||
match self.map.entry(index) {
|
||||
Entry::Vacant(e) => {
|
||||
e.insert(new.clone());
|
||||
None
|
||||
}
|
||||
Entry::Occupied(mut e) => {
|
||||
assert_eq!(e.get().epoch, new.epoch);
|
||||
let old = mem::replace(&mut e.get_mut().last, new.last);
|
||||
if old == new.init {
|
||||
None
|
||||
} else {
|
||||
Some((id.0.clone(), old..new.last))
|
||||
Some((I::new(index, new.epoch), old .. new.last))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Consume another tacker, adding it's transitions to `self`.
|
||||
/// Extends the current usage without doing any transitions.
|
||||
pub fn consume_by_extend<'a>(&'a mut self, other: &'a Self) -> Result<(), (I, Range<U>)> {
|
||||
for (id, new) in other.map.iter() {
|
||||
match self.map.entry(WeaklyStored(id.0.clone())) {
|
||||
for (&index, new) in other.map.iter() {
|
||||
match self.map.entry(index) {
|
||||
Entry::Vacant(e) => {
|
||||
e.insert(new.clone());
|
||||
}
|
||||
Entry::Occupied(mut e) => {
|
||||
assert_eq!(e.get().epoch, new.epoch);
|
||||
let old = e.get().last;
|
||||
if old != new.last {
|
||||
let extended = old | new.last;
|
||||
if extended.is_exclusive() {
|
||||
return Err((id.0.clone(), old..new.last));
|
||||
let id = I::new(index, new.epoch);
|
||||
return Err((id, old .. new.last));
|
||||
}
|
||||
e.get_mut().last = extended;
|
||||
}
|
||||
@ -243,7 +275,7 @@ impl<I: Clone + Hash + Eq, U: Copy + GenericUsage + BitOr<Output = U> + PartialE
|
||||
|
||||
/// Return an iterator over used resources keys.
|
||||
pub fn used<'a>(&'a self) -> impl 'a + Iterator<Item = I> {
|
||||
self.map.keys().map(|&WeaklyStored(ref id)| id.clone())
|
||||
self.map.iter().map(|(&index, track)| I::new(index, track.epoch))
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user