mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
[wgpu-core] Allow creation of bind groups containing external textures
Adds a `BindingResource` variant for external textures. In core's create_bind_group() implementation, allow binding either external textures or texture views to `BindingType::ExternalTexture` layout entries. In either case, provide HAL with a `hal::ExternalTextureBinding`, consisting of 3 `hal::TextureBinding`s and a `hal::BufferBinding`. In the texture view case we use the device's default params buffer for the buffer. When there are fewer than 3 planes we can simply repeat an existing plane multiple times - the contents of the params buffer will ensure the shader only accesses the correct number of planes anyway. Track the view or external texture in `BindGroupStates` to ensure they remain alive whilst required. And finally, add the corresponding API to wgpu, with an implementation for the wgpu-core backend.
This commit is contained in:
parent
d263b1875d
commit
7087f0c01f
@ -21,13 +21,13 @@ use crate::{
|
||||
device::{
|
||||
bgl, Device, DeviceError, MissingDownlevelFlags, MissingFeatures, SHADER_STAGE_COUNT,
|
||||
},
|
||||
id::{BindGroupLayoutId, BufferId, SamplerId, TextureViewId, TlasId},
|
||||
id::{BindGroupLayoutId, BufferId, ExternalTextureId, SamplerId, TextureViewId, TlasId},
|
||||
init_tracker::{BufferInitTrackerAction, TextureInitTrackerAction},
|
||||
pipeline::{ComputePipeline, RenderPipeline},
|
||||
resource::{
|
||||
Buffer, DestroyedResourceError, InvalidResourceError, Labeled, MissingBufferUsageError,
|
||||
MissingTextureUsageError, RawResourceAccess, ResourceErrorIdent, Sampler, TextureView,
|
||||
Tlas, TrackingData,
|
||||
Buffer, DestroyedResourceError, ExternalTexture, InvalidResourceError, Labeled,
|
||||
MissingBufferUsageError, MissingTextureUsageError, RawResourceAccess, ResourceErrorIdent,
|
||||
Sampler, TextureView, Tlas, TrackingData,
|
||||
},
|
||||
resource_log,
|
||||
snatch::{SnatchGuard, Snatchable},
|
||||
@ -594,8 +594,14 @@ impl BindingTypeMaxCountValidator {
|
||||
/// cbindgen:ignore
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct BindGroupEntry<'a, B = BufferId, S = SamplerId, TV = TextureViewId, TLAS = TlasId>
|
||||
where
|
||||
pub struct BindGroupEntry<
|
||||
'a,
|
||||
B = BufferId,
|
||||
S = SamplerId,
|
||||
TV = TextureViewId,
|
||||
TLAS = TlasId,
|
||||
ET = ExternalTextureId,
|
||||
> where
|
||||
[BufferBinding<B>]: ToOwned,
|
||||
[S]: ToOwned,
|
||||
[TV]: ToOwned,
|
||||
@ -608,15 +614,21 @@ where
|
||||
pub binding: u32,
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
serde(bound(deserialize = "BindingResource<'a, B, S, TV, TLAS>: Deserialize<'de>"))
|
||||
serde(bound(deserialize = "BindingResource<'a, B, S, TV, TLAS, ET>: Deserialize<'de>"))
|
||||
)]
|
||||
/// Resource to attach to the binding
|
||||
pub resource: BindingResource<'a, B, S, TV, TLAS>,
|
||||
pub resource: BindingResource<'a, B, S, TV, TLAS, ET>,
|
||||
}
|
||||
|
||||
/// cbindgen:ignore
|
||||
pub type ResolvedBindGroupEntry<'a> =
|
||||
BindGroupEntry<'a, Arc<Buffer>, Arc<Sampler>, Arc<TextureView>, Arc<Tlas>>;
|
||||
pub type ResolvedBindGroupEntry<'a> = BindGroupEntry<
|
||||
'a,
|
||||
Arc<Buffer>,
|
||||
Arc<Sampler>,
|
||||
Arc<TextureView>,
|
||||
Arc<Tlas>,
|
||||
Arc<ExternalTexture>,
|
||||
>;
|
||||
|
||||
/// Describes a group of bindings and the resources to be bound.
|
||||
#[derive(Clone, Debug)]
|
||||
@ -628,6 +640,7 @@ pub struct BindGroupDescriptor<
|
||||
S = SamplerId,
|
||||
TV = TextureViewId,
|
||||
TLAS = TlasId,
|
||||
ET = ExternalTextureId,
|
||||
> where
|
||||
[BufferBinding<B>]: ToOwned,
|
||||
[S]: ToOwned,
|
||||
@ -635,8 +648,8 @@ pub struct BindGroupDescriptor<
|
||||
<[BufferBinding<B>] as ToOwned>::Owned: fmt::Debug,
|
||||
<[S] as ToOwned>::Owned: fmt::Debug,
|
||||
<[TV] as ToOwned>::Owned: fmt::Debug,
|
||||
[BindGroupEntry<'a, B, S, TV, TLAS>]: ToOwned,
|
||||
<[BindGroupEntry<'a, B, S, TV, TLAS>] as ToOwned>::Owned: fmt::Debug,
|
||||
[BindGroupEntry<'a, B, S, TV, TLAS, ET>]: ToOwned,
|
||||
<[BindGroupEntry<'a, B, S, TV, TLAS, ET>] as ToOwned>::Owned: fmt::Debug,
|
||||
{
|
||||
/// Debug label of the bind group.
|
||||
///
|
||||
@ -647,11 +660,12 @@ pub struct BindGroupDescriptor<
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
serde(bound(
|
||||
deserialize = "<[BindGroupEntry<'a, B, S, TV, TLAS>] as ToOwned>::Owned: Deserialize<'de>"
|
||||
deserialize = "<[BindGroupEntry<'a, B, S, TV, TLAS, ET>] as ToOwned>::Owned: Deserialize<'de>"
|
||||
))
|
||||
)]
|
||||
/// The resources to bind to this bind group.
|
||||
pub entries: Cow<'a, [BindGroupEntry<'a, B, S, TV, TLAS>]>,
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub entries: Cow<'a, [BindGroupEntry<'a, B, S, TV, TLAS, ET>]>,
|
||||
}
|
||||
|
||||
/// cbindgen:ignore
|
||||
@ -662,6 +676,7 @@ pub type ResolvedBindGroupDescriptor<'a> = BindGroupDescriptor<
|
||||
Arc<Sampler>,
|
||||
Arc<TextureView>,
|
||||
Arc<Tlas>,
|
||||
Arc<ExternalTexture>,
|
||||
>;
|
||||
|
||||
/// Describes a [`BindGroupLayout`].
|
||||
@ -1005,8 +1020,14 @@ pub type ResolvedBufferBinding = BufferBinding<Arc<Buffer>>;
|
||||
// They're different enough that it doesn't make sense to share a common type
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum BindingResource<'a, B = BufferId, S = SamplerId, TV = TextureViewId, TLAS = TlasId>
|
||||
where
|
||||
pub enum BindingResource<
|
||||
'a,
|
||||
B = BufferId,
|
||||
S = SamplerId,
|
||||
TV = TextureViewId,
|
||||
TLAS = TlasId,
|
||||
ET = ExternalTextureId,
|
||||
> where
|
||||
[BufferBinding<B>]: ToOwned,
|
||||
[S]: ToOwned,
|
||||
[TV]: ToOwned,
|
||||
@ -1033,10 +1054,17 @@ where
|
||||
)]
|
||||
TextureViewArray(Cow<'a, [TV]>),
|
||||
AccelerationStructure(TLAS),
|
||||
ExternalTexture(ET),
|
||||
}
|
||||
|
||||
pub type ResolvedBindingResource<'a> =
|
||||
BindingResource<'a, Arc<Buffer>, Arc<Sampler>, Arc<TextureView>, Arc<Tlas>>;
|
||||
pub type ResolvedBindingResource<'a> = BindingResource<
|
||||
'a,
|
||||
Arc<Buffer>,
|
||||
Arc<Sampler>,
|
||||
Arc<TextureView>,
|
||||
Arc<Tlas>,
|
||||
Arc<ExternalTexture>,
|
||||
>;
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[non_exhaustive]
|
||||
|
||||
@ -846,6 +846,7 @@ impl Global {
|
||||
sampler_storage: &Storage<Fallible<resource::Sampler>>,
|
||||
texture_view_storage: &Storage<Fallible<resource::TextureView>>,
|
||||
tlas_storage: &Storage<Fallible<resource::Tlas>>,
|
||||
external_texture_storage: &Storage<Fallible<resource::ExternalTexture>>,
|
||||
) -> Result<ResolvedBindGroupEntry<'a>, binding_model::CreateBindGroupError>
|
||||
{
|
||||
let resolve_buffer = |bb: &BufferBinding| {
|
||||
@ -877,6 +878,12 @@ impl Global {
|
||||
.get()
|
||||
.map_err(binding_model::CreateBindGroupError::from)
|
||||
};
|
||||
let resolve_external_texture = |id: &id::ExternalTextureId| {
|
||||
external_texture_storage
|
||||
.get(*id)
|
||||
.get()
|
||||
.map_err(binding_model::CreateBindGroupError::from)
|
||||
};
|
||||
let resource = match e.resource {
|
||||
BindingResource::Buffer(ref buffer) => {
|
||||
ResolvedBindingResource::Buffer(resolve_buffer(buffer)?)
|
||||
@ -911,6 +918,9 @@ impl Global {
|
||||
BindingResource::AccelerationStructure(ref tlas) => {
|
||||
ResolvedBindingResource::AccelerationStructure(resolve_tlas(tlas)?)
|
||||
}
|
||||
BindingResource::ExternalTexture(ref et) => {
|
||||
ResolvedBindingResource::ExternalTexture(resolve_external_texture(et)?)
|
||||
}
|
||||
};
|
||||
Ok(ResolvedBindGroupEntry {
|
||||
binding: e.binding,
|
||||
@ -923,6 +933,7 @@ impl Global {
|
||||
let texture_view_guard = hub.texture_views.read();
|
||||
let sampler_guard = hub.samplers.read();
|
||||
let tlas_guard = hub.tlas_s.read();
|
||||
let external_texture_guard = hub.external_textures.read();
|
||||
desc.entries
|
||||
.iter()
|
||||
.map(|e| {
|
||||
@ -932,6 +943,7 @@ impl Global {
|
||||
&sampler_guard,
|
||||
&texture_view_guard,
|
||||
&tlas_guard,
|
||||
&external_texture_guard,
|
||||
)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
|
||||
@ -76,8 +76,8 @@ pub(crate) struct CommandIndices {
|
||||
pub(crate) next_acceleration_structure_build_command_index: u64,
|
||||
}
|
||||
|
||||
/// Parameters provided to shaders via a uniform buffer, describing an
|
||||
/// ExternalTexture resource binding.
|
||||
/// Parameters provided to shaders via a uniform buffer, describing a
|
||||
/// [`binding_model::BindingResource::ExternalTexture`] resource binding.
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, bytemuck::Zeroable, bytemuck::Pod)]
|
||||
pub struct ExternalTextureParams {
|
||||
@ -2612,6 +2612,121 @@ impl Device {
|
||||
Ok(tlas.try_raw(snatch_guard)?)
|
||||
}
|
||||
|
||||
fn create_external_texture_binding<'a>(
|
||||
&'a self,
|
||||
binding: u32,
|
||||
decl: &wgt::BindGroupLayoutEntry,
|
||||
external_texture: &'a Arc<ExternalTexture>,
|
||||
used: &mut BindGroupStates,
|
||||
snatch_guard: &'a SnatchGuard,
|
||||
) -> Result<
|
||||
hal::ExternalTextureBinding<'a, dyn hal::DynBuffer, dyn hal::DynTextureView>,
|
||||
binding_model::CreateBindGroupError,
|
||||
> {
|
||||
use crate::binding_model::CreateBindGroupError as Error;
|
||||
|
||||
external_texture.same_device(self)?;
|
||||
|
||||
used.external_textures
|
||||
.insert_single(external_texture.clone());
|
||||
|
||||
match decl.ty {
|
||||
wgt::BindingType::ExternalTexture => {}
|
||||
_ => {
|
||||
return Err(Error::WrongBindingType {
|
||||
binding,
|
||||
actual: decl.ty,
|
||||
expected: "ExternalTexture",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let planes = (0..3)
|
||||
.map(|i| {
|
||||
// We always need 3 bindings. If we have fewer than 3 planes
|
||||
// just bind plane 0 multiple times. The shader will only
|
||||
// sample from valid planes anyway.
|
||||
let plane = external_texture
|
||||
.planes
|
||||
.get(i)
|
||||
.unwrap_or(&external_texture.planes[0]);
|
||||
let internal_use = wgt::TextureUses::RESOURCE;
|
||||
used.views.insert_single(plane.clone(), internal_use);
|
||||
let view = plane.try_raw(snatch_guard)?;
|
||||
Ok(hal::TextureBinding {
|
||||
view,
|
||||
usage: internal_use,
|
||||
})
|
||||
})
|
||||
// We can remove this intermediate Vec by using
|
||||
// array::try_from_fn() above, once it stabilizes.
|
||||
.collect::<Result<Vec<_>, Error>>()?;
|
||||
let planes = planes.try_into().unwrap();
|
||||
|
||||
used.buffers
|
||||
.insert_single(external_texture.params.clone(), wgt::BufferUses::UNIFORM);
|
||||
let params = hal::BufferBinding {
|
||||
buffer: external_texture.params.try_raw(snatch_guard)?,
|
||||
offset: 0,
|
||||
size: wgt::BufferSize::new(external_texture.params.size),
|
||||
};
|
||||
|
||||
Ok(hal::ExternalTextureBinding { planes, params })
|
||||
}
|
||||
|
||||
fn create_external_texture_binding_from_view<'a>(
|
||||
&'a self,
|
||||
binding: u32,
|
||||
decl: &wgt::BindGroupLayoutEntry,
|
||||
view: &'a Arc<TextureView>,
|
||||
used: &mut BindGroupStates,
|
||||
snatch_guard: &'a SnatchGuard,
|
||||
) -> Result<
|
||||
hal::ExternalTextureBinding<'a, dyn hal::DynBuffer, dyn hal::DynTextureView>,
|
||||
binding_model::CreateBindGroupError,
|
||||
> {
|
||||
use crate::binding_model::CreateBindGroupError as Error;
|
||||
|
||||
view.same_device(self)?;
|
||||
|
||||
let internal_use = self.texture_use_parameters(binding, decl, view, "SampledTexture")?;
|
||||
used.views.insert_single(view.clone(), internal_use);
|
||||
|
||||
match decl.ty {
|
||||
wgt::BindingType::ExternalTexture => {}
|
||||
_ => {
|
||||
return Err(Error::WrongBindingType {
|
||||
binding,
|
||||
actual: decl.ty,
|
||||
expected: "ExternalTexture",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// We need 3 bindings, so just repeat the same texture view 3 times.
|
||||
let planes = [
|
||||
hal::TextureBinding {
|
||||
view: view.try_raw(snatch_guard)?,
|
||||
usage: internal_use,
|
||||
},
|
||||
hal::TextureBinding {
|
||||
view: view.try_raw(snatch_guard)?,
|
||||
usage: internal_use,
|
||||
},
|
||||
hal::TextureBinding {
|
||||
view: view.try_raw(snatch_guard)?,
|
||||
usage: internal_use,
|
||||
},
|
||||
];
|
||||
let params = hal::BufferBinding {
|
||||
buffer: self.default_external_texture_params_buffer.as_ref(),
|
||||
offset: 0,
|
||||
size: None,
|
||||
};
|
||||
|
||||
Ok(hal::ExternalTextureBinding { planes, params })
|
||||
}
|
||||
|
||||
// This function expects the provided bind group layout to be resolved
|
||||
// (not passing a duplicate) beforehand.
|
||||
pub(crate) fn create_bind_group(
|
||||
@ -2652,6 +2767,7 @@ impl Device {
|
||||
let mut hal_samplers = Vec::new();
|
||||
let mut hal_textures = Vec::new();
|
||||
let mut hal_tlas_s = Vec::new();
|
||||
let mut hal_external_textures = Vec::new();
|
||||
let snatch_guard = self.snatchable_lock.read();
|
||||
for entry in desc.entries.iter() {
|
||||
let binding = entry.binding;
|
||||
@ -2718,19 +2834,33 @@ impl Device {
|
||||
|
||||
(res_index, num_bindings)
|
||||
}
|
||||
Br::TextureView(ref view) => {
|
||||
let tb = self.create_texture_binding(
|
||||
binding,
|
||||
decl,
|
||||
view,
|
||||
&mut used,
|
||||
&mut used_texture_ranges,
|
||||
&snatch_guard,
|
||||
)?;
|
||||
let res_index = hal_textures.len();
|
||||
hal_textures.push(tb);
|
||||
(res_index, 1)
|
||||
}
|
||||
Br::TextureView(ref view) => match decl.ty {
|
||||
wgt::BindingType::ExternalTexture => {
|
||||
let et = self.create_external_texture_binding_from_view(
|
||||
binding,
|
||||
decl,
|
||||
view,
|
||||
&mut used,
|
||||
&snatch_guard,
|
||||
)?;
|
||||
let res_index = hal_external_textures.len();
|
||||
hal_external_textures.push(et);
|
||||
(res_index, 1)
|
||||
}
|
||||
_ => {
|
||||
let tb = self.create_texture_binding(
|
||||
binding,
|
||||
decl,
|
||||
view,
|
||||
&mut used,
|
||||
&mut used_texture_ranges,
|
||||
&snatch_guard,
|
||||
)?;
|
||||
let res_index = hal_textures.len();
|
||||
hal_textures.push(tb);
|
||||
(res_index, 1)
|
||||
}
|
||||
},
|
||||
Br::TextureViewArray(ref views) => {
|
||||
let num_bindings = views.len();
|
||||
Self::check_array_binding(self.features, decl.count, num_bindings)?;
|
||||
@ -2758,6 +2888,18 @@ impl Device {
|
||||
hal_tlas_s.push(tlas);
|
||||
(res_index, 1)
|
||||
}
|
||||
Br::ExternalTexture(ref et) => {
|
||||
let et = self.create_external_texture_binding(
|
||||
binding,
|
||||
decl,
|
||||
et,
|
||||
&mut used,
|
||||
&snatch_guard,
|
||||
)?;
|
||||
let res_index = hal_external_textures.len();
|
||||
hal_external_textures.push(et);
|
||||
(res_index, 1)
|
||||
}
|
||||
};
|
||||
|
||||
hal_entries.push(hal::BindGroupEntry {
|
||||
@ -2783,6 +2925,7 @@ impl Device {
|
||||
samplers: &hal_samplers,
|
||||
textures: &hal_textures,
|
||||
acceleration_structures: &hal_tlas_s,
|
||||
external_textures: &hal_external_textures,
|
||||
};
|
||||
let raw = unsafe { self.raw().create_bind_group(&hal_desc) }
|
||||
.map_err(|e| self.handle_hal_error(e))?;
|
||||
|
||||
@ -241,6 +241,7 @@ impl Dispatch {
|
||||
samplers: &[],
|
||||
textures: &[],
|
||||
acceleration_structures: &[],
|
||||
external_textures: &[],
|
||||
};
|
||||
let dst_bind_group = unsafe {
|
||||
device
|
||||
@ -284,6 +285,7 @@ impl Dispatch {
|
||||
samplers: &[],
|
||||
textures: &[],
|
||||
acceleration_structures: &[],
|
||||
external_textures: &[],
|
||||
};
|
||||
unsafe {
|
||||
device
|
||||
|
||||
@ -140,6 +140,7 @@ impl Draw {
|
||||
samplers: &[],
|
||||
textures: &[],
|
||||
acceleration_structures: &[],
|
||||
external_textures: &[],
|
||||
};
|
||||
unsafe {
|
||||
device
|
||||
@ -690,6 +691,7 @@ fn create_buffer_and_bind_group(
|
||||
samplers: &[],
|
||||
textures: &[],
|
||||
acceleration_structures: &[],
|
||||
external_textures: &[],
|
||||
};
|
||||
let bind_group = unsafe { device.create_bind_group(&bind_group_desc) }?;
|
||||
Ok(BufferPoolEntry { buffer, bind_group })
|
||||
|
||||
@ -1801,11 +1801,9 @@ pub type ExternalTextureDescriptor<'a> = wgt::ExternalTextureDescriptor<Label<'a
|
||||
pub struct ExternalTexture {
|
||||
pub(crate) device: Arc<Device>,
|
||||
/// Between 1 and 3 (inclusive) planes of texture data.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) planes: arrayvec::ArrayVec<Arc<TextureView>, 3>,
|
||||
/// Buffer containing a [`crate::device::resource::ExternalTextureParams`]
|
||||
/// describing the external texture.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) params: Arc<Buffer>,
|
||||
/// The `label` from the descriptor used to create the resource.
|
||||
pub(crate) label: String,
|
||||
|
||||
@ -289,6 +289,7 @@ impl TimestampNormalizer {
|
||||
samplers: &[],
|
||||
textures: &[],
|
||||
acceleration_structures: &[],
|
||||
external_textures: &[],
|
||||
entries: &[hal::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource_index: 0,
|
||||
|
||||
@ -438,6 +438,7 @@ impl<T: ResourceUses> fmt::Display for InvalidUse<T> {
|
||||
pub(crate) struct BindGroupStates {
|
||||
pub buffers: BufferBindGroupState,
|
||||
pub views: TextureViewBindGroupState,
|
||||
pub external_textures: StatelessTracker<resource::ExternalTexture>,
|
||||
pub samplers: StatelessTracker<resource::Sampler>,
|
||||
pub acceleration_structures: StatelessTracker<resource::Tlas>,
|
||||
}
|
||||
@ -447,6 +448,7 @@ impl BindGroupStates {
|
||||
Self {
|
||||
buffers: BufferBindGroupState::new(),
|
||||
views: TextureViewBindGroupState::new(),
|
||||
external_textures: StatelessTracker::new(),
|
||||
samplers: StatelessTracker::new(),
|
||||
acceleration_structures: StatelessTracker::new(),
|
||||
}
|
||||
|
||||
@ -464,6 +464,7 @@ impl<A: hal::Api> Example<A> {
|
||||
samplers: &[&sampler],
|
||||
textures: &[texture_binding],
|
||||
acceleration_structures: &[],
|
||||
external_textures: &[],
|
||||
entries: &[
|
||||
hal::BindGroupEntry {
|
||||
binding: 0,
|
||||
@ -499,6 +500,7 @@ impl<A: hal::Api> Example<A> {
|
||||
samplers: &[],
|
||||
textures: &[],
|
||||
acceleration_structures: &[],
|
||||
external_textures: &[],
|
||||
entries: &[hal::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource_index: 0,
|
||||
|
||||
@ -622,6 +622,7 @@ impl<A: hal::Api> Example<A> {
|
||||
samplers: &[],
|
||||
textures: &[texture_binding],
|
||||
acceleration_structures: &[&tlas],
|
||||
external_textures: &[],
|
||||
entries: &[
|
||||
hal::BindGroupEntry {
|
||||
binding: 0,
|
||||
|
||||
@ -345,6 +345,11 @@ impl<D: Device + DynResource> DynDevice for D {
|
||||
.iter()
|
||||
.map(|a| a.expect_downcast_ref())
|
||||
.collect();
|
||||
let external_textures: Vec<_> = desc
|
||||
.external_textures
|
||||
.iter()
|
||||
.map(|et| et.clone().expect_downcast())
|
||||
.collect();
|
||||
|
||||
let desc = BindGroupDescriptor {
|
||||
label: desc.label.to_owned(),
|
||||
@ -354,6 +359,7 @@ impl<D: Device + DynResource> DynDevice for D {
|
||||
textures: &textures,
|
||||
entries: desc.entries,
|
||||
acceleration_structures: &acceleration_structures,
|
||||
external_textures: &external_textures,
|
||||
};
|
||||
|
||||
unsafe { D::create_bind_group(self, &desc) }
|
||||
|
||||
@ -23,7 +23,8 @@ use wgt::WasmNotSendSync;
|
||||
use crate::{
|
||||
AccelerationStructureAABBs, AccelerationStructureEntries, AccelerationStructureInstances,
|
||||
AccelerationStructureTriangleIndices, AccelerationStructureTriangleTransform,
|
||||
AccelerationStructureTriangles, BufferBinding, ProgrammableStage, TextureBinding,
|
||||
AccelerationStructureTriangles, BufferBinding, ExternalTextureBinding, ProgrammableStage,
|
||||
TextureBinding,
|
||||
};
|
||||
|
||||
/// Base trait for all resources, allows downcasting via [`Any`].
|
||||
@ -143,6 +144,16 @@ impl<'a> TextureBinding<'a, dyn DynTextureView> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ExternalTextureBinding<'a, dyn DynBuffer, dyn DynTextureView> {
|
||||
pub fn expect_downcast<B: DynBuffer, T: DynTextureView>(
|
||||
self,
|
||||
) -> ExternalTextureBinding<'a, B, T> {
|
||||
let planes = self.planes.map(|plane| plane.expect_downcast());
|
||||
let params = self.params.expect_downcast();
|
||||
ExternalTextureBinding { planes, params }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ProgrammableStage<'a, dyn DynShaderModule> {
|
||||
fn expect_downcast<T: DynShaderModule>(self) -> ProgrammableStage<'a, T> {
|
||||
ProgrammableStage {
|
||||
|
||||
@ -2145,6 +2145,23 @@ impl<'a, T: DynTextureView + ?Sized> Clone for TextureBinding<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ExternalTextureBinding<'a, B: DynBuffer + ?Sized, T: DynTextureView + ?Sized> {
|
||||
pub planes: [TextureBinding<'a, T>; 3],
|
||||
pub params: BufferBinding<'a, B>,
|
||||
}
|
||||
|
||||
impl<'a, B: DynBuffer + ?Sized, T: DynTextureView + ?Sized> Clone
|
||||
for ExternalTextureBinding<'a, B, T>
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
ExternalTextureBinding {
|
||||
planes: self.planes.clone(),
|
||||
params: self.params.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// cbindgen:ignore
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BindGroupEntry {
|
||||
@ -2178,6 +2195,7 @@ pub struct BindGroupDescriptor<
|
||||
pub textures: &'a [TextureBinding<'a, T>],
|
||||
pub entries: &'a [BindGroupEntry],
|
||||
pub acceleration_structures: &'a [&'a A],
|
||||
pub external_textures: &'a [ExternalTextureBinding<'a, B, T>],
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
||||
@ -81,6 +81,12 @@ pub enum BindingResource<'a> {
|
||||
/// built using `build_acceleration_structures` a validation error is generated otherwise this is a part of the
|
||||
/// safety section of `build_acceleration_structures_unsafe_tlas` and so undefined behavior occurs.
|
||||
AccelerationStructure(&'a Tlas),
|
||||
/// Binding is backed by an external texture.
|
||||
///
|
||||
/// [`Features::EXTERNAL_TEXTURE`] must be supported to use this feature.
|
||||
///
|
||||
/// Corresponds to [`wgt::BindingType::ExternalTexture`].
|
||||
ExternalTexture(&'a ExternalTexture),
|
||||
}
|
||||
#[cfg(send_sync)]
|
||||
static_assertions::assert_impl_all!(BindingResource<'_>: Send, Sync);
|
||||
|
||||
@ -2017,6 +2017,9 @@ impl dispatch::DeviceInterface for WebDevice {
|
||||
crate::BindingResource::AccelerationStructure(_) => {
|
||||
unimplemented!("Raytracing not implemented for web")
|
||||
}
|
||||
crate::BindingResource::ExternalTexture(_) => {
|
||||
unimplemented!("ExternalTexture not implemented for web")
|
||||
}
|
||||
};
|
||||
|
||||
webgpu_sys::GpuBindGroupEntry::new(binding.binding, &mapped_resource)
|
||||
|
||||
@ -1190,6 +1190,9 @@ impl dispatch::DeviceInterface for CoreDevice {
|
||||
acceleration_structure.inner.as_core().id,
|
||||
)
|
||||
}
|
||||
BindingResource::ExternalTexture(external_texture) => {
|
||||
bm::BindingResource::ExternalTexture(external_texture.inner.as_core().id)
|
||||
}
|
||||
},
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user