Use peek-poke for compute pass encoding

This commit is contained in:
Dzmitry Malyshau
2020-01-08 14:26:51 -05:00
parent 20cd803d67
commit c01a7c6abe
9 changed files with 257 additions and 28 deletions

56
Cargo.lock generated
View File

@@ -365,11 +365,37 @@ dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "peek-poke"
version = "0.2.0"
source = "git+https://github.com/djg/peek-poke?rev=728591c140ead9a6b646a27eaad29e5136fb96b8#728591c140ead9a6b646a27eaad29e5136fb96b8"
dependencies = [
"peek-poke-derive 0.2.0 (git+https://github.com/djg/peek-poke?rev=728591c140ead9a6b646a27eaad29e5136fb96b8)",
]
[[package]]
name = "peek-poke-derive"
version = "0.2.0"
source = "git+https://github.com/djg/peek-poke?rev=728591c140ead9a6b646a27eaad29e5136fb96b8#728591c140ead9a6b646a27eaad29e5136fb96b8"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pkg-config"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro2"
version = "1.0.6"
@@ -378,6 +404,14 @@ dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "1.0.2"
@@ -527,6 +561,16 @@ dependencies = [
"lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "0.15.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "1.0.11"
@@ -537,6 +581,11 @@ dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.2.0"
@@ -612,6 +661,7 @@ dependencies = [
"gfx-hal 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"peek-poke 0.2.0 (git+https://github.com/djg/peek-poke?rev=728591c140ead9a6b646a27eaad29e5136fb96b8)",
"rendy-descriptor 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rendy-memory 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -717,8 +767,12 @@ dependencies = [
"checksum objc_exception 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4"
"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
"checksum peek-poke 0.2.0 (git+https://github.com/djg/peek-poke?rev=728591c140ead9a6b646a27eaad29e5136fb96b8)" = "<none>"
"checksum peek-poke-derive 0.2.0 (git+https://github.com/djg/peek-poke?rev=728591c140ead9a6b646a27eaad29e5136fb96b8)" = "<none>"
"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
"checksum range-alloc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5927936723a9e8b715d37d7e4b390455087c4bdf25b9f702309460577b14f9"
"checksum raw-window-handle 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211"
@@ -738,7 +792,9 @@ dependencies = [
"checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86"
"checksum spirv_cross 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fbbe441b3ac8ec0ae6a4f05234239bd372a241ce15793eef694e8b24afc267bb"
"checksum storage-map 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0a4829a5c591dc24a944a736d6b1e4053e51339a79fd5d4702c4c999a9c45e"
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
"checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum wasm-bindgen 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "29ae32af33bacd663a9a28241abecf01f2be64e6a185c6139b04f18b6385c5f2"

View File

@@ -243,6 +243,10 @@ typedef enum {
WGPUVertexFormat_Int4 = 48,
} WGPUVertexFormat;
typedef struct WGPURawPass WGPURawPass;
typedef struct WGPURenderCommand WGPURenderCommand;
typedef uint64_t WGPUId_Device_Dummy;
typedef WGPUId_Device_Dummy WGPUDeviceId;
@@ -698,6 +702,8 @@ WGPUComputePassId wgpu_command_encoder_begin_compute_pass(WGPUCommandEncoderId e
WGPURenderPassId wgpu_command_encoder_begin_render_pass(WGPUCommandEncoderId encoder_id,
const WGPURenderPassDescriptor *desc);
void wgpu_command_encoder_compute_pass(WGPUCommandEncoderId self_id, const WGPURawPass *pass);
void wgpu_command_encoder_copy_buffer_to_buffer(WGPUCommandEncoderId command_encoder_id,
WGPUBufferId source,
WGPUBufferAddress source_offset,
@@ -725,6 +731,15 @@ void wgpu_command_encoder_destroy(WGPUCommandEncoderId command_encoder_id);
WGPUCommandBufferId wgpu_command_encoder_finish(WGPUCommandEncoderId encoder_id,
const WGPUCommandBufferDescriptor *desc);
void wgpu_command_encoder_render_pass(WGPUCommandEncoderId self_id,
const WGPURenderPassColorAttachmentDescriptor *color_attachments,
uintptr_t color_attachment_length,
const WGPURenderPassDepthStencilAttachmentDescriptor *depth_stencil_attachment,
const WGPURenderCommand *commands,
uintptr_t command_length,
const WGPUBufferAddress *offsets,
uintptr_t offset_length);
void wgpu_compute_pass_dispatch(WGPUComputePassId pass_id, uint32_t x, uint32_t y, uint32_t z);
void wgpu_compute_pass_dispatch_indirect(WGPUComputePassId pass_id,

View File

@@ -29,6 +29,7 @@ log = "0.4"
hal = { package = "gfx-hal", version = "0.4" }
gfx-backend-empty = { version = "0.4" }
parking_lot = "0.9"
peek-poke = { git = "https://github.com/djg/peek-poke", rev = "728591c140ead9a6b646a27eaad29e5136fb96b8" }
rendy-memory = "0.5"
rendy-descriptor = "0.5"
serde = { version = "1.0", features = ["serde_derive"], optional = true }

View File

@@ -6,7 +6,7 @@ use crate::{
command::{
bind::{Binder, LayoutChange},
CommandBuffer,
OffsetIndex,
RawPass,
},
device::{all_buffer_stages, BIND_BUFFER_ALIGNMENT},
hub::{GfxBackend, Global, IdentityFilter, Token},
@@ -18,17 +18,17 @@ use crate::{
};
use hal::command::CommandBuffer as _;
use peek_poke::{Peek, PeekCopy, Poke};
use std::{iter, ops::Range};
use std::{convert::TryInto, iter, mem, ptr, slice};
#[non_exhaustive]
#[derive(Debug)]
#[derive(Clone, Copy, Debug, PeekCopy, Poke)]
pub enum ComputeCommand {
SetBindGroup {
index: u32,
num_dynamic_offsets: u8,
bind_group_id: id::BindGroupId,
offset_indices: Range<OffsetIndex>,
},
SetPipeline(id::ComputePipelineId),
Dispatch([u32; 3]),
@@ -38,12 +38,6 @@ pub enum ComputeCommand {
},
}
#[derive(Copy, Clone, Debug)]
pub struct StandaloneComputePass<'a> {
pub commands: &'a [ComputeCommand],
pub offsets: &'a [BufferAddress],
}
#[repr(C)]
#[derive(Clone, Debug, Default)]
pub struct ComputePassDescriptor {
@@ -96,7 +90,7 @@ impl<F> Global<F> {
pub fn command_encoder_run_compute_pass<B: GfxBackend>(
&self,
encoder_id: id::CommandEncoderId,
pass: StandaloneComputePass,
raw_data: &[u8],
) {
let hub = B::hub(self);
let mut token = Token::root();
@@ -112,10 +106,23 @@ impl<F> Global<F> {
let (buffer_guard, mut token) = hub.buffers.read(&mut token);
let (texture_guard, _) = hub.textures.read(&mut token);
for command in pass.commands {
match *command {
ComputeCommand::SetBindGroup { index, bind_group_id, ref offset_indices } => {
let offsets = &pass.offsets[offset_indices.start as usize .. offset_indices.end as usize];
let mut peeker = raw_data.as_ptr();
let raw_data_end = unsafe {
raw_data.as_ptr().add(raw_data.len())
};
let mut command = ComputeCommand::Dispatch([0; 3]); // dummy
while unsafe { peeker.add(mem::size_of::<ComputeCommand>()) } <= raw_data_end {
peeker = unsafe { command.peek_from(peeker) };
match command {
ComputeCommand::SetBindGroup { index, num_dynamic_offsets, bind_group_id } => {
debug_assert_eq!(peeker.align_offset(mem::align_of::<BufferAddress>()), 0);
let extra_size = (num_dynamic_offsets as usize) * mem::size_of::<BufferAddress>();
let end = unsafe { peeker.add(extra_size) };
assert!(end <= raw_data_end);
let offsets = unsafe {
slice::from_raw_parts(peeker as *const BufferAddress, num_dynamic_offsets as usize)
};
peeker = end;
if cfg!(debug_assertions) {
for off in offsets {
assert_eq!(
@@ -234,6 +241,8 @@ impl<F> Global<F> {
}
}
}
assert_eq!(peeker, raw_data_end);
}
pub fn compute_pass_set_bind_group<B: GfxBackend>(
@@ -413,3 +422,73 @@ impl<F> Global<F> {
}
}
}
impl RawPass {
#[inline]
unsafe fn encode(&mut self, command: &ComputeCommand) {
self.ensure_extra_size(mem::size_of::<ComputeCommand>());
self.data = command.poke_into(self.data);
}
#[inline]
unsafe fn encode_with<T>(&mut self, command: &ComputeCommand, extra: &[T]) {
let extra_size = extra.len() * mem::size_of::<T>();
self.ensure_extra_size(mem::size_of::<ComputeCommand>() + extra_size);
self.data = command.poke_into(self.data);
debug_assert_eq!(self.data.align_offset(mem::align_of::<T>()), 0);
ptr::copy_nonoverlapping(extra.as_ptr(), self.data as *mut T, extra.len());
self.data = self.data.add(extra_size);
}
#[no_mangle]
pub unsafe extern "C" fn wgpu_raw_compute_pass_set_bind_group(
&mut self,
index: u32,
bind_group_id: id::BindGroupId,
offsets: *const BufferAddress,
offset_length: usize,
) {
self.encode_with(
&ComputeCommand::SetBindGroup {
index,
num_dynamic_offsets: offset_length.try_into().unwrap(),
bind_group_id,
},
slice::from_raw_parts(offsets, offset_length),
);
for offset in slice::from_raw_parts(offsets, offset_length) {
self.data = offset.poke_into(self.data);
}
}
#[no_mangle]
pub unsafe extern "C" fn wgpu_standalone_compute_pass_set_pipeline(
&mut self,
pipeline_id: id::ComputePipelineId,
) {
self.encode(&ComputeCommand::SetPipeline(pipeline_id));
}
#[no_mangle]
pub unsafe extern "C" fn wgpu_standalone_compute_pass_dispatch(
&mut self,
groups_x: u32,
groups_y: u32,
groups_z: u32,
) {
self.encode(&ComputeCommand::Dispatch([groups_x, groups_y, groups_z]));
}
#[no_mangle]
pub unsafe extern "C" fn wgpu_standalone_compute_pass_dispatch_indirect(
&mut self,
buffer_id: id::BufferId,
offset: BufferAddress,
) {
self.encode(&ComputeCommand::DispatchIndirect {
buffer_id,
offset,
});
}
}

View File

@@ -54,7 +54,45 @@ use std::{
};
pub type OffsetIndex = u16;
pub struct RawPass {
data: *mut u8,
base: *mut u8,
capacity: usize,
}
impl RawPass {
pub fn new() -> Self {
let mut vec = Vec::with_capacity(16);
RawPass {
data: vec.as_mut_ptr(),
base: vec.as_mut_ptr(),
capacity: vec.capacity(),
}
}
pub unsafe fn delete(self) {
let size = self.data as usize - self.base as usize;
let _ = Vec::from_raw_parts(self.base, size, self.capacity);
}
pub unsafe fn to_slice(&self) -> &[u8] {
let size = self.data as usize - self.base as usize;
assert!(size <= self.capacity);
slice::from_raw_parts(self.base, size)
}
unsafe fn ensure_extra_size(&mut self, extra_size: usize) {
let size = self.data as usize - self.base as usize;
if let Some(extra_capacity) = (size + extra_size).checked_sub(self.capacity) {
let mut vec = Vec::from_raw_parts(self.base, size, self.capacity);
vec.reserve(extra_capacity);
//let (data, size, capacity) = vec.into_raw_parts(); //TODO: when stable
self.data = vec.as_mut_ptr().add(vec.len());
self.base = vec.as_mut_ptr();
self.capacity = vec.capacity();
}
}
}
pub struct RenderBundle<B: hal::Backend> {
_raw: B::CommandBuffer,

View File

@@ -6,7 +6,6 @@ use crate::{
command::{
bind::{Binder, LayoutChange},
CommandBuffer,
OffsetIndex,
},
conv,
device::{
@@ -38,6 +37,8 @@ use std::{
};
type OffsetIndex = u16;
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum LoadOp {

View File

@@ -5,7 +5,7 @@
use crate::{Backend, Epoch, Index};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::{fmt, marker::PhantomData};
use std::{fmt, marker::PhantomData, mem};
const BACKEND_BITS: usize = 3;
const EPOCH_MASK: u32 = (1 << (32 - BACKEND_BITS)) - 1;
@@ -57,6 +57,21 @@ impl<T> PartialEq for Id<T> {
}
}
unsafe impl<T> peek_poke::Poke for Id<T> {
fn max_size() -> usize {
mem::size_of::<u64>()
}
unsafe fn poke_into(&self, data: *mut u8) -> *mut u8 {
self.0.poke_into(data)
}
}
impl<T> peek_poke::Peek for Id<T> {
unsafe fn peek_from(&mut self, data: *const u8) -> *const u8 {
self.0.peek_from(data)
}
}
pub trait TypedId {
fn zip(index: Index, epoch: Epoch, backend: Backend) -> Self;
fn unzip(self) -> (Index, Epoch, Backend);

View File

@@ -315,3 +315,32 @@ pub extern "C" fn wgpu_compute_pass_set_pipeline(
) {
gfx_select!(pass_id => GLOBAL.compute_pass_set_pipeline(pass_id, pipeline_id))
}
#[no_mangle]
pub unsafe extern "C" fn wgpu_command_encoder_compute_pass(
self_id: id::CommandEncoderId,
pass: &core::command::RawPass,
) {
let raw_data = pass.to_slice();
gfx_select!(self_id => GLOBAL.command_encoder_run_compute_pass(self_id, raw_data));
}
#[no_mangle]
pub unsafe extern "C" fn wgpu_command_encoder_render_pass(
self_id: id::CommandEncoderId,
color_attachments: *const core::command::RenderPassColorAttachmentDescriptor,
color_attachment_length: usize,
depth_stencil_attachment: Option<&core::command::RenderPassDepthStencilAttachmentDescriptor>,
commands: *const core::command::RenderCommand,
command_length: usize,
offsets: *const core::BufferAddress,
offset_length: usize,
) {
let pass = core::command::StandaloneRenderPass {
color_attachments: slice::from_raw_parts(color_attachments, color_attachment_length),
depth_stencil_attachment,
commands: slice::from_raw_parts(commands, command_length),
offsets: slice::from_raw_parts(offsets, offset_length),
};
gfx_select!(self_id => GLOBAL.command_encoder_run_render_pass(self_id, pass));
}

View File

@@ -127,16 +127,11 @@ pub extern "C" fn wgpu_server_encoder_destroy(
pub unsafe extern "C" fn wgpu_server_encode_compute_pass(
global: &Global,
self_id: id::CommandEncoderId,
commands: *const core::command::ComputeCommand,
command_length: usize,
offsets: *const core::BufferAddress,
offset_length: usize,
bytes: *const u8,
byte_length: usize,
) {
let pass = core::command::StandaloneComputePass {
commands: slice::from_raw_parts(commands, command_length),
offsets: slice::from_raw_parts(offsets, offset_length),
};
gfx_select!(self_id => global.command_encoder_run_compute_pass(self_id, pass));
let raw_data = slice::from_raw_parts(bytes, byte_length);
gfx_select!(self_id => global.command_encoder_run_compute_pass(self_id, raw_data));
}
#[no_mangle]