Skip to content

Commit

Permalink
[wgpu-core] make implicit_pipeline_ids arg optional for users that …
Browse files Browse the repository at this point in the history
…don't provide IDs
  • Loading branch information
teoxoy committed Jul 17, 2024
1 parent 7e112ca commit 91924fb
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 117 deletions.
25 changes: 2 additions & 23 deletions deno_webgpu/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ use std::rc::Rc;
use super::error::WebGpuError;
use super::error::WebGpuResult;

const MAX_BIND_GROUPS: usize = 8;

pub(crate) struct WebGpuPipelineLayout(
pub(crate) crate::Instance,
pub(crate) wgpu_core::id::PipelineLayoutId,
Expand Down Expand Up @@ -118,21 +116,12 @@ pub fn op_webgpu_create_compute_pipeline(
},
cache: None,
};
let implicit_pipelines = match layout {
GPUPipelineLayoutOrGPUAutoLayoutMode::Layout(_) => None,
GPUPipelineLayoutOrGPUAutoLayoutMode::Auto(GPUAutoLayoutMode::Auto) => {
Some(wgpu_core::device::ImplicitPipelineIds {
root_id: None,
group_ids: &[None; MAX_BIND_GROUPS],
})
}
};

let (compute_pipeline, maybe_err) = gfx_select!(device => instance.device_create_compute_pipeline(
device,
&descriptor,
None,
implicit_pipelines
None,
));

let rid = state
Expand Down Expand Up @@ -397,21 +386,11 @@ pub fn op_webgpu_create_render_pipeline(
cache: None,
};

let implicit_pipelines = match args.layout {
GPUPipelineLayoutOrGPUAutoLayoutMode::Layout(_) => None,
GPUPipelineLayoutOrGPUAutoLayoutMode::Auto(GPUAutoLayoutMode::Auto) => {
Some(wgpu_core::device::ImplicitPipelineIds {
root_id: None,
group_ids: &[None; MAX_BIND_GROUPS],
})
}
};

let (render_pipeline, maybe_err) = gfx_select!(device => instance.device_create_render_pipeline(
device,
&descriptor,
None,
implicit_pipelines
None,
));

let rid = state
Expand Down
8 changes: 4 additions & 4 deletions player/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,8 @@ impl GlobalPlay for wgc::global::Global {
implicit_context
.as_ref()
.map(|ic| wgc::device::ImplicitPipelineIds {
root_id: Some(ic.root_id),
group_ids: wgc::id::as_option_slice(&ic.group_ids),
root_id: ic.root_id,
group_ids: &ic.group_ids,
});
let (_, error) =
self.device_create_compute_pipeline::<A>(device, &desc, Some(id), implicit_ids);
Expand All @@ -277,8 +277,8 @@ impl GlobalPlay for wgc::global::Global {
implicit_context
.as_ref()
.map(|ic| wgc::device::ImplicitPipelineIds {
root_id: Some(ic.root_id),
group_ids: wgc::id::as_option_slice(&ic.group_ids),
root_id: ic.root_id,
group_ids: &ic.group_ids,
});
let (_, error) =
self.device_create_render_pipeline::<A>(device, &desc, Some(id), implicit_ids);
Expand Down
114 changes: 56 additions & 58 deletions wgpu-core/src/device/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1385,12 +1385,18 @@ impl Global {

let hub = A::hub(self);

let missing_implicit_pipeline_ids =
desc.layout.is_none() && id_in.is_some() && implicit_pipeline_ids.is_none();

let fid = hub.render_pipelines.prepare(id_in);
let implicit_context = implicit_pipeline_ids.map(|ipi| ipi.prepare(hub));

let is_auto_layout = desc.layout.is_none();

let error = 'error: {
if missing_implicit_pipeline_ids {
// TODO: categorize this error as API misuse
break 'error pipeline::ImplicitLayoutError::MissingImplicitPipelineIds.into();
}

let device = match hub.devices.get(device_id) {
Ok(device) => device,
Err(_) => break 'error DeviceError::InvalidDeviceId.into(),
Expand Down Expand Up @@ -1505,23 +1511,18 @@ impl Global {
Err(e) => break 'error e,
};

if is_auto_layout {
// TODO: categorize the errors below as API misuse
let ids = if let Some(ids) = implicit_context.as_ref() {
let group_count = pipeline.layout.bind_group_layouts.len();
if ids.group_ids.len() < group_count {
log::error!(
"Not enough bind group IDs ({}) specified for the implicit layout ({})",
ids.group_ids.len(),
group_count
);
break 'error pipeline::ImplicitLayoutError::MissingIds(group_count as _)
.into();
}
ids
} else {
break 'error pipeline::ImplicitLayoutError::MissingIds(0).into();
};
if let Some(ids) = implicit_context.as_ref() {
let group_count = pipeline.layout.bind_group_layouts.len();
if ids.group_ids.len() < group_count {
log::error!(
"Not enough bind group IDs ({}) specified for the implicit layout ({})",
ids.group_ids.len(),
group_count
);
// TODO: categorize this error as API misuse
break 'error pipeline::ImplicitLayoutError::MissingIds(group_count as _)
.into();
}

let mut pipeline_layout_guard = hub.pipeline_layouts.write();
let mut bgl_guard = hub.bind_group_layouts.write();
Expand Down Expand Up @@ -1552,16 +1553,14 @@ impl Global {

let id = fid.assign_error();

if is_auto_layout {
// We also need to assign errors to the implicit pipeline layout and the
// implicit bind group layouts.
if let Some(ids) = implicit_context {
let mut pipeline_layout_guard = hub.pipeline_layouts.write();
let mut bgl_guard = hub.bind_group_layouts.write();
pipeline_layout_guard.insert_error(ids.root_id);
for bgl_id in ids.group_ids {
bgl_guard.insert_error(bgl_id);
}
// We also need to assign errors to the implicit pipeline layout and the
// implicit bind group layouts.
if let Some(ids) = implicit_context {
let mut pipeline_layout_guard = hub.pipeline_layouts.write();
let mut bgl_guard = hub.bind_group_layouts.write();
pipeline_layout_guard.insert_error(ids.root_id);
for bgl_id in ids.group_ids {
bgl_guard.insert_error(bgl_id);
}
}

Expand Down Expand Up @@ -1629,12 +1628,18 @@ impl Global {

let hub = A::hub(self);

let missing_implicit_pipeline_ids =
desc.layout.is_none() && id_in.is_some() && implicit_pipeline_ids.is_none();

let fid = hub.compute_pipelines.prepare(id_in);
let implicit_context = implicit_pipeline_ids.map(|ipi| ipi.prepare(hub));

let is_auto_layout = desc.layout.is_none();

let error = 'error: {
if missing_implicit_pipeline_ids {
// TODO: categorize this error as API misuse
break 'error pipeline::ImplicitLayoutError::MissingImplicitPipelineIds.into();
}

let device = match hub.devices.get(device_id) {
Ok(device) => device,
Err(_) => break 'error DeviceError::InvalidDeviceId.into(),
Expand Down Expand Up @@ -1703,23 +1708,18 @@ impl Global {
Err(e) => break 'error e,
};

if is_auto_layout {
// TODO: categorize the errors below as API misuse
let ids = if let Some(ids) = implicit_context.as_ref() {
let group_count = pipeline.layout.bind_group_layouts.len();
if ids.group_ids.len() < group_count {
log::error!(
"Not enough bind group IDs ({}) specified for the implicit layout ({})",
ids.group_ids.len(),
group_count
);
break 'error pipeline::ImplicitLayoutError::MissingIds(group_count as _)
.into();
}
ids
} else {
break 'error pipeline::ImplicitLayoutError::MissingIds(0).into();
};
if let Some(ids) = implicit_context.as_ref() {
let group_count = pipeline.layout.bind_group_layouts.len();
if ids.group_ids.len() < group_count {
log::error!(
"Not enough bind group IDs ({}) specified for the implicit layout ({})",
ids.group_ids.len(),
group_count
);
// TODO: categorize this error as API misuse
break 'error pipeline::ImplicitLayoutError::MissingIds(group_count as _)
.into();
}

let mut pipeline_layout_guard = hub.pipeline_layouts.write();
let mut bgl_guard = hub.bind_group_layouts.write();
Expand Down Expand Up @@ -1750,16 +1750,14 @@ impl Global {

let id = fid.assign_error();

if is_auto_layout {
// We also need to assign errors to the implicit pipeline layout and the
// implicit bind group layouts.
if let Some(ids) = implicit_context {
let mut pipeline_layout_guard = hub.pipeline_layouts.write();
let mut bgl_guard = hub.bind_group_layouts.write();
pipeline_layout_guard.insert_error(ids.root_id);
for bgl_id in ids.group_ids {
bgl_guard.insert_error(bgl_id);
}
// We also need to assign errors to the implicit pipeline layout and the
// implicit bind group layouts.
if let Some(ids) = implicit_context {
let mut pipeline_layout_guard = hub.pipeline_layouts.write();
let mut bgl_guard = hub.bind_group_layouts.write();
pipeline_layout_guard.insert_error(ids.root_id);
for bgl_id in ids.group_ids {
bgl_guard.insert_error(bgl_id);
}
}

Expand Down
8 changes: 4 additions & 4 deletions wgpu-core/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -433,18 +433,18 @@ pub struct ImplicitPipelineContext {
}

pub struct ImplicitPipelineIds<'a> {
pub root_id: Option<PipelineLayoutId>,
pub group_ids: &'a [Option<BindGroupLayoutId>],
pub root_id: PipelineLayoutId,
pub group_ids: &'a [BindGroupLayoutId],
}

impl ImplicitPipelineIds<'_> {
fn prepare<A: HalApi>(self, hub: &Hub<A>) -> ImplicitPipelineContext {
ImplicitPipelineContext {
root_id: hub.pipeline_layouts.prepare(self.root_id).into_id(),
root_id: hub.pipeline_layouts.prepare(Some(self.root_id)).into_id(),
group_ids: self
.group_ids
.iter()
.map(|id_in| hub.bind_group_layouts.prepare(*id_in).into_id())
.map(|id_in| hub.bind_group_layouts.prepare(Some(*id_in)).into_id())
.collect(),
}
}
Expand Down
12 changes: 0 additions & 12 deletions wgpu-core/src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,6 @@ impl RawId {
}
}

/// Coerce a slice of identifiers into a slice of optional raw identifiers.
///
/// There's two reasons why we know this is correct:
/// * `Option<T>` is guaranteed to be niche-filled to 0's.
/// * The `T` in `Option<T>` can inhabit any representation except 0's, since
/// its underlying representation is `NonZero*`.
pub fn as_option_slice<T: Marker>(ids: &[Id<T>]) -> &[Option<Id<T>>] {
// SAFETY: Any Id<T> is repr(transparent) over `Option<RawId>`, since both
// are backed by non-zero types.
unsafe { std::slice::from_raw_parts(ids.as_ptr().cast(), ids.len()) }
}

/// An identifier for a wgpu object.
///
/// An `Id<T>` value identifies a value stored in a [`Global`]'s [`Hub`].
Expand Down
2 changes: 2 additions & 0 deletions wgpu-core/src/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ pub type ImplicitBindGroupCount = u8;
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum ImplicitLayoutError {
#[error("The implicit_pipeline_ids arg is required")]
MissingImplicitPipelineIds,
#[error("Missing IDs for deriving {0} bind groups")]
MissingIds(ImplicitBindGroupCount),
#[error("Unable to reflect the shader {0:?} interface")]
Expand Down
18 changes: 2 additions & 16 deletions wgpu/src/backend/wgpu_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1162,13 +1162,6 @@ impl crate::Context for ContextWgpuCore {
})
.collect();

let implicit_pipeline_ids = match desc.layout {
Some(_) => None,
None => Some(wgc::device::ImplicitPipelineIds {
root_id: None,
group_ids: &[None; wgc::MAX_BIND_GROUPS],
}),
};
let descriptor = pipe::RenderPipelineDescriptor {
label: desc.label.map(Borrowed),
layout: desc.layout.map(|l| l.id.into()),
Expand Down Expand Up @@ -1211,7 +1204,7 @@ impl crate::Context for ContextWgpuCore {
*device,
&descriptor,
None,
implicit_pipeline_ids
None,
));
if let Some(cause) = error {
if let wgc::pipeline::CreateRenderPipelineError::Internal { stage, ref error } = cause {
Expand All @@ -1235,13 +1228,6 @@ impl crate::Context for ContextWgpuCore {
) -> (Self::ComputePipelineId, Self::ComputePipelineData) {
use wgc::pipeline as pipe;

let implicit_pipeline_ids = match desc.layout {
Some(_) => None,
None => Some(wgc::device::ImplicitPipelineIds {
root_id: None,
group_ids: &[None; wgc::MAX_BIND_GROUPS],
}),
};
let descriptor = pipe::ComputePipelineDescriptor {
label: desc.label.map(Borrowed),
layout: desc.layout.map(|l| l.id.into()),
Expand All @@ -1261,7 +1247,7 @@ impl crate::Context for ContextWgpuCore {
*device,
&descriptor,
None,
implicit_pipeline_ids
None,
));
if let Some(cause) = error {
if let wgc::pipeline::CreateComputePipelineError::Internal(ref error) = cause {
Expand Down

0 comments on commit 91924fb

Please sign in to comment.