Skip to content

Commit d263b18

Browse files
jamienicoljimblandy
authored andcommitted
[wgpu-core] Create default ExternalTextureParams buffer
In upcoming patches, wgpu will allowing the creation of bind groups with either `TextureView`s or `ExternalTexture`s bound to a `BindingType::ExternalTexture` bind group layout entry. Wgpu-hal and the Naga-generated shaders must be able to handle both of these cases. For external textures they will be provided a uniform buffer containing the external texture's `ExternalTextureParams`. For the texture view case, we must therefore provide the same. To do this, we create a single buffer per device which can be shared between all texture views. We initialize it with the required values in Device::late_init_resources_with_queue(). We know that texture views must have a single RGBA plane, with no rotation or crop-rect. The only thing that can vary between them is their size. We will therefore use the value of [0, 0] in the params buffer to indicate to the shader that it should query the actual texture's size rather than using the value provided in the buffer.
1 parent acfa8c5 commit d263b18

File tree

1 file changed

+101
-1
lines changed

1 file changed

+101
-1
lines changed

wgpu-core/src/device/resource.rs

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,11 @@ pub struct Device {
176176
// Optional so that we can late-initialize this after the queue is created.
177177
pub(crate) timestamp_normalizer:
178178
OnceCellOrLock<crate::timestamp_normalization::TimestampNormalizer>,
179+
/// Uniform buffer containing [`ExternalTextureParams`] with values such
180+
/// that a [`TextureView`] bound to a [`wgt::BindingType::ExternalTexture`]
181+
/// binding point will be rendered correctly. Intended to be used as the
182+
/// [`hal::ExternalTextureBinding::params`] field.
183+
pub(crate) default_external_texture_params_buffer: ManuallyDrop<Box<dyn hal::DynBuffer>>,
179184
// needs to be dropped last
180185
#[cfg(feature = "trace")]
181186
pub(crate) trace: Mutex<Option<trace::Trace>>,
@@ -203,6 +208,10 @@ impl Drop for Device {
203208

204209
// SAFETY: We are in the Drop impl and we don't use self.zero_buffer anymore after this point.
205210
let zero_buffer = unsafe { ManuallyDrop::take(&mut self.zero_buffer) };
211+
// SAFETY: We are in the Drop impl and we don't use
212+
// self.default_external_texture_params_buffer anymore after this point.
213+
let default_external_texture_params_buffer =
214+
unsafe { ManuallyDrop::take(&mut self.default_external_texture_params_buffer) };
206215
// SAFETY: We are in the Drop impl and we don't use self.fence anymore after this point.
207216
let fence = unsafe { ManuallyDrop::take(&mut self.fence.write()) };
208217
if let Some(indirect_validation) = self.indirect_validation.take() {
@@ -213,6 +222,8 @@ impl Drop for Device {
213222
}
214223
unsafe {
215224
self.raw.destroy_buffer(zero_buffer);
225+
self.raw
226+
.destroy_buffer(default_external_texture_params_buffer);
216227
self.raw.destroy_fence(fence);
217228
}
218229
}
@@ -292,6 +303,19 @@ impl Device {
292303
}
293304
.map_err(DeviceError::from_hal)?;
294305

306+
let default_external_texture_params_buffer = unsafe {
307+
raw_device.create_buffer(&hal::BufferDescriptor {
308+
label: hal_label(
309+
Some("(wgpu internal) default external texture params buffer"),
310+
instance_flags,
311+
),
312+
size: size_of::<ExternalTextureParams>() as _,
313+
usage: wgt::BufferUses::COPY_DST | wgt::BufferUses::UNIFORM,
314+
memory_flags: hal::MemoryFlags::empty(),
315+
})
316+
}
317+
.map_err(DeviceError::from_hal)?;
318+
295319
let alignments = adapter.raw.capabilities.alignments.clone();
296320
let downlevel = adapter.raw.capabilities.downlevel.clone();
297321

@@ -317,6 +341,9 @@ impl Device {
317341
adapter: adapter.clone(),
318342
queue: OnceCellOrLock::new(),
319343
zero_buffer: ManuallyDrop::new(zero_buffer),
344+
default_external_texture_params_buffer: ManuallyDrop::new(
345+
default_external_texture_params_buffer,
346+
),
320347
label: desc.label.to_string(),
321348
command_allocator,
322349
command_indices: RwLock::new(
@@ -367,7 +394,78 @@ impl Device {
367394
})
368395
}
369396

370-
pub fn late_init_resources_with_queue(&self) -> Result<(), RequestDeviceError> {
397+
/// Initializes [`Device::default_external_texture_params_buffer`] with
398+
/// required values such that a [`TextureView`] bound to a
399+
/// [`wgt::BindingType::ExternalTexture`] binding point will be rendered
400+
/// correctly.
401+
fn init_default_external_texture_params_buffer(self: &Arc<Self>) -> Result<(), DeviceError> {
402+
let data = ExternalTextureParams {
403+
#[rustfmt::skip]
404+
yuv_conversion_matrix: [
405+
1.0, 0.0, 0.0, 0.0,
406+
0.0, 1.0, 0.0, 0.0,
407+
0.0, 0.0, 1.0, 0.0,
408+
0.0, 0.0, 0.0, 1.0,
409+
],
410+
size: [0, 0],
411+
#[rustfmt::skip]
412+
sample_transform: [
413+
1.0, 0.0,
414+
0.0, 1.0,
415+
0.0, 0.0
416+
],
417+
#[rustfmt::skip]
418+
load_transform: [
419+
1.0, 0.0,
420+
0.0, 1.0,
421+
0.0, 0.0
422+
],
423+
num_planes: 1,
424+
};
425+
let mut staging_buffer =
426+
StagingBuffer::new(self, wgt::BufferSize::new(size_of_val(&data) as _).unwrap())?;
427+
staging_buffer.write(bytemuck::bytes_of(&data));
428+
let staging_buffer = staging_buffer.flush();
429+
430+
let params_buffer = self.default_external_texture_params_buffer.as_ref();
431+
let queue = self.get_queue().unwrap();
432+
let mut pending_writes = queue.pending_writes.lock();
433+
434+
unsafe {
435+
pending_writes
436+
.command_encoder
437+
.transition_buffers(&[hal::BufferBarrier {
438+
buffer: params_buffer,
439+
usage: hal::StateTransition {
440+
from: wgt::BufferUses::MAP_WRITE,
441+
to: wgt::BufferUses::COPY_SRC,
442+
},
443+
}]);
444+
pending_writes.command_encoder.copy_buffer_to_buffer(
445+
staging_buffer.raw(),
446+
params_buffer,
447+
&[hal::BufferCopy {
448+
src_offset: 0,
449+
dst_offset: 0,
450+
size: staging_buffer.size,
451+
}],
452+
);
453+
pending_writes.consume(staging_buffer);
454+
pending_writes
455+
.command_encoder
456+
.transition_buffers(&[hal::BufferBarrier {
457+
buffer: params_buffer,
458+
usage: hal::StateTransition {
459+
from: wgt::BufferUses::COPY_DST,
460+
to: wgt::BufferUses::UNIFORM,
461+
},
462+
}]);
463+
}
464+
465+
Ok(())
466+
}
467+
468+
pub fn late_init_resources_with_queue(self: &Arc<Self>) -> Result<(), RequestDeviceError> {
371469
let queue = self.get_queue().unwrap();
372470

373471
let timestamp_normalizer = crate::timestamp_normalization::TimestampNormalizer::new(
@@ -379,6 +477,8 @@ impl Device {
379477
.set(timestamp_normalizer)
380478
.unwrap_or_else(|_| panic!("Called late_init_resources_with_queue twice"));
381479

480+
self.init_default_external_texture_params_buffer()?;
481+
382482
Ok(())
383483
}
384484

0 commit comments

Comments
 (0)