489: All the missing Gecko fixes r=grovesNL a=kvark

Last auto-integration in #474 got borked, partially because of the original change being reverted in mozilla-central. This is the manual sync-up from m-c. Hopefully it doesn't break anything new we got here.

Fixes #457 
Fixes #463

Co-authored-by: Dzmitry Malyshau <kvarkus@gmail.com>
This commit is contained in:
bors[bot] 2020-02-10 13:48:33 +00:00 committed by GitHub
commit 557ed0674c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 592 additions and 130 deletions

View File

@ -255,14 +255,14 @@ typedef enum {
WGPUVertexFormat_Int4 = 48, WGPUVertexFormat_Int4 = 48,
} WGPUVertexFormat; } WGPUVertexFormat;
typedef uint64_t WGPUId_Device_Dummy;
typedef WGPUId_Device_Dummy WGPUDeviceId;
typedef uint64_t WGPUId_Adapter_Dummy; typedef uint64_t WGPUId_Adapter_Dummy;
typedef WGPUId_Adapter_Dummy WGPUAdapterId; typedef WGPUId_Adapter_Dummy WGPUAdapterId;
typedef uint64_t WGPUId_Device_Dummy;
typedef WGPUId_Device_Dummy WGPUDeviceId;
typedef struct { typedef struct {
bool anisotropic_filtering; bool anisotropic_filtering;
} WGPUExtensions; } WGPUExtensions;
@ -413,6 +413,8 @@ typedef WGPURawPass *WGPUComputePassId;
typedef const char *WGPURawString; typedef const char *WGPURawString;
typedef uint32_t WGPUDynamicOffset;
typedef uint64_t WGPUId_ComputePipeline_Dummy; typedef uint64_t WGPUId_ComputePipeline_Dummy;
typedef WGPUId_ComputePipeline_Dummy WGPUComputePipelineId; typedef WGPUId_ComputePipeline_Dummy WGPUComputePipelineId;
@ -706,6 +708,8 @@ typedef struct {
uint32_t array_layer_count; uint32_t array_layer_count;
} WGPUTextureViewDescriptor; } WGPUTextureViewDescriptor;
void wgpu_adapter_destroy(WGPUAdapterId adapter_id);
WGPUDeviceId wgpu_adapter_request_device(WGPUAdapterId adapter_id, WGPUDeviceId wgpu_adapter_request_device(WGPUAdapterId adapter_id,
const WGPUDeviceDescriptor *desc); const WGPUDeviceDescriptor *desc);
@ -729,6 +733,13 @@ void wgpu_buffer_unmap(WGPUBufferId buffer_id);
void wgpu_command_buffer_destroy(WGPUCommandBufferId command_buffer_id); void wgpu_command_buffer_destroy(WGPUCommandBufferId command_buffer_id);
/**
* # Safety
*
* This function is unsafe because improper use may lead to memory
* problems. For example, a double-free may occur if the function is called
* twice on the same raw pointer.
*/
WGPURawPass *wgpu_command_encoder_begin_compute_pass(WGPUCommandEncoderId encoder_id, WGPURawPass *wgpu_command_encoder_begin_compute_pass(WGPUCommandEncoderId encoder_id,
const WGPUComputePassDescriptor *_desc); const WGPUComputePassDescriptor *_desc);
@ -769,6 +780,8 @@ void wgpu_command_encoder_destroy(WGPUCommandEncoderId command_encoder_id);
WGPUCommandBufferId wgpu_command_encoder_finish(WGPUCommandEncoderId encoder_id, WGPUCommandBufferId wgpu_command_encoder_finish(WGPUCommandEncoderId encoder_id,
const WGPUCommandBufferDescriptor *desc); const WGPUCommandBufferDescriptor *desc);
void wgpu_compute_pass_destroy(WGPURawPass *pass);
void wgpu_compute_pass_dispatch(WGPURawPass *pass, void wgpu_compute_pass_dispatch(WGPURawPass *pass,
uint32_t groups_x, uint32_t groups_x,
uint32_t groups_y, uint32_t groups_y,
@ -778,15 +791,10 @@ void wgpu_compute_pass_dispatch_indirect(WGPURawPass *pass,
WGPUBufferId buffer_id, WGPUBufferId buffer_id,
WGPUBufferAddress offset); WGPUBufferAddress offset);
/**
* # Safety
*
* This function is unsafe because improper use may lead to memory
* problems. For example, a double-free may occur if the function is called
* twice on the same raw pointer.
*/
void wgpu_compute_pass_end_pass(WGPUComputePassId pass_id); void wgpu_compute_pass_end_pass(WGPUComputePassId pass_id);
const uint8_t *wgpu_compute_pass_finish(WGPURawPass *pass, uintptr_t *length);
void wgpu_compute_pass_insert_debug_marker(WGPURawPass *_pass, WGPURawString _label); void wgpu_compute_pass_insert_debug_marker(WGPURawPass *_pass, WGPURawString _label);
void wgpu_compute_pass_pop_debug_group(WGPURawPass *_pass); void wgpu_compute_pass_pop_debug_group(WGPURawPass *_pass);
@ -802,7 +810,7 @@ void wgpu_compute_pass_push_debug_group(WGPURawPass *_pass, WGPURawString _label
void wgpu_compute_pass_set_bind_group(WGPURawPass *pass, void wgpu_compute_pass_set_bind_group(WGPURawPass *pass,
uint32_t index, uint32_t index,
WGPUBindGroupId bind_group_id, WGPUBindGroupId bind_group_id,
const WGPUBufferAddress *offsets, const WGPUDynamicOffset *offsets,
uintptr_t offset_length); uintptr_t offset_length);
void wgpu_compute_pass_set_pipeline(WGPURawPass *pass, WGPUComputePipelineId pipeline_id); void wgpu_compute_pass_set_pipeline(WGPURawPass *pass, WGPUComputePipelineId pipeline_id);
@ -874,6 +882,8 @@ void wgpu_queue_submit(WGPUQueueId queue_id,
const WGPUCommandBufferId *command_buffers, const WGPUCommandBufferId *command_buffers,
uintptr_t command_buffers_length); uintptr_t command_buffers_length);
void wgpu_render_pass_destroy(WGPURawRenderPass *pass);
void wgpu_render_pass_draw(WGPURawRenderPass *pass, void wgpu_render_pass_draw(WGPURawRenderPass *pass,
uint32_t vertex_count, uint32_t vertex_count,
uint32_t instance_count, uint32_t instance_count,
@ -908,6 +918,8 @@ void wgpu_render_pass_execute_bundles(WGPURawRenderPass *_pass,
const WGPURenderBundleId *_bundles, const WGPURenderBundleId *_bundles,
uintptr_t _bundles_length); uintptr_t _bundles_length);
const uint8_t *wgpu_render_pass_finish(WGPURawRenderPass *pass, uintptr_t *length);
void wgpu_render_pass_insert_debug_marker(WGPURawRenderPass *_pass, WGPURawString _label); void wgpu_render_pass_insert_debug_marker(WGPURawRenderPass *_pass, WGPURawString _label);
void wgpu_render_pass_pop_debug_group(WGPURawRenderPass *_pass); void wgpu_render_pass_pop_debug_group(WGPURawRenderPass *_pass);
@ -923,7 +935,7 @@ void wgpu_render_pass_push_debug_group(WGPURawRenderPass *_pass, WGPURawString _
void wgpu_render_pass_set_bind_group(WGPURawRenderPass *pass, void wgpu_render_pass_set_bind_group(WGPURawRenderPass *pass,
uint32_t index, uint32_t index,
WGPUBindGroupId bind_group_id, WGPUBindGroupId bind_group_id,
const WGPUBufferAddress *offsets, const WGPUDynamicOffset *offsets,
uintptr_t offset_length); uintptr_t offset_length);
void wgpu_render_pass_set_blend_color(WGPURawRenderPass *pass, const WGPUColor *color); void wgpu_render_pass_set_blend_color(WGPURawRenderPass *pass, const WGPUColor *color);

View File

@ -49,4 +49,4 @@ gfx-backend-dx11 = { version = "0.4" }
gfx-backend-vulkan = { version = "0.4" } gfx-backend-vulkan = { version = "0.4" }
[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "dragonfly", target_os = "freebsd"))'.dependencies] [target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "dragonfly", target_os = "freebsd"))'.dependencies]
battery = "0.7" battery = { version = "0.7", optional = true }

View File

@ -6,7 +6,7 @@ use crate::{
binding_model::BindGroup, binding_model::BindGroup,
hub::GfxBackend, hub::GfxBackend,
id::{BindGroupId, BindGroupLayoutId, PipelineLayoutId}, id::{BindGroupId, BindGroupLayoutId, PipelineLayoutId},
BufferAddress, DynamicOffset,
Stored, Stored,
}; };
@ -26,7 +26,7 @@ pub struct BindGroupPair {
#[derive(Debug)] #[derive(Debug)]
pub enum LayoutChange<'a> { pub enum LayoutChange<'a> {
Unchanged, Unchanged,
Match(BindGroupId, &'a [BufferAddress]), Match(BindGroupId, &'a [DynamicOffset]),
Mismatch, Mismatch,
} }
@ -41,7 +41,7 @@ pub struct FollowUpIter<'a> {
iter: slice::Iter<'a, BindGroupEntry>, iter: slice::Iter<'a, BindGroupEntry>,
} }
impl<'a> Iterator for FollowUpIter<'a> { impl<'a> Iterator for FollowUpIter<'a> {
type Item = (BindGroupId, &'a [BufferAddress]); type Item = (BindGroupId, &'a [DynamicOffset]);
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
self.iter self.iter
.next() .next()
@ -58,7 +58,7 @@ impl<'a> Iterator for FollowUpIter<'a> {
pub struct BindGroupEntry { pub struct BindGroupEntry {
expected_layout_id: Option<BindGroupLayoutId>, expected_layout_id: Option<BindGroupLayoutId>,
provided: Option<BindGroupPair>, provided: Option<BindGroupPair>,
dynamic_offsets: Vec<BufferAddress>, dynamic_offsets: Vec<DynamicOffset>,
} }
impl BindGroupEntry { impl BindGroupEntry {
@ -66,7 +66,7 @@ impl BindGroupEntry {
&mut self, &mut self,
bind_group_id: BindGroupId, bind_group_id: BindGroupId,
bind_group: &BindGroup<B>, bind_group: &BindGroup<B>,
offsets: &[BufferAddress], offsets: &[DynamicOffset],
) -> Provision { ) -> Provision {
debug_assert_eq!(B::VARIANT, bind_group_id.backend()); debug_assert_eq!(B::VARIANT, bind_group_id.backend());
@ -167,7 +167,7 @@ impl Binder {
index: usize, index: usize,
bind_group_id: BindGroupId, bind_group_id: BindGroupId,
bind_group: &BindGroup<B>, bind_group: &BindGroup<B>,
offsets: &[BufferAddress], offsets: &[DynamicOffset],
) -> Option<(PipelineLayoutId, FollowUpIter<'a>)> { ) -> Option<(PipelineLayoutId, FollowUpIter<'a>)> {
log::trace!("\tBinding [{}] = group {:?}", index, bind_group_id); log::trace!("\tBinding [{}] = group {:?}", index, bind_group_id);
debug_assert_eq!(B::VARIANT, bind_group_id.backend()); debug_assert_eq!(B::VARIANT, bind_group_id.backend());

View File

@ -13,6 +13,7 @@ use crate::{
id, id,
resource::BufferUsage, resource::BufferUsage,
BufferAddress, BufferAddress,
DynamicOffset,
}; };
use hal::command::CommandBuffer as _; use hal::command::CommandBuffer as _;
@ -27,7 +28,7 @@ enum ComputeCommand {
index: u8, index: u8,
num_dynamic_offsets: u8, num_dynamic_offsets: u8,
bind_group_id: id::BindGroupId, bind_group_id: id::BindGroupId,
phantom_offsets: PhantomSlice<BufferAddress>, phantom_offsets: PhantomSlice<DynamicOffset>,
}, },
SetPipeline(id::ComputePipelineId), SetPipeline(id::ComputePipelineId),
Dispatch([u32; 3]), Dispatch([u32; 3]),
@ -43,8 +44,9 @@ impl super::RawPass {
Self::from_vec(Vec::<ComputeCommand>::with_capacity(1), parent) Self::from_vec(Vec::<ComputeCommand>::with_capacity(1), parent)
} }
pub unsafe fn finish_compute(self) -> (Vec<u8>, id::CommandEncoderId) { pub unsafe fn finish_compute(mut self) -> (Vec<u8>, id::CommandEncoderId) {
self.finish_with(ComputeCommand::End) self.finish(ComputeCommand::End);
self.into_vec()
} }
} }
@ -87,14 +89,14 @@ impl<F> Global<F> {
match command { match command {
ComputeCommand::SetBindGroup { index, num_dynamic_offsets, bind_group_id, phantom_offsets } => { ComputeCommand::SetBindGroup { index, num_dynamic_offsets, bind_group_id, phantom_offsets } => {
let (new_peeker, offsets) = unsafe { let (new_peeker, offsets) = unsafe {
phantom_offsets.decode(peeker, num_dynamic_offsets as usize, raw_data_end) phantom_offsets.decode_unaligned(peeker, num_dynamic_offsets as usize, raw_data_end)
}; };
peeker = new_peeker; peeker = new_peeker;
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
for off in offsets { for off in offsets {
assert_eq!( assert_eq!(
*off % BIND_BUFFER_ALIGNMENT, *off as BufferAddress % BIND_BUFFER_ALIGNMENT,
0, 0,
"Misaligned dynamic buffer offset: {} does not align with {}", "Misaligned dynamic buffer offset: {} does not align with {}",
off, off,
@ -221,6 +223,7 @@ pub mod compute_ffi {
use crate::{ use crate::{
id, id,
BufferAddress, BufferAddress,
DynamicOffset,
RawString, RawString,
}; };
use std::{convert::TryInto, slice}; use std::{convert::TryInto, slice};
@ -236,7 +239,7 @@ pub mod compute_ffi {
pass: &mut RawPass, pass: &mut RawPass,
index: u32, index: u32,
bind_group_id: id::BindGroupId, bind_group_id: id::BindGroupId,
offsets: *const BufferAddress, offsets: *const DynamicOffset,
offset_length: usize, offset_length: usize,
) { ) {
pass.encode(&ComputeCommand::SetBindGroup { pass.encode(&ComputeCommand::SetBindGroup {
@ -302,4 +305,14 @@ pub mod compute_ffi {
) { ) {
//TODO //TODO
} }
#[no_mangle]
pub unsafe extern "C" fn wgpu_compute_pass_finish(
pass: &mut RawPass,
length: &mut usize,
) -> *const u8 {
pass.finish(ComputeCommand::End);
*length = pass.size();
pass.base
}
} }

View File

@ -31,6 +31,7 @@ use crate::{
use std::{ use std::{
marker::PhantomData, marker::PhantomData,
mem, mem,
ptr,
slice, slice,
thread::ThreadId, thread::ThreadId,
}; };
@ -44,7 +45,7 @@ impl<T> PhantomSlice<T> {
PhantomSlice(PhantomData) PhantomSlice(PhantomData)
} }
unsafe fn decode<'a>( unsafe fn decode_unaligned<'a>(
self, pointer: *const u8, count: usize, bound: *const u8 self, pointer: *const u8, count: usize, bound: *const u8
) -> (*const u8, &'a [T]) { ) -> (*const u8, &'a [T]) {
let align_offset = pointer.align_offset(mem::align_of::<T>()); let align_offset = pointer.align_offset(mem::align_of::<T>());
@ -84,18 +85,29 @@ impl RawPass {
/// ///
/// The last command is provided, yet the encoder /// The last command is provided, yet the encoder
/// is guaranteed to have exactly `C::max_size()` space for it. /// is guaranteed to have exactly `C::max_size()` space for it.
unsafe fn finish_with<C: peek_poke::Poke>( unsafe fn finish<C: peek_poke::Poke>(
mut self, command: C &mut self, command: C
) -> (Vec<u8>, id::CommandEncoderId) { ) {
self.ensure_extra_size(C::max_size()); self.ensure_extra_size(C::max_size());
command.poke_into(self.data); let extended_end = self.data.add(C::max_size());
let size = self.data as usize + C::max_size() - self.base as usize; let end = command.poke_into(self.data);
ptr::write_bytes(end, 0, extended_end as usize - end as usize);
self.data = extended_end;
}
fn size(&self) -> usize {
self.data as usize - self.base as usize
}
pub unsafe fn into_vec(self) -> (Vec<u8>, id::CommandEncoderId) {
let size = self.size();
assert!(size <= self.capacity); assert!(size <= self.capacity);
(Vec::from_raw_parts(self.base, size, self.capacity), self.parent) let vec = Vec::from_raw_parts(self.base, size, self.capacity);
(vec, self.parent)
} }
unsafe fn ensure_extra_size(&mut self, extra_size: usize) { unsafe fn ensure_extra_size(&mut self, extra_size: usize) {
let size = self.data as usize - self.base as usize; let size = self.size();
if size + extra_size > self.capacity { if size + extra_size > self.capacity {
let mut vec = Vec::from_raw_parts(self.base, size, self.capacity); let mut vec = Vec::from_raw_parts(self.base, size, self.capacity);
vec.reserve(extra_size); vec.reserve(extra_size);
@ -196,15 +208,6 @@ pub struct CommandBufferDescriptor {
pub todo: u32, pub todo: u32,
} }
#[no_mangle]
pub extern "C" fn wgpu_command_encoder_begin_compute_pass(
encoder_id: id::CommandEncoderId,
_desc: Option<&ComputePassDescriptor>,
) -> *mut RawPass {
let pass = RawPass::new_compute(encoder_id);
Box::into_raw(Box::new(pass))
}
type RawRenderPassColorAttachmentDescriptor = type RawRenderPassColorAttachmentDescriptor =
RenderPassColorAttachmentDescriptorBase<id::TextureViewId, id::TextureViewId>; RenderPassColorAttachmentDescriptorBase<id::TextureViewId, id::TextureViewId>;

View File

@ -24,6 +24,7 @@ use crate::{
track::TrackerSet, track::TrackerSet,
BufferAddress, BufferAddress,
Color, Color,
DynamicOffset,
Stored, Stored,
}; };
@ -106,7 +107,7 @@ enum RenderCommand {
index: u8, index: u8,
num_dynamic_offsets: u8, num_dynamic_offsets: u8,
bind_group_id: id::BindGroupId, bind_group_id: id::BindGroupId,
phantom_offsets: PhantomSlice<BufferAddress>, phantom_offsets: PhantomSlice<DynamicOffset>,
}, },
SetPipeline(id::RenderPipelineId), SetPipeline(id::RenderPipelineId),
SetIndexBuffer { SetIndexBuffer {
@ -159,8 +160,9 @@ impl super::RawPass {
} }
impl super::RawRenderPass { impl super::RawRenderPass {
pub unsafe fn finish_render(self) -> (Vec<u8>, id::CommandEncoderId, RawRenderTargets) { pub unsafe fn finish_render(mut self) -> (Vec<u8>, id::CommandEncoderId, RawRenderTargets) {
let (vec, parent_id) = self.raw.finish_with(RenderCommand::End); self.raw.finish(RenderCommand::End);
let (vec, parent_id) = self.raw.into_vec();
(vec, parent_id, self.targets) (vec, parent_id, self.targets)
} }
} }
@ -784,14 +786,14 @@ impl<F> Global<F> {
match command { match command {
RenderCommand::SetBindGroup { index, num_dynamic_offsets, bind_group_id, phantom_offsets } => { RenderCommand::SetBindGroup { index, num_dynamic_offsets, bind_group_id, phantom_offsets } => {
let (new_peeker, offsets) = unsafe { let (new_peeker, offsets) = unsafe {
phantom_offsets.decode(peeker, num_dynamic_offsets as usize, raw_data_end) phantom_offsets.decode_unaligned(peeker, num_dynamic_offsets as usize, raw_data_end)
}; };
peeker = new_peeker; peeker = new_peeker;
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
for off in offsets { for off in offsets {
assert_eq!( assert_eq!(
*off % BIND_BUFFER_ALIGNMENT, *off as BufferAddress % BIND_BUFFER_ALIGNMENT,
0, 0,
"Misaligned dynamic buffer offset: {} does not align with {}", "Misaligned dynamic buffer offset: {} does not align with {}",
off, off,
@ -943,10 +945,10 @@ impl<F> Global<F> {
} }
RenderCommand::SetVertexBuffers { start_index, count, phantom_buffer_ids, phantom_offsets } => { RenderCommand::SetVertexBuffers { start_index, count, phantom_buffer_ids, phantom_offsets } => {
let (new_peeker, buffer_ids) = unsafe { let (new_peeker, buffer_ids) = unsafe {
phantom_buffer_ids.decode(peeker, count as usize, raw_data_end) phantom_buffer_ids.decode_unaligned(peeker, count as usize, raw_data_end)
}; };
let (new_peeker, offsets) = unsafe { let (new_peeker, offsets) = unsafe {
phantom_offsets.decode(new_peeker, count as usize, raw_data_end) phantom_offsets.decode_unaligned(new_peeker, count as usize, raw_data_end)
}; };
peeker = new_peeker; peeker = new_peeker;
@ -1117,6 +1119,7 @@ pub mod render_ffi {
id, id,
BufferAddress, BufferAddress,
Color, Color,
DynamicOffset,
RawString, RawString,
}; };
use std::{convert::TryInto, slice}; use std::{convert::TryInto, slice};
@ -1132,7 +1135,7 @@ pub mod render_ffi {
pass: &mut RawRenderPass, pass: &mut RawRenderPass,
index: u32, index: u32,
bind_group_id: id::BindGroupId, bind_group_id: id::BindGroupId,
offsets: *const BufferAddress, offsets: *const DynamicOffset,
offset_length: usize, offset_length: usize,
) { ) {
pass.raw.encode(&RenderCommand::SetBindGroup { pass.raw.encode(&RenderCommand::SetBindGroup {
@ -1327,4 +1330,20 @@ pub mod render_ffi {
) { ) {
//TODO //TODO
} }
#[no_mangle]
pub unsafe extern "C" fn wgpu_render_pass_finish(
pass: &mut RawRenderPass,
length: &mut usize,
) -> *const u8 {
//TODO: put target information into the byte stream
pass.raw.finish(RenderCommand::End);
*length = pass.raw.size();
pass.raw.base
}
#[no_mangle]
pub unsafe extern "C" fn wgpu_render_pass_destroy(pass: *mut RawRenderPass) {
let _ = Box::from_raw(pass).raw.into_vec();
}
} }

View File

@ -159,7 +159,7 @@ pub struct LifetimeTracker<B: hal::Backend> {
ready_to_map: Vec<id::BufferId>, ready_to_map: Vec<id::BufferId>,
} }
impl<B: GfxBackend> LifetimeTracker<B> { impl<B: hal::Backend> LifetimeTracker<B> {
pub fn new() -> Self { pub fn new() -> Self {
LifetimeTracker { LifetimeTracker {
mapped: Vec::new(), mapped: Vec::new(),
@ -202,13 +202,8 @@ impl<B: GfxBackend> LifetimeTracker<B> {
.fold(std::usize::MAX, |v, active| active.index.min(v)) .fold(std::usize::MAX, |v, active| active.index.min(v))
} }
/// Returns the last submission index that is done. fn wait_idle(&self, device: &B::Device) {
fn check_last_done( if !self.active.is_empty() {
&mut self,
device: &B::Device,
force_wait: bool,
) -> SubmissionIndex {
if force_wait && !self.active.is_empty() {
let status = unsafe { let status = unsafe {
device.wait_for_fences( device.wait_for_fences(
self.active.iter().map(|a| &a.fence), self.active.iter().map(|a| &a.fence),
@ -218,7 +213,13 @@ impl<B: GfxBackend> LifetimeTracker<B> {
}; };
assert_eq!(status, Ok(true), "GPU got stuck :("); assert_eq!(status, Ok(true), "GPU got stuck :(");
} }
}
/// Returns the last submission index that is done.
fn check_last_done(
&mut self,
device: &B::Device,
) -> SubmissionIndex {
//TODO: enable when `is_sorted_by_key` is stable //TODO: enable when `is_sorted_by_key` is stable
//debug_assert!(self.active.is_sorted_by_key(|a| a.index)); //debug_assert!(self.active.is_sorted_by_key(|a| a.index));
let done_count = self let done_count = self
@ -251,7 +252,10 @@ impl<B: GfxBackend> LifetimeTracker<B> {
heaps_mutex: &Mutex<Heaps<B>>, heaps_mutex: &Mutex<Heaps<B>>,
descriptor_allocator_mutex: &Mutex<DescriptorAllocator<B>>, descriptor_allocator_mutex: &Mutex<DescriptorAllocator<B>>,
) -> SubmissionIndex { ) -> SubmissionIndex {
let last_done = self.check_last_done(device, force_wait); if force_wait {
self.wait_idle(device);
}
let last_done = self.check_last_done(device);
unsafe { unsafe {
self.free_resources.clean( self.free_resources.clean(
device, device,
@ -261,7 +265,9 @@ impl<B: GfxBackend> LifetimeTracker<B> {
} }
last_done last_done
} }
}
impl<B: GfxBackend> LifetimeTracker<B> {
pub(crate) fn triage_suspected<F: AllIdentityFilter>( pub(crate) fn triage_suspected<F: AllIdentityFilter>(
&mut self, &mut self,
global: &Global<F>, global: &Global<F>,

View File

@ -110,6 +110,11 @@ pub(crate) type RenderPassContext = AttachmentData<resource::TextureFormat>;
type BufferMapResult = Result<*mut u8, hal::device::MapError>; type BufferMapResult = Result<*mut u8, hal::device::MapError>;
type BufferMapPendingCallback = (resource::BufferMapOperation, BufferMapResult); type BufferMapPendingCallback = (resource::BufferMapOperation, BufferMapResult);
pub type BufferMapReadCallback =
unsafe extern "C" fn(status: resource::BufferMapAsyncStatus, data: *const u8, userdata: *mut u8);
pub type BufferMapWriteCallback =
unsafe extern "C" fn(status: resource::BufferMapAsyncStatus, data: *mut u8, userdata: *mut u8);
fn map_buffer<B: hal::Backend>( fn map_buffer<B: hal::Backend>(
raw: &B::Device, raw: &B::Device,
buffer: &mut resource::Buffer<B>, buffer: &mut resource::Buffer<B>,
@ -164,6 +169,29 @@ fn unmap_buffer<B: hal::Backend>(
buffer.memory.unmap(raw); buffer.memory.unmap(raw);
} }
//Note: this logic is specifically moved out of `handle_mapping()` in order to
// have nothing locked by the time we execute users callback code.
fn fire_map_callbacks<I: IntoIterator<Item = BufferMapPendingCallback>>(callbacks: I) {
for (operation, result) in callbacks {
let (status, ptr) = match result {
Ok(ptr) => (resource::BufferMapAsyncStatus::Success, ptr),
Err(e) => {
log::error!("failed to map buffer: {:?}", e);
(resource::BufferMapAsyncStatus::Error, ptr::null_mut())
}
};
match operation {
resource::BufferMapOperation::Read(on_read) => {
on_read(status, ptr)
}
resource::BufferMapOperation::Write(on_write) => {
on_write(status, ptr)
}
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct Device<B: hal::Backend> { pub struct Device<B: hal::Backend> {
pub(crate) raw: B::Device, pub(crate) raw: B::Device,
@ -269,28 +297,6 @@ impl<B: GfxBackend> Device<B> {
callbacks callbacks
} }
//Note: this logic is specifically moved out of `handle_mapping()` in order to
// have nothing locked by the time we execute users callback code.
fn fire_map_callbacks<I: IntoIterator<Item = BufferMapPendingCallback>>(callbacks: I) {
for (operation, result) in callbacks {
let (status, ptr) = match result {
Ok(ptr) => (resource::BufferMapAsyncStatus::Success, ptr),
Err(e) => {
log::error!("failed to map buffer: {:?}", e);
(resource::BufferMapAsyncStatus::Error, ptr::null_mut())
}
};
match operation {
resource::BufferMapOperation::Read(on_read) => {
on_read(status, ptr)
}
resource::BufferMapOperation::Write(on_write) => {
on_write(status, ptr)
}
}
}
}
fn create_buffer( fn create_buffer(
&self, &self,
self_id: id::DeviceId, self_id: id::DeviceId,
@ -461,6 +467,12 @@ impl<B: hal::Backend> Device<B> {
} }
pub(crate) fn dispose(self) { pub(crate) fn dispose(self) {
self.life_tracker.lock().cleanup(
&self.raw,
true,
&self.mem_allocator,
&self.desc_allocator,
);
self.com_allocator.destroy(&self.raw); self.com_allocator.destroy(&self.raw);
let desc_alloc = self.desc_allocator.into_inner(); let desc_alloc = self.desc_allocator.into_inner();
let mem_alloc = self.mem_allocator.into_inner(); let mem_alloc = self.mem_allocator.into_inner();
@ -487,6 +499,8 @@ impl<F: IdentityFilter<id::BufferId>> Global<F> {
let hub = B::hub(self); let hub = B::hub(self);
let mut token = Token::root(); let mut token = Token::root();
log::info!("Create buffer {:?} with ID {:?}", desc, id_in);
let (device_guard, mut token) = hub.devices.read(&mut token); let (device_guard, mut token) = hub.devices.read(&mut token);
let device = &device_guard[device_id]; let device = &device_guard[device_id];
let buffer = device.create_buffer(device_id, desc); let buffer = device.create_buffer(device_id, desc);
@ -873,14 +887,16 @@ impl<F: IdentityFilter<id::BindGroupLayoutId>> Global<F> {
.map(|b| (b.binding, b)) .map(|b| (b.binding, b))
.collect(); .collect();
{ // TODO: deduplicate the bind group layouts at some level.
let (bind_group_layout_guard, _) = hub.bind_group_layouts.read(&mut token); // We can't do it right here, because in the remote scenario
let bind_group_layout = // the client need to know if the same ID can be used, or not.
bind_group_layout_guard if false {
.iter(device_id.backend()) let (bgl_guard, _) = hub.bind_group_layouts.read(&mut token);
.find(|(_, bgl)| bgl.bindings == bindings_map); let bind_group_layout_id = bgl_guard
.iter(device_id.backend())
.find(|(_, bgl)| bgl.bindings == bindings_map);
if let Some((id, _)) = bind_group_layout { if let Some((id, _)) = bind_group_layout_id {
return id; return id;
} }
} }
@ -914,6 +930,13 @@ impl<F: IdentityFilter<id::BindGroupLayoutId>> Global<F> {
hub.bind_group_layouts hub.bind_group_layouts
.register_identity(id_in, layout, &mut token) .register_identity(id_in, layout, &mut token)
} }
pub fn bind_group_layout_destroy<B: GfxBackend>(&self, bind_group_layout_id: id::BindGroupLayoutId) {
let hub = B::hub(self);
let mut token = Token::root();
//TODO: track usage by GPU
hub.bind_group_layouts.unregister(bind_group_layout_id, &mut token);
}
} }
impl<F: IdentityFilter<id::PipelineLayoutId>> Global<F> { impl<F: IdentityFilter<id::PipelineLayoutId>> Global<F> {
@ -956,6 +979,13 @@ impl<F: IdentityFilter<id::PipelineLayoutId>> Global<F> {
hub.pipeline_layouts hub.pipeline_layouts
.register_identity(id_in, layout, &mut token) .register_identity(id_in, layout, &mut token)
} }
pub fn pipeline_layout_destroy<B: GfxBackend>(&self, pipeline_layout_id: id::PipelineLayoutId) {
let hub = B::hub(self);
let mut token = Token::root();
//TODO: track usage by GPU
hub.pipeline_layouts.unregister(pipeline_layout_id, &mut token);
}
} }
impl<F: IdentityFilter<id::BindGroupId>> Global<F> { impl<F: IdentityFilter<id::BindGroupId>> Global<F> {
@ -1189,6 +1219,13 @@ impl<F: IdentityFilter<id::ShaderModuleId>> Global<F> {
hub.shader_modules hub.shader_modules
.register_identity(id_in, shader, &mut token) .register_identity(id_in, shader, &mut token)
} }
pub fn shader_module_destroy<B: GfxBackend>(&self, shader_module_id: id::ShaderModuleId) {
let hub = B::hub(self);
let mut token = Token::root();
//TODO: track usage by GPU
hub.shader_modules.unregister(shader_module_id, &mut token);
}
} }
impl<F: IdentityFilter<id::CommandEncoderId>> Global<F> { impl<F: IdentityFilter<id::CommandEncoderId>> Global<F> {
@ -1435,7 +1472,7 @@ impl<F: AllIdentityFilter + IdentityFilter<id::CommandBufferId>> Global<F> {
callbacks callbacks
}; };
Device::<B>::fire_map_callbacks(callbacks); fire_map_callbacks(callbacks);
} }
} }
@ -1701,6 +1738,13 @@ impl<F: IdentityFilter<id::RenderPipelineId>> Global<F> {
hub.render_pipelines hub.render_pipelines
.register_identity(id_in, pipeline, &mut token) .register_identity(id_in, pipeline, &mut token)
} }
pub fn render_pipeline_destroy<B: GfxBackend>(&self, render_pipeline_id: id::RenderPipelineId) {
let hub = B::hub(self);
let mut token = Token::root();
//TODO: track usage by GPU
hub.render_pipelines.unregister(render_pipeline_id, &mut token);
}
} }
impl<F: IdentityFilter<id::ComputePipelineId>> Global<F> { impl<F: IdentityFilter<id::ComputePipelineId>> Global<F> {
@ -1756,6 +1800,13 @@ impl<F: IdentityFilter<id::ComputePipelineId>> Global<F> {
hub.compute_pipelines hub.compute_pipelines
.register_identity(id_in, pipeline, &mut token) .register_identity(id_in, pipeline, &mut token)
} }
pub fn compute_pipeline_destroy<B: GfxBackend>(&self, compute_pipeline_id: id::ComputePipelineId) {
let hub = B::hub(self);
let mut token = Token::root();
//TODO: track usage by GPU
hub.compute_pipelines.unregister(compute_pipeline_id, &mut token);
}
} }
fn validate_swap_chain_descriptor( fn validate_swap_chain_descriptor(
@ -1863,7 +1914,40 @@ impl<F: AllIdentityFilter> Global<F> {
let (device_guard, mut token) = hub.devices.read(&mut token); let (device_guard, mut token) = hub.devices.read(&mut token);
device_guard[device_id].maintain(self, force_wait, &mut token) device_guard[device_id].maintain(self, force_wait, &mut token)
}; };
Device::<B>::fire_map_callbacks(callbacks); fire_map_callbacks(callbacks);
}
fn poll_devices<B: GfxBackend>(
&self,
force_wait: bool,
callbacks: &mut Vec<BufferMapPendingCallback>,
) {
let hub = B::hub(self);
let mut token = Token::root();
let (device_guard, mut token) = hub.devices.read(&mut token);
for (_, device) in device_guard.iter(B::VARIANT) {
let cbs = device.maintain(self, force_wait, &mut token);
callbacks.extend(cbs);
}
}
pub fn poll_all_devices(&self, force_wait: bool) {
use crate::backend;
let mut callbacks = Vec::new();
#[cfg(any(
not(any(target_os = "ios", target_os = "macos")),
feature = "gfx-backend-vulkan"
))]
self.poll_devices::<backend::Vulkan>(force_wait, &mut callbacks);
#[cfg(windows)]
self.poll_devices::<backend::Dx11>(force_wait, &mut callbacks);
#[cfg(windows)]
self.poll_devices::<backend::Dx12>(force_wait, &mut callbacks);
#[cfg(any(target_os = "ios", target_os = "macos"))]
self.poll_devices::<backend::Metal>(force_wait, &mut callbacks);
fire_map_callbacks(callbacks);
} }
} }

View File

@ -39,7 +39,7 @@ use vec_map::VecMap;
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
use std::cell::Cell; use std::cell::Cell;
use std::{marker::PhantomData, ops}; use std::{fmt::Debug, marker::PhantomData, ops};
/// A simple structure to manage identities of objects. /// A simple structure to manage identities of objects.
@ -252,13 +252,13 @@ impl<'a, T> Drop for Token<'a, T> {
} }
pub trait IdentityFilter<I> { pub trait IdentityFilter<I>: Debug {
type Input: Clone; type Input: Clone + Debug;
fn process(&self, id: Self::Input, backend: Backend) -> I; fn process(&self, id: Self::Input, backend: Backend) -> I;
fn free(&self, id: I); fn free(&self, id: I);
} }
impl<I: TypedId + Clone> IdentityFilter<I> for () { impl<I: TypedId + Clone + Debug> IdentityFilter<I> for () {
type Input = I; type Input = I;
fn process(&self, id: I, _backend: Backend) -> I { fn process(&self, id: I, _backend: Backend) -> I {
//debug_assert_eq!(id.unzip().2, backend); //debug_assert_eq!(id.unzip().2, backend);
@ -267,7 +267,7 @@ impl<I: TypedId + Clone> IdentityFilter<I> for () {
fn free(&self, _id: I) {} fn free(&self, _id: I) {}
} }
impl<I: TypedId> IdentityFilter<I> for Mutex<IdentityManager> { impl<I: TypedId + Debug> IdentityFilter<I> for Mutex<IdentityManager> {
type Input = PhantomData<I>; type Input = PhantomData<I>;
fn process(&self, _id: Self::Input, backend: Backend) -> I { fn process(&self, _id: Self::Input, backend: Backend) -> I {
self.lock().alloc(backend) self.lock().alloc(backend)

View File

@ -56,27 +56,25 @@ impl Instance {
} }
pub(crate) fn destroy_surface(&mut self, surface: Surface) { pub(crate) fn destroy_surface(&mut self, surface: Surface) {
//TODO: fill out the proper destruction once we are on gfx-0.4
#[cfg(any( #[cfg(any(
not(any(target_os = "ios", target_os = "macos")), not(any(target_os = "ios", target_os = "macos")),
feature = "gfx-backend-vulkan" feature = "gfx-backend-vulkan"
))] ))]
{ unsafe {
if let Some(_suf) = surface.vulkan { if let Some(suf) = surface.vulkan {
//self.vulkan.as_mut().unwrap().destroy_surface(suf); self.vulkan.as_mut().unwrap().destroy_surface(suf);
} }
} }
#[cfg(any(target_os = "ios", target_os = "macos"))] #[cfg(any(target_os = "ios", target_os = "macos"))]
{ unsafe {
let _ = surface; self.metal.destroy_surface(surface.metal);
//self.metal.destroy_surface(surface.metal);
} }
#[cfg(windows)] #[cfg(windows)]
{ unsafe {
if let Some(_suf) = surface.dx12 { if let Some(suf) = surface.dx12 {
//self.dx12.as_mut().unwrap().destroy_surface(suf); self.dx12.as_mut().unwrap().destroy_surface(suf);
} }
//self.dx11.destroy_surface(surface.dx11); self.dx11.destroy_surface(surface.dx11);
} }
} }
} }
@ -432,6 +430,12 @@ impl<F: IdentityFilter<AdapterId>> Global<F> {
let adapter = &adapter_guard[adapter_id]; let adapter = &adapter_guard[adapter_id];
AdapterInfo::from_gfx(adapter.raw.info.clone(), adapter_id.backend()) AdapterInfo::from_gfx(adapter.raw.info.clone(), adapter_id.backend())
} }
pub fn adapter_destroy<B: GfxBackend>(&self, adapter_id: AdapterId) {
let hub = B::hub(self);
let mut token = Token::root();
let (_adapter, _) = hub.adapters.unregister(adapter_id, &mut token);
}
} }
impl<F: IdentityFilter<DeviceId>> Global<F> { impl<F: IdentityFilter<DeviceId>> Global<F> {

View File

@ -59,6 +59,7 @@ pub enum Backend {
} }
pub type BufferAddress = u64; pub type BufferAddress = u64;
pub type DynamicOffset = u32;
pub type RawString = *const c_char; pub type RawString = *const c_char;
//TODO: make it private. Currently used for swapchain creation impl. //TODO: make it private. Currently used for swapchain creation impl.

View File

@ -1,3 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use std::fmt; use std::fmt;
#[derive(Debug)] #[derive(Debug)]
@ -15,13 +19,13 @@ impl fmt::Display for Error {
} }
} }
#[cfg(any( #[cfg(all(feature = "battery", any(
target_os = "linux", target_os = "linux",
target_os = "macos", target_os = "macos",
target_os = "windows", target_os = "windows",
target_os = "dragonfly", target_os = "dragonfly",
target_os = "freebsd" target_os = "freebsd"
))] )))]
mod platform { mod platform {
use super::Error; use super::Error;
use battery::{self, Manager, State}; use battery::{self, Manager, State};
@ -45,13 +49,13 @@ mod platform {
} }
} }
#[cfg(not(any( #[cfg(any(not(feature = "battery"), not(any(
target_os = "linux", target_os = "linux",
target_os = "macos", target_os = "macos",
target_os = "windows", target_os = "windows",
target_os = "dragonfly", target_os = "dragonfly",
target_os = "freebsd" target_os = "freebsd"
)))] ))))]
mod platform { mod platform {
use super::Error; use super::Error;

View File

@ -5,7 +5,6 @@
use crate::GLOBAL; use crate::GLOBAL;
pub use core::command::{ pub use core::command::{
wgpu_command_encoder_begin_compute_pass,
wgpu_command_encoder_begin_render_pass, wgpu_command_encoder_begin_render_pass,
compute_ffi::*, compute_ffi::*,
render_ffi::*, render_ffi::*,
@ -124,8 +123,22 @@ pub unsafe extern "C" fn wgpu_render_pass_end_pass(pass_id: id::RenderPassId) {
/// This function is unsafe because improper use may lead to memory /// This function is unsafe because improper use may lead to memory
/// problems. For example, a double-free may occur if the function is called /// problems. For example, a double-free may occur if the function is called
/// twice on the same raw pointer. /// twice on the same raw pointer.
#[no_mangle]
pub unsafe extern "C" fn wgpu_command_encoder_begin_compute_pass(
encoder_id: id::CommandEncoderId,
_desc: Option<&core::command::ComputePassDescriptor>,
) -> *mut core::command::RawPass {
let pass = core::command::RawPass::new_compute(encoder_id);
Box::into_raw(Box::new(pass))
}
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wgpu_compute_pass_end_pass(pass_id: id::ComputePassId) { pub unsafe extern "C" fn wgpu_compute_pass_end_pass(pass_id: id::ComputePassId) {
let (pass_data, encoder_id) = Box::from_raw(pass_id).finish_compute(); let (pass_data, encoder_id) = Box::from_raw(pass_id).finish_compute();
gfx_select!(encoder_id => GLOBAL.command_encoder_run_compute_pass(encoder_id, &pass_data)) gfx_select!(encoder_id => GLOBAL.command_encoder_run_compute_pass(encoder_id, &pass_data))
} }
#[no_mangle]
pub unsafe extern "C" fn wgpu_compute_pass_destroy(pass: *mut core::command::RawPass) {
let _ = Box::from_raw(pass).into_vec();
}

View File

@ -13,10 +13,6 @@ use objc::{msg_send, runtime::Object, sel, sel_impl};
pub type RequestAdapterCallback = pub type RequestAdapterCallback =
unsafe extern "C" fn(id: id::AdapterId, userdata: *mut std::ffi::c_void); unsafe extern "C" fn(id: id::AdapterId, userdata: *mut std::ffi::c_void);
pub type BufferMapReadCallback =
unsafe extern "C" fn(status: core::resource::BufferMapAsyncStatus, data: *const u8, userdata: *mut u8);
pub type BufferMapWriteCallback =
unsafe extern "C" fn(status: core::resource::BufferMapAsyncStatus, data: *mut u8, userdata: *mut u8);
pub fn wgpu_create_surface(raw_handle: raw_window_handle::RawWindowHandle) -> id::SurfaceId { pub fn wgpu_create_surface(raw_handle: raw_window_handle::RawWindowHandle) -> id::SurfaceId {
use raw_window_handle::RawWindowHandle as Rwh; use raw_window_handle::RawWindowHandle as Rwh;
@ -176,10 +172,15 @@ pub extern "C" fn wgpu_adapter_request_device(
gfx_select!(adapter_id => GLOBAL.adapter_request_device(adapter_id, desc, PhantomData)) gfx_select!(adapter_id => GLOBAL.adapter_request_device(adapter_id, desc, PhantomData))
} }
pub fn wgpu_adapter_get_info(adapter_id: id::AdapterId) -> core::instance::AdapterInfo { pub fn adapter_get_info(adapter_id: id::AdapterId) -> core::instance::AdapterInfo {
gfx_select!(adapter_id => GLOBAL.adapter_get_info(adapter_id)) gfx_select!(adapter_id => GLOBAL.adapter_get_info(adapter_id))
} }
#[no_mangle]
pub extern "C" fn wgpu_adapter_destroy(adapter_id: id::AdapterId) {
gfx_select!(adapter_id => GLOBAL.adapter_destroy(adapter_id))
}
#[no_mangle] #[no_mangle]
pub extern "C" fn wgpu_device_get_limits( pub extern "C" fn wgpu_device_get_limits(
_device_id: id::DeviceId, _device_id: id::DeviceId,
@ -371,7 +372,7 @@ pub extern "C" fn wgpu_buffer_map_read_async(
buffer_id: id::BufferId, buffer_id: id::BufferId,
start: core::BufferAddress, start: core::BufferAddress,
size: core::BufferAddress, size: core::BufferAddress,
callback: BufferMapReadCallback, callback: core::device::BufferMapReadCallback,
userdata: *mut u8, userdata: *mut u8,
) { ) {
let operation = core::resource::BufferMapOperation::Read( let operation = core::resource::BufferMapOperation::Read(
@ -387,7 +388,7 @@ pub extern "C" fn wgpu_buffer_map_write_async(
buffer_id: id::BufferId, buffer_id: id::BufferId,
start: core::BufferAddress, start: core::BufferAddress,
size: core::BufferAddress, size: core::BufferAddress,
callback: BufferMapWriteCallback, callback: core::device::BufferMapWriteCallback,
userdata: *mut u8, userdata: *mut u8,
) { ) {
let operation = core::resource::BufferMapOperation::Write( let operation = core::resource::BufferMapOperation::Write(

View File

@ -16,6 +16,7 @@ braces = "SameLine"
line_length = 100 line_length = 100
tab_width = 2 tab_width = 2
language = "C" language = "C"
style = "tag"
[export] [export]
prefix = "WGPU" prefix = "WGPU"
@ -25,6 +26,8 @@ exclude = ["BufferMapResult"]
parse_deps = true parse_deps = true
include = ["wgpu-core"] include = ["wgpu-core"]
extra_bindings = ["wgpu-core"]
[fn] [fn]
prefix = "WGPU_INLINE" prefix = "WGPU_INLINE"
postfix = "WGPU_FUNC" postfix = "WGPU_FUNC"

View File

@ -8,6 +8,12 @@ use core::{
Backend, Backend,
}; };
pub use core::command::{
wgpu_command_encoder_begin_render_pass,
compute_ffi::*,
render_ffi::*,
};
use parking_lot::Mutex; use parking_lot::Mutex;
use std::{ptr, slice}; use std::{ptr, slice};
@ -21,6 +27,11 @@ struct IdentityHub {
devices: IdentityManager, devices: IdentityManager,
buffers: IdentityManager, buffers: IdentityManager,
command_buffers: IdentityManager, command_buffers: IdentityManager,
bind_group_layouts: IdentityManager,
pipeline_layouts: IdentityManager,
bind_groups: IdentityManager,
shader_modules: IdentityManager,
compute_pipelines: IdentityManager,
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]
@ -194,3 +205,151 @@ pub extern "C" fn wgpu_client_kill_encoder_id(
.command_buffers .command_buffers
.free(id) .free(id)
} }
#[no_mangle]
pub unsafe extern "C" fn wgpu_command_encoder_begin_compute_pass(
encoder_id: id::CommandEncoderId,
_desc: Option<&core::command::ComputePassDescriptor>,
) -> core::command::RawPass {
core::command::RawPass::new_compute(encoder_id)
}
#[no_mangle]
pub unsafe extern "C" fn wgpu_compute_pass_destroy(pass: core::command::RawPass) {
let _ = pass.into_vec();
}
#[no_mangle]
pub extern "C" fn wgpu_client_make_bind_group_layout_id(
client: &Client,
device_id: id::DeviceId,
) -> id::BindGroupLayoutId {
let backend = device_id.backend();
client
.identities
.lock()
.select(backend)
.bind_group_layouts
.alloc(backend)
}
#[no_mangle]
pub extern "C" fn wgpu_client_kill_bind_group_layout_id(
client: &Client,
id: id::BindGroupLayoutId,
) {
client
.identities
.lock()
.select(id.backend())
.bind_group_layouts
.free(id)
}
#[no_mangle]
pub extern "C" fn wgpu_client_make_pipeline_layout_id(
client: &Client,
device_id: id::DeviceId,
) -> id::PipelineLayoutId {
let backend = device_id.backend();
client
.identities
.lock()
.select(backend)
.pipeline_layouts
.alloc(backend)
}
#[no_mangle]
pub extern "C" fn wgpu_client_kill_pipeline_layout_id(
client: &Client,
id: id::PipelineLayoutId,
) {
client
.identities
.lock()
.select(id.backend())
.pipeline_layouts
.free(id)
}
#[no_mangle]
pub extern "C" fn wgpu_client_make_bind_group_id(
client: &Client,
device_id: id::DeviceId,
) -> id::BindGroupId {
let backend = device_id.backend();
client
.identities
.lock()
.select(backend)
.bind_groups
.alloc(backend)
}
#[no_mangle]
pub extern "C" fn wgpu_client_kill_bind_group_id(
client: &Client,
id: id::BindGroupId,
) {
client
.identities
.lock()
.select(id.backend())
.bind_groups
.free(id)
}
#[no_mangle]
pub extern "C" fn wgpu_client_make_shader_module_id(
client: &Client,
device_id: id::DeviceId,
) -> id::ShaderModuleId {
let backend = device_id.backend();
client
.identities
.lock()
.select(backend)
.shader_modules
.alloc(backend)
}
#[no_mangle]
pub extern "C" fn wgpu_client_kill_shader_module_id(
client: &Client,
id: id::ShaderModuleId,
) {
client
.identities
.lock()
.select(id.backend())
.shader_modules
.free(id)
}
#[no_mangle]
pub extern "C" fn wgpu_client_make_compute_pipeline_id(
client: &Client,
device_id: id::DeviceId,
) -> id::ComputePipelineId {
let backend = device_id.backend();
client
.identities
.lock()
.select(backend)
.compute_pipelines
.alloc(backend)
}
#[no_mangle]
pub extern "C" fn wgpu_client_kill_compute_pipeline_id(
client: &Client,
id: id::ComputePipelineId,
) {
client
.identities
.lock()
.select(id.backend())
.compute_pipelines
.free(id)
}

View File

@ -26,6 +26,11 @@ pub unsafe extern "C" fn wgpu_server_delete(global: *mut Global) {
log::info!("\t...done"); log::info!("\t...done");
} }
#[no_mangle]
pub extern "C" fn wgpu_server_poll_all_devices(global: &Global, force_wait: bool) {
global.poll_all_devices(force_wait);
}
/// Request an adapter according to the specified options. /// Request an adapter according to the specified options.
/// Provide the list of IDs to pick from. /// Provide the list of IDs to pick from.
/// ///
@ -62,6 +67,14 @@ pub extern "C" fn wgpu_server_adapter_request_device(
gfx_select!(self_id => global.adapter_request_device(self_id, desc, new_id)); gfx_select!(self_id => global.adapter_request_device(self_id, desc, new_id));
} }
#[no_mangle]
pub extern "C" fn wgpu_server_adapter_destroy(
global: &Global,
adapter_id: id::AdapterId,
) {
gfx_select!(adapter_id => global.adapter_destroy(adapter_id))
}
#[no_mangle] #[no_mangle]
pub extern "C" fn wgpu_server_device_destroy(global: &Global, self_id: id::DeviceId) { pub extern "C" fn wgpu_server_device_destroy(global: &Global, self_id: id::DeviceId) {
gfx_select!(self_id => global.device_destroy(self_id)) gfx_select!(self_id => global.device_destroy(self_id))
@ -99,16 +112,25 @@ pub unsafe extern "C" fn wgpu_server_device_set_buffer_sub_data(
/// This function is unsafe as there is no guarantee that the given pointer is /// This function is unsafe as there is no guarantee that the given pointer is
/// valid for `size` elements. /// valid for `size` elements.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wgpu_server_device_get_buffer_sub_data( pub extern "C" fn wgpu_server_buffer_map_read(
global: &Global, global: &Global,
self_id: id::DeviceId,
buffer_id: id::BufferId, buffer_id: id::BufferId,
offset: core::BufferAddress, start: core::BufferAddress,
data: *mut u8,
size: core::BufferAddress, size: core::BufferAddress,
callback: core::device::BufferMapReadCallback,
userdata: *mut u8,
) { ) {
let slice = slice::from_raw_parts_mut(data, size as usize); let operation = core::resource::BufferMapOperation::Read(
gfx_select!(self_id => global.device_get_buffer_sub_data(self_id, buffer_id, offset, slice)); Box::new(move |status, data| unsafe {
callback(status, data, userdata)
}),
);
gfx_select!(buffer_id => global.buffer_map_async(
buffer_id,
core::resource::BufferUsage::MAP_READ,
start .. start + size,
operation
));
} }
#[no_mangle] #[no_mangle]
@ -120,12 +142,19 @@ pub extern "C" fn wgpu_server_buffer_destroy(global: &Global, self_id: id::Buffe
pub extern "C" fn wgpu_server_device_create_encoder( pub extern "C" fn wgpu_server_device_create_encoder(
global: &Global, global: &Global,
self_id: id::DeviceId, self_id: id::DeviceId,
encoder_id: id::CommandEncoderId, desc: &core::command::CommandEncoderDescriptor,
new_id: id::CommandEncoderId,
) { ) {
let desc = core::command::CommandEncoderDescriptor { gfx_select!(self_id => global.device_create_command_encoder(self_id, &desc, new_id));
todo: 0, }
};
gfx_select!(self_id => global.device_create_command_encoder(self_id, &desc, encoder_id)); #[no_mangle]
pub extern "C" fn wgpu_server_encoder_finish(
global: &Global,
self_id: id::CommandEncoderId,
desc: &core::command::CommandBufferDescriptor,
) {
gfx_select!(self_id => global.command_encoder_finish(self_id, desc));
} }
#[no_mangle] #[no_mangle]
@ -140,6 +169,27 @@ pub extern "C" fn wgpu_server_encoder_destroy(
/// ///
/// This function is unsafe as there is no guarantee that the given pointer is /// This function is unsafe as there is no guarantee that the given pointer is
/// valid for `byte_length` elements. /// valid for `byte_length` elements.
#[no_mangle]
pub extern "C" fn wgpu_server_command_buffer_destroy(
global: &Global,
self_id: id::CommandBufferId,
) {
gfx_select!(self_id => global.command_buffer_destroy(self_id));
}
#[no_mangle]
pub unsafe extern "C" fn wgpu_server_encoder_copy_buffer_to_buffer(
global: &Global,
self_id: id::CommandEncoderId,
source_id: id::BufferId,
source_offset: core::BufferAddress,
destination_id: id::BufferId,
destination_offset: core::BufferAddress,
size: core::BufferAddress,
) {
gfx_select!(self_id => global.command_encoder_copy_buffer_to_buffer(self_id, source_id, source_offset, destination_id, destination_offset, size));
}
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wgpu_server_encode_compute_pass( pub unsafe extern "C" fn wgpu_server_encode_compute_pass(
global: &Global, global: &Global,
@ -185,3 +235,93 @@ pub unsafe extern "C" fn wgpu_server_queue_submit(
let command_buffers = slice::from_raw_parts(command_buffer_ids, command_buffer_id_length); let command_buffers = slice::from_raw_parts(command_buffer_ids, command_buffer_id_length);
gfx_select!(self_id => global.queue_submit(self_id, command_buffers)); gfx_select!(self_id => global.queue_submit(self_id, command_buffers));
} }
#[no_mangle]
pub extern "C" fn wgpu_server_device_create_bind_group_layout(
global: &Global,
self_id: id::DeviceId,
desc: &core::binding_model::BindGroupLayoutDescriptor,
new_id: id::BindGroupLayoutId,
) {
gfx_select!(self_id => global.device_create_bind_group_layout(self_id, desc, new_id));
}
#[no_mangle]
pub extern "C" fn wgpu_server_bind_group_layout_destroy(
global: &Global,
self_id: id::BindGroupLayoutId,
) {
gfx_select!(self_id => global.bind_group_layout_destroy(self_id));
}
#[no_mangle]
pub extern "C" fn wgpu_server_device_create_pipeline_layout(
global: &Global,
self_id: id::DeviceId,
desc: &core::binding_model::PipelineLayoutDescriptor,
new_id: id::PipelineLayoutId,
) {
gfx_select!(self_id => global.device_create_pipeline_layout(self_id, desc, new_id));
}
#[no_mangle]
pub extern "C" fn wgpu_server_pipeline_layout_destroy(
global: &Global,
self_id: id::PipelineLayoutId,
) {
gfx_select!(self_id => global.pipeline_layout_destroy(self_id));
}
#[no_mangle]
pub extern "C" fn wgpu_server_device_create_bind_group(
global: &Global,
self_id: id::DeviceId,
desc: &core::binding_model::BindGroupDescriptor,
new_id: id::BindGroupId,
) {
gfx_select!(self_id => global.device_create_bind_group(self_id, desc, new_id));
}
#[no_mangle]
pub extern "C" fn wgpu_server_bind_group_destroy(
global: &Global,
self_id: id::BindGroupId,
) {
gfx_select!(self_id => global.bind_group_destroy(self_id));
}
#[no_mangle]
pub extern "C" fn wgpu_server_device_create_shader_module(
global: &Global,
self_id: id::DeviceId,
desc: &core::pipeline::ShaderModuleDescriptor,
new_id: id::ShaderModuleId,
) {
gfx_select!(self_id => global.device_create_shader_module(self_id, desc, new_id));
}
#[no_mangle]
pub extern "C" fn wgpu_server_shader_module_destroy(
global: &Global,
self_id: id::ShaderModuleId,
) {
gfx_select!(self_id => global.shader_module_destroy(self_id));
}
#[no_mangle]
pub extern "C" fn wgpu_server_device_create_compute_pipeline(
global: &Global,
self_id: id::DeviceId,
desc: &core::pipeline::ComputePipelineDescriptor,
new_id: id::ComputePipelineId,
) {
gfx_select!(self_id => global.device_create_compute_pipeline(self_id, desc, new_id));
}
#[no_mangle]
pub extern "C" fn wgpu_server_compute_pipeline_destroy(
global: &Global,
self_id: id::ComputePipelineId,
) {
gfx_select!(self_id => global.compute_pipeline_destroy(self_id));
}