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::{
|
device::{
|
||||||
bgl, Device, DeviceError, MissingDownlevelFlags, MissingFeatures, SHADER_STAGE_COUNT,
|
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},
|
init_tracker::{BufferInitTrackerAction, TextureInitTrackerAction},
|
||||||
pipeline::{ComputePipeline, RenderPipeline},
|
pipeline::{ComputePipeline, RenderPipeline},
|
||||||
resource::{
|
resource::{
|
||||||
Buffer, DestroyedResourceError, InvalidResourceError, Labeled, MissingBufferUsageError,
|
Buffer, DestroyedResourceError, ExternalTexture, InvalidResourceError, Labeled,
|
||||||
MissingTextureUsageError, RawResourceAccess, ResourceErrorIdent, Sampler, TextureView,
|
MissingBufferUsageError, MissingTextureUsageError, RawResourceAccess, ResourceErrorIdent,
|
||||||
Tlas, TrackingData,
|
Sampler, TextureView, Tlas, TrackingData,
|
||||||
},
|
},
|
||||||
resource_log,
|
resource_log,
|
||||||
snatch::{SnatchGuard, Snatchable},
|
snatch::{SnatchGuard, Snatchable},
|
||||||
@ -594,8 +594,14 @@ impl BindingTypeMaxCountValidator {
|
|||||||
/// cbindgen:ignore
|
/// cbindgen:ignore
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct BindGroupEntry<'a, B = BufferId, S = SamplerId, TV = TextureViewId, TLAS = TlasId>
|
pub struct BindGroupEntry<
|
||||||
where
|
'a,
|
||||||
|
B = BufferId,
|
||||||
|
S = SamplerId,
|
||||||
|
TV = TextureViewId,
|
||||||
|
TLAS = TlasId,
|
||||||
|
ET = ExternalTextureId,
|
||||||
|
> where
|
||||||
[BufferBinding<B>]: ToOwned,
|
[BufferBinding<B>]: ToOwned,
|
||||||
[S]: ToOwned,
|
[S]: ToOwned,
|
||||||
[TV]: ToOwned,
|
[TV]: ToOwned,
|
||||||
@ -608,15 +614,21 @@ where
|
|||||||
pub binding: u32,
|
pub binding: u32,
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde",
|
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
|
/// 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
|
/// cbindgen:ignore
|
||||||
pub type ResolvedBindGroupEntry<'a> =
|
pub type ResolvedBindGroupEntry<'a> = BindGroupEntry<
|
||||||
BindGroupEntry<'a, Arc<Buffer>, Arc<Sampler>, Arc<TextureView>, Arc<Tlas>>;
|
'a,
|
||||||
|
Arc<Buffer>,
|
||||||
|
Arc<Sampler>,
|
||||||
|
Arc<TextureView>,
|
||||||
|
Arc<Tlas>,
|
||||||
|
Arc<ExternalTexture>,
|
||||||
|
>;
|
||||||
|
|
||||||
/// Describes a group of bindings and the resources to be bound.
|
/// Describes a group of bindings and the resources to be bound.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -628,6 +640,7 @@ pub struct BindGroupDescriptor<
|
|||||||
S = SamplerId,
|
S = SamplerId,
|
||||||
TV = TextureViewId,
|
TV = TextureViewId,
|
||||||
TLAS = TlasId,
|
TLAS = TlasId,
|
||||||
|
ET = ExternalTextureId,
|
||||||
> where
|
> where
|
||||||
[BufferBinding<B>]: ToOwned,
|
[BufferBinding<B>]: ToOwned,
|
||||||
[S]: ToOwned,
|
[S]: ToOwned,
|
||||||
@ -635,8 +648,8 @@ pub struct BindGroupDescriptor<
|
|||||||
<[BufferBinding<B>] as ToOwned>::Owned: fmt::Debug,
|
<[BufferBinding<B>] as ToOwned>::Owned: fmt::Debug,
|
||||||
<[S] as ToOwned>::Owned: fmt::Debug,
|
<[S] as ToOwned>::Owned: fmt::Debug,
|
||||||
<[TV] as ToOwned>::Owned: fmt::Debug,
|
<[TV] as ToOwned>::Owned: fmt::Debug,
|
||||||
[BindGroupEntry<'a, B, S, TV, TLAS>]: ToOwned,
|
[BindGroupEntry<'a, B, S, TV, TLAS, ET>]: ToOwned,
|
||||||
<[BindGroupEntry<'a, B, S, TV, TLAS>] as ToOwned>::Owned: fmt::Debug,
|
<[BindGroupEntry<'a, B, S, TV, TLAS, ET>] as ToOwned>::Owned: fmt::Debug,
|
||||||
{
|
{
|
||||||
/// Debug label of the bind group.
|
/// Debug label of the bind group.
|
||||||
///
|
///
|
||||||
@ -647,11 +660,12 @@ pub struct BindGroupDescriptor<
|
|||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde",
|
feature = "serde",
|
||||||
serde(bound(
|
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.
|
/// 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
|
/// cbindgen:ignore
|
||||||
@ -662,6 +676,7 @@ pub type ResolvedBindGroupDescriptor<'a> = BindGroupDescriptor<
|
|||||||
Arc<Sampler>,
|
Arc<Sampler>,
|
||||||
Arc<TextureView>,
|
Arc<TextureView>,
|
||||||
Arc<Tlas>,
|
Arc<Tlas>,
|
||||||
|
Arc<ExternalTexture>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/// Describes a [`BindGroupLayout`].
|
/// 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
|
// They're different enough that it doesn't make sense to share a common type
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub enum BindingResource<'a, B = BufferId, S = SamplerId, TV = TextureViewId, TLAS = TlasId>
|
pub enum BindingResource<
|
||||||
where
|
'a,
|
||||||
|
B = BufferId,
|
||||||
|
S = SamplerId,
|
||||||
|
TV = TextureViewId,
|
||||||
|
TLAS = TlasId,
|
||||||
|
ET = ExternalTextureId,
|
||||||
|
> where
|
||||||
[BufferBinding<B>]: ToOwned,
|
[BufferBinding<B>]: ToOwned,
|
||||||
[S]: ToOwned,
|
[S]: ToOwned,
|
||||||
[TV]: ToOwned,
|
[TV]: ToOwned,
|
||||||
@ -1033,10 +1054,17 @@ where
|
|||||||
)]
|
)]
|
||||||
TextureViewArray(Cow<'a, [TV]>),
|
TextureViewArray(Cow<'a, [TV]>),
|
||||||
AccelerationStructure(TLAS),
|
AccelerationStructure(TLAS),
|
||||||
|
ExternalTexture(ET),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ResolvedBindingResource<'a> =
|
pub type ResolvedBindingResource<'a> = BindingResource<
|
||||||
BindingResource<'a, Arc<Buffer>, Arc<Sampler>, Arc<TextureView>, Arc<Tlas>>;
|
'a,
|
||||||
|
Arc<Buffer>,
|
||||||
|
Arc<Sampler>,
|
||||||
|
Arc<TextureView>,
|
||||||
|
Arc<Tlas>,
|
||||||
|
Arc<ExternalTexture>,
|
||||||
|
>;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Error)]
|
#[derive(Clone, Debug, Error)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|||||||
@ -846,6 +846,7 @@ impl Global {
|
|||||||
sampler_storage: &Storage<Fallible<resource::Sampler>>,
|
sampler_storage: &Storage<Fallible<resource::Sampler>>,
|
||||||
texture_view_storage: &Storage<Fallible<resource::TextureView>>,
|
texture_view_storage: &Storage<Fallible<resource::TextureView>>,
|
||||||
tlas_storage: &Storage<Fallible<resource::Tlas>>,
|
tlas_storage: &Storage<Fallible<resource::Tlas>>,
|
||||||
|
external_texture_storage: &Storage<Fallible<resource::ExternalTexture>>,
|
||||||
) -> Result<ResolvedBindGroupEntry<'a>, binding_model::CreateBindGroupError>
|
) -> Result<ResolvedBindGroupEntry<'a>, binding_model::CreateBindGroupError>
|
||||||
{
|
{
|
||||||
let resolve_buffer = |bb: &BufferBinding| {
|
let resolve_buffer = |bb: &BufferBinding| {
|
||||||
@ -877,6 +878,12 @@ impl Global {
|
|||||||
.get()
|
.get()
|
||||||
.map_err(binding_model::CreateBindGroupError::from)
|
.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 {
|
let resource = match e.resource {
|
||||||
BindingResource::Buffer(ref buffer) => {
|
BindingResource::Buffer(ref buffer) => {
|
||||||
ResolvedBindingResource::Buffer(resolve_buffer(buffer)?)
|
ResolvedBindingResource::Buffer(resolve_buffer(buffer)?)
|
||||||
@ -911,6 +918,9 @@ impl Global {
|
|||||||
BindingResource::AccelerationStructure(ref tlas) => {
|
BindingResource::AccelerationStructure(ref tlas) => {
|
||||||
ResolvedBindingResource::AccelerationStructure(resolve_tlas(tlas)?)
|
ResolvedBindingResource::AccelerationStructure(resolve_tlas(tlas)?)
|
||||||
}
|
}
|
||||||
|
BindingResource::ExternalTexture(ref et) => {
|
||||||
|
ResolvedBindingResource::ExternalTexture(resolve_external_texture(et)?)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Ok(ResolvedBindGroupEntry {
|
Ok(ResolvedBindGroupEntry {
|
||||||
binding: e.binding,
|
binding: e.binding,
|
||||||
@ -923,6 +933,7 @@ impl Global {
|
|||||||
let texture_view_guard = hub.texture_views.read();
|
let texture_view_guard = hub.texture_views.read();
|
||||||
let sampler_guard = hub.samplers.read();
|
let sampler_guard = hub.samplers.read();
|
||||||
let tlas_guard = hub.tlas_s.read();
|
let tlas_guard = hub.tlas_s.read();
|
||||||
|
let external_texture_guard = hub.external_textures.read();
|
||||||
desc.entries
|
desc.entries
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| {
|
.map(|e| {
|
||||||
@ -932,6 +943,7 @@ impl Global {
|
|||||||
&sampler_guard,
|
&sampler_guard,
|
||||||
&texture_view_guard,
|
&texture_view_guard,
|
||||||
&tlas_guard,
|
&tlas_guard,
|
||||||
|
&external_texture_guard,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()
|
.collect::<Result<Vec<_>, _>>()
|
||||||
|
|||||||
@ -76,8 +76,8 @@ pub(crate) struct CommandIndices {
|
|||||||
pub(crate) next_acceleration_structure_build_command_index: u64,
|
pub(crate) next_acceleration_structure_build_command_index: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parameters provided to shaders via a uniform buffer, describing an
|
/// Parameters provided to shaders via a uniform buffer, describing a
|
||||||
/// ExternalTexture resource binding.
|
/// [`binding_model::BindingResource::ExternalTexture`] resource binding.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, bytemuck::Zeroable, bytemuck::Pod)]
|
#[derive(Copy, Clone, bytemuck::Zeroable, bytemuck::Pod)]
|
||||||
pub struct ExternalTextureParams {
|
pub struct ExternalTextureParams {
|
||||||
@ -2612,6 +2612,121 @@ impl Device {
|
|||||||
Ok(tlas.try_raw(snatch_guard)?)
|
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
|
// This function expects the provided bind group layout to be resolved
|
||||||
// (not passing a duplicate) beforehand.
|
// (not passing a duplicate) beforehand.
|
||||||
pub(crate) fn create_bind_group(
|
pub(crate) fn create_bind_group(
|
||||||
@ -2652,6 +2767,7 @@ impl Device {
|
|||||||
let mut hal_samplers = Vec::new();
|
let mut hal_samplers = Vec::new();
|
||||||
let mut hal_textures = Vec::new();
|
let mut hal_textures = Vec::new();
|
||||||
let mut hal_tlas_s = Vec::new();
|
let mut hal_tlas_s = Vec::new();
|
||||||
|
let mut hal_external_textures = Vec::new();
|
||||||
let snatch_guard = self.snatchable_lock.read();
|
let snatch_guard = self.snatchable_lock.read();
|
||||||
for entry in desc.entries.iter() {
|
for entry in desc.entries.iter() {
|
||||||
let binding = entry.binding;
|
let binding = entry.binding;
|
||||||
@ -2718,19 +2834,33 @@ impl Device {
|
|||||||
|
|
||||||
(res_index, num_bindings)
|
(res_index, num_bindings)
|
||||||
}
|
}
|
||||||
Br::TextureView(ref view) => {
|
Br::TextureView(ref view) => match decl.ty {
|
||||||
let tb = self.create_texture_binding(
|
wgt::BindingType::ExternalTexture => {
|
||||||
binding,
|
let et = self.create_external_texture_binding_from_view(
|
||||||
decl,
|
binding,
|
||||||
view,
|
decl,
|
||||||
&mut used,
|
view,
|
||||||
&mut used_texture_ranges,
|
&mut used,
|
||||||
&snatch_guard,
|
&snatch_guard,
|
||||||
)?;
|
)?;
|
||||||
let res_index = hal_textures.len();
|
let res_index = hal_external_textures.len();
|
||||||
hal_textures.push(tb);
|
hal_external_textures.push(et);
|
||||||
(res_index, 1)
|
(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) => {
|
Br::TextureViewArray(ref views) => {
|
||||||
let num_bindings = views.len();
|
let num_bindings = views.len();
|
||||||
Self::check_array_binding(self.features, decl.count, num_bindings)?;
|
Self::check_array_binding(self.features, decl.count, num_bindings)?;
|
||||||
@ -2758,6 +2888,18 @@ impl Device {
|
|||||||
hal_tlas_s.push(tlas);
|
hal_tlas_s.push(tlas);
|
||||||
(res_index, 1)
|
(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 {
|
hal_entries.push(hal::BindGroupEntry {
|
||||||
@ -2783,6 +2925,7 @@ impl Device {
|
|||||||
samplers: &hal_samplers,
|
samplers: &hal_samplers,
|
||||||
textures: &hal_textures,
|
textures: &hal_textures,
|
||||||
acceleration_structures: &hal_tlas_s,
|
acceleration_structures: &hal_tlas_s,
|
||||||
|
external_textures: &hal_external_textures,
|
||||||
};
|
};
|
||||||
let raw = unsafe { self.raw().create_bind_group(&hal_desc) }
|
let raw = unsafe { self.raw().create_bind_group(&hal_desc) }
|
||||||
.map_err(|e| self.handle_hal_error(e))?;
|
.map_err(|e| self.handle_hal_error(e))?;
|
||||||
|
|||||||
@ -241,6 +241,7 @@ impl Dispatch {
|
|||||||
samplers: &[],
|
samplers: &[],
|
||||||
textures: &[],
|
textures: &[],
|
||||||
acceleration_structures: &[],
|
acceleration_structures: &[],
|
||||||
|
external_textures: &[],
|
||||||
};
|
};
|
||||||
let dst_bind_group = unsafe {
|
let dst_bind_group = unsafe {
|
||||||
device
|
device
|
||||||
@ -284,6 +285,7 @@ impl Dispatch {
|
|||||||
samplers: &[],
|
samplers: &[],
|
||||||
textures: &[],
|
textures: &[],
|
||||||
acceleration_structures: &[],
|
acceleration_structures: &[],
|
||||||
|
external_textures: &[],
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
device
|
device
|
||||||
|
|||||||
@ -140,6 +140,7 @@ impl Draw {
|
|||||||
samplers: &[],
|
samplers: &[],
|
||||||
textures: &[],
|
textures: &[],
|
||||||
acceleration_structures: &[],
|
acceleration_structures: &[],
|
||||||
|
external_textures: &[],
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
device
|
device
|
||||||
@ -690,6 +691,7 @@ fn create_buffer_and_bind_group(
|
|||||||
samplers: &[],
|
samplers: &[],
|
||||||
textures: &[],
|
textures: &[],
|
||||||
acceleration_structures: &[],
|
acceleration_structures: &[],
|
||||||
|
external_textures: &[],
|
||||||
};
|
};
|
||||||
let bind_group = unsafe { device.create_bind_group(&bind_group_desc) }?;
|
let bind_group = unsafe { device.create_bind_group(&bind_group_desc) }?;
|
||||||
Ok(BufferPoolEntry { buffer, bind_group })
|
Ok(BufferPoolEntry { buffer, bind_group })
|
||||||
|
|||||||
@ -1801,11 +1801,9 @@ pub type ExternalTextureDescriptor<'a> = wgt::ExternalTextureDescriptor<Label<'a
|
|||||||
pub struct ExternalTexture {
|
pub struct ExternalTexture {
|
||||||
pub(crate) device: Arc<Device>,
|
pub(crate) device: Arc<Device>,
|
||||||
/// Between 1 and 3 (inclusive) planes of texture data.
|
/// Between 1 and 3 (inclusive) planes of texture data.
|
||||||
#[allow(dead_code)]
|
|
||||||
pub(crate) planes: arrayvec::ArrayVec<Arc<TextureView>, 3>,
|
pub(crate) planes: arrayvec::ArrayVec<Arc<TextureView>, 3>,
|
||||||
/// Buffer containing a [`crate::device::resource::ExternalTextureParams`]
|
/// Buffer containing a [`crate::device::resource::ExternalTextureParams`]
|
||||||
/// describing the external texture.
|
/// describing the external texture.
|
||||||
#[allow(dead_code)]
|
|
||||||
pub(crate) params: Arc<Buffer>,
|
pub(crate) params: Arc<Buffer>,
|
||||||
/// The `label` from the descriptor used to create the resource.
|
/// The `label` from the descriptor used to create the resource.
|
||||||
pub(crate) label: String,
|
pub(crate) label: String,
|
||||||
|
|||||||
@ -289,6 +289,7 @@ impl TimestampNormalizer {
|
|||||||
samplers: &[],
|
samplers: &[],
|
||||||
textures: &[],
|
textures: &[],
|
||||||
acceleration_structures: &[],
|
acceleration_structures: &[],
|
||||||
|
external_textures: &[],
|
||||||
entries: &[hal::BindGroupEntry {
|
entries: &[hal::BindGroupEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
resource_index: 0,
|
resource_index: 0,
|
||||||
|
|||||||
@ -438,6 +438,7 @@ impl<T: ResourceUses> fmt::Display for InvalidUse<T> {
|
|||||||
pub(crate) struct BindGroupStates {
|
pub(crate) struct BindGroupStates {
|
||||||
pub buffers: BufferBindGroupState,
|
pub buffers: BufferBindGroupState,
|
||||||
pub views: TextureViewBindGroupState,
|
pub views: TextureViewBindGroupState,
|
||||||
|
pub external_textures: StatelessTracker<resource::ExternalTexture>,
|
||||||
pub samplers: StatelessTracker<resource::Sampler>,
|
pub samplers: StatelessTracker<resource::Sampler>,
|
||||||
pub acceleration_structures: StatelessTracker<resource::Tlas>,
|
pub acceleration_structures: StatelessTracker<resource::Tlas>,
|
||||||
}
|
}
|
||||||
@ -447,6 +448,7 @@ impl BindGroupStates {
|
|||||||
Self {
|
Self {
|
||||||
buffers: BufferBindGroupState::new(),
|
buffers: BufferBindGroupState::new(),
|
||||||
views: TextureViewBindGroupState::new(),
|
views: TextureViewBindGroupState::new(),
|
||||||
|
external_textures: StatelessTracker::new(),
|
||||||
samplers: StatelessTracker::new(),
|
samplers: StatelessTracker::new(),
|
||||||
acceleration_structures: StatelessTracker::new(),
|
acceleration_structures: StatelessTracker::new(),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -464,6 +464,7 @@ impl<A: hal::Api> Example<A> {
|
|||||||
samplers: &[&sampler],
|
samplers: &[&sampler],
|
||||||
textures: &[texture_binding],
|
textures: &[texture_binding],
|
||||||
acceleration_structures: &[],
|
acceleration_structures: &[],
|
||||||
|
external_textures: &[],
|
||||||
entries: &[
|
entries: &[
|
||||||
hal::BindGroupEntry {
|
hal::BindGroupEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
@ -499,6 +500,7 @@ impl<A: hal::Api> Example<A> {
|
|||||||
samplers: &[],
|
samplers: &[],
|
||||||
textures: &[],
|
textures: &[],
|
||||||
acceleration_structures: &[],
|
acceleration_structures: &[],
|
||||||
|
external_textures: &[],
|
||||||
entries: &[hal::BindGroupEntry {
|
entries: &[hal::BindGroupEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
resource_index: 0,
|
resource_index: 0,
|
||||||
|
|||||||
@ -622,6 +622,7 @@ impl<A: hal::Api> Example<A> {
|
|||||||
samplers: &[],
|
samplers: &[],
|
||||||
textures: &[texture_binding],
|
textures: &[texture_binding],
|
||||||
acceleration_structures: &[&tlas],
|
acceleration_structures: &[&tlas],
|
||||||
|
external_textures: &[],
|
||||||
entries: &[
|
entries: &[
|
||||||
hal::BindGroupEntry {
|
hal::BindGroupEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
|
|||||||
@ -345,6 +345,11 @@ impl<D: Device + DynResource> DynDevice for D {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|a| a.expect_downcast_ref())
|
.map(|a| a.expect_downcast_ref())
|
||||||
.collect();
|
.collect();
|
||||||
|
let external_textures: Vec<_> = desc
|
||||||
|
.external_textures
|
||||||
|
.iter()
|
||||||
|
.map(|et| et.clone().expect_downcast())
|
||||||
|
.collect();
|
||||||
|
|
||||||
let desc = BindGroupDescriptor {
|
let desc = BindGroupDescriptor {
|
||||||
label: desc.label.to_owned(),
|
label: desc.label.to_owned(),
|
||||||
@ -354,6 +359,7 @@ impl<D: Device + DynResource> DynDevice for D {
|
|||||||
textures: &textures,
|
textures: &textures,
|
||||||
entries: desc.entries,
|
entries: desc.entries,
|
||||||
acceleration_structures: &acceleration_structures,
|
acceleration_structures: &acceleration_structures,
|
||||||
|
external_textures: &external_textures,
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe { D::create_bind_group(self, &desc) }
|
unsafe { D::create_bind_group(self, &desc) }
|
||||||
|
|||||||
@ -23,7 +23,8 @@ use wgt::WasmNotSendSync;
|
|||||||
use crate::{
|
use crate::{
|
||||||
AccelerationStructureAABBs, AccelerationStructureEntries, AccelerationStructureInstances,
|
AccelerationStructureAABBs, AccelerationStructureEntries, AccelerationStructureInstances,
|
||||||
AccelerationStructureTriangleIndices, AccelerationStructureTriangleTransform,
|
AccelerationStructureTriangleIndices, AccelerationStructureTriangleTransform,
|
||||||
AccelerationStructureTriangles, BufferBinding, ProgrammableStage, TextureBinding,
|
AccelerationStructureTriangles, BufferBinding, ExternalTextureBinding, ProgrammableStage,
|
||||||
|
TextureBinding,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Base trait for all resources, allows downcasting via [`Any`].
|
/// 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> {
|
impl<'a> ProgrammableStage<'a, dyn DynShaderModule> {
|
||||||
fn expect_downcast<T: DynShaderModule>(self) -> ProgrammableStage<'a, T> {
|
fn expect_downcast<T: DynShaderModule>(self) -> ProgrammableStage<'a, T> {
|
||||||
ProgrammableStage {
|
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
|
/// cbindgen:ignore
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct BindGroupEntry {
|
pub struct BindGroupEntry {
|
||||||
@ -2178,6 +2195,7 @@ pub struct BindGroupDescriptor<
|
|||||||
pub textures: &'a [TextureBinding<'a, T>],
|
pub textures: &'a [TextureBinding<'a, T>],
|
||||||
pub entries: &'a [BindGroupEntry],
|
pub entries: &'a [BindGroupEntry],
|
||||||
pub acceleration_structures: &'a [&'a A],
|
pub acceleration_structures: &'a [&'a A],
|
||||||
|
pub external_textures: &'a [ExternalTextureBinding<'a, B, T>],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[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
|
/// 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.
|
/// safety section of `build_acceleration_structures_unsafe_tlas` and so undefined behavior occurs.
|
||||||
AccelerationStructure(&'a Tlas),
|
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)]
|
#[cfg(send_sync)]
|
||||||
static_assertions::assert_impl_all!(BindingResource<'_>: Send, Sync);
|
static_assertions::assert_impl_all!(BindingResource<'_>: Send, Sync);
|
||||||
|
|||||||
@ -2017,6 +2017,9 @@ impl dispatch::DeviceInterface for WebDevice {
|
|||||||
crate::BindingResource::AccelerationStructure(_) => {
|
crate::BindingResource::AccelerationStructure(_) => {
|
||||||
unimplemented!("Raytracing not implemented for web")
|
unimplemented!("Raytracing not implemented for web")
|
||||||
}
|
}
|
||||||
|
crate::BindingResource::ExternalTexture(_) => {
|
||||||
|
unimplemented!("ExternalTexture not implemented for web")
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
webgpu_sys::GpuBindGroupEntry::new(binding.binding, &mapped_resource)
|
webgpu_sys::GpuBindGroupEntry::new(binding.binding, &mapped_resource)
|
||||||
|
|||||||
@ -1190,6 +1190,9 @@ impl dispatch::DeviceInterface for CoreDevice {
|
|||||||
acceleration_structure.inner.as_core().id,
|
acceleration_structure.inner.as_core().id,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
BindingResource::ExternalTexture(external_texture) => {
|
||||||
|
bm::BindingResource::ExternalTexture(external_texture.inner.as_core().id)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user