Skip to content

Commit a6647da

Browse files
committed
refactor(rendering): use D3D11WgpuInterop for NV12 zero-copy texture import
1 parent 9aee219 commit a6647da

File tree

1 file changed

+73
-89
lines changed

1 file changed

+73
-89
lines changed

crates/rendering/src/yuv_converter.rs

Lines changed: 73 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::iosurface_texture::{
99
use cidre::cv;
1010

1111
#[cfg(target_os = "windows")]
12-
use crate::d3d_texture::D3DTextureError;
12+
use crate::d3d_texture::{D3D11WgpuInterop, D3DTextureError};
1313

1414
#[cfg(target_os = "windows")]
1515
use windows::Win32::Graphics::Direct3D11::{
@@ -420,6 +420,8 @@ pub struct YuvToRgbaConverter {
420420
d3d11_staging_height: u32,
421421
#[cfg(target_os = "windows")]
422422
zero_copy_failed: bool,
423+
#[cfg(target_os = "windows")]
424+
d3d11_interop: D3D11WgpuInterop,
423425
}
424426

425427
impl YuvToRgbaConverter {
@@ -476,6 +478,8 @@ impl YuvToRgbaConverter {
476478
d3d11_staging_height: 0,
477479
#[cfg(target_os = "windows")]
478480
zero_copy_failed: false,
481+
#[cfg(target_os = "windows")]
482+
d3d11_interop: D3D11WgpuInterop::new(),
479483
}
480484
}
481485

@@ -1230,109 +1234,88 @@ impl YuvToRgbaConverter {
12301234
width: u32,
12311235
height: u32,
12321236
) -> Result<&wgpu::TextureView, YuvConversionError> {
1237+
if self.zero_copy_failed {
1238+
return Err(YuvConversionError::D3D11Error(
1239+
"D3D11 zero-copy path disabled after prior failure".to_string(),
1240+
));
1241+
}
1242+
12331243
let (effective_width, effective_height, _downscaled) =
12341244
validate_dimensions(width, height, self.gpu_max_texture_size)?;
12351245
self.ensure_texture_size(device, effective_width, effective_height);
12361246

1237-
use crate::d3d_texture::import_d3d11_texture_to_wgpu;
1238-
12391247
self.swap_output_buffer();
12401248

1241-
let y_import_result = import_d3d11_texture_to_wgpu(
1242-
device,
1243-
y_handle,
1244-
wgpu::TextureFormat::R8Unorm,
1245-
width,
1246-
height,
1247-
Some("D3D11 Y Plane Zero-Copy"),
1248-
);
1249-
1250-
let uv_import_result = import_d3d11_texture_to_wgpu(
1251-
device,
1252-
uv_handle,
1253-
wgpu::TextureFormat::Rg8Unorm,
1254-
width / 2,
1255-
height / 2,
1256-
Some("D3D11 UV Plane Zero-Copy"),
1257-
);
1258-
1259-
match (y_import_result, uv_import_result) {
1260-
(Ok(y_wgpu_texture), Ok(uv_wgpu_texture)) => {
1261-
tracing::debug!(
1262-
width = width,
1263-
height = height,
1264-
y_handle = y_handle.0 as usize,
1265-
uv_handle = uv_handle.0 as usize,
1266-
"Zero-copy D3D11 texture import starting"
1267-
);
1249+
let (y_wgpu_texture, uv_wgpu_texture) = match self
1250+
.d3d11_interop
1251+
.import_nv12_planes(device, y_handle, uv_handle, width, height)
1252+
{
1253+
Ok(textures) => textures,
1254+
Err(err) => {
12681255
tracing::debug!(
1256+
error = %err,
12691257
width = width,
12701258
height = height,
1271-
"Zero-copy D3D11 texture import succeeded"
1259+
"Zero-copy D3D11 texture import failed, disabling zero-copy path"
12721260
);
1261+
self.zero_copy_failed = true;
1262+
self.d3d11_interop.invalidate();
1263+
return Err(err.into());
1264+
}
1265+
};
12731266

1274-
let y_view = y_wgpu_texture.create_view(&Default::default());
1275-
let uv_view = uv_wgpu_texture.create_view(&Default::default());
1267+
tracing::debug!(
1268+
width = width,
1269+
height = height,
1270+
y_handle = y_handle.0 as usize,
1271+
uv_handle = uv_handle.0 as usize,
1272+
"Zero-copy D3D11 texture import starting"
1273+
);
1274+
tracing::debug!(
1275+
width = width,
1276+
height = height,
1277+
"Zero-copy D3D11 texture import succeeded"
1278+
);
12761279

1277-
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
1278-
label: Some("NV12 D3D11 Zero-Copy Converter Bind Group"),
1279-
layout: &self.pipelines.nv12_bind_group_layout,
1280-
entries: &[
1281-
wgpu::BindGroupEntry {
1282-
binding: 0,
1283-
resource: wgpu::BindingResource::TextureView(&y_view),
1284-
},
1285-
wgpu::BindGroupEntry {
1286-
binding: 1,
1287-
resource: wgpu::BindingResource::TextureView(&uv_view),
1288-
},
1289-
wgpu::BindGroupEntry {
1290-
binding: 2,
1291-
resource: wgpu::BindingResource::TextureView(
1292-
self.current_output_view(),
1293-
),
1294-
},
1295-
],
1296-
});
1297-
1298-
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
1299-
label: Some("NV12 D3D11 Zero-Copy Conversion Encoder"),
1300-
});
1301-
1302-
{
1303-
let mut compute_pass =
1304-
encoder.begin_compute_pass(&wgpu::ComputePassDescriptor {
1305-
label: Some("NV12 D3D11 Zero-Copy Conversion Pass"),
1306-
..Default::default()
1307-
});
1308-
compute_pass.set_pipeline(&self.pipelines.nv12_pipeline);
1309-
compute_pass.set_bind_group(0, &bind_group, &[]);
1310-
compute_pass.dispatch_workgroups(width.div_ceil(8), height.div_ceil(8), 1);
1311-
}
1280+
let y_view = y_wgpu_texture.create_view(&Default::default());
1281+
let uv_view = uv_wgpu_texture.create_view(&Default::default());
13121282

1313-
queue.submit(std::iter::once(encoder.finish()));
1283+
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
1284+
label: Some("NV12 D3D11 Zero-Copy Converter Bind Group"),
1285+
layout: &self.pipelines.nv12_bind_group_layout,
1286+
entries: &[
1287+
wgpu::BindGroupEntry {
1288+
binding: 0,
1289+
resource: wgpu::BindingResource::TextureView(&y_view),
1290+
},
1291+
wgpu::BindGroupEntry {
1292+
binding: 1,
1293+
resource: wgpu::BindingResource::TextureView(&uv_view),
1294+
},
1295+
wgpu::BindGroupEntry {
1296+
binding: 2,
1297+
resource: wgpu::BindingResource::TextureView(self.current_output_view()),
1298+
},
1299+
],
1300+
});
13141301

1315-
Ok(self.current_output_view())
1316-
}
1317-
(Err(y_err), _) => {
1318-
tracing::debug!(
1319-
error = %y_err,
1320-
width = width,
1321-
height = height,
1322-
"Zero-copy D3D11 Y texture import failed, returning error"
1323-
);
1324-
Err(y_err.into())
1325-
}
1326-
(_, Err(uv_err)) => {
1327-
tracing::debug!(
1328-
error = %uv_err,
1329-
width = width,
1330-
height = height,
1331-
"Zero-copy D3D11 UV texture import failed, returning error"
1332-
);
1333-
Err(uv_err.into())
1334-
}
1302+
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
1303+
label: Some("NV12 D3D11 Zero-Copy Conversion Encoder"),
1304+
});
1305+
1306+
{
1307+
let mut compute_pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor {
1308+
label: Some("NV12 D3D11 Zero-Copy Conversion Pass"),
1309+
..Default::default()
1310+
});
1311+
compute_pass.set_pipeline(&self.pipelines.nv12_pipeline);
1312+
compute_pass.set_bind_group(0, &bind_group, &[]);
1313+
compute_pass.dispatch_workgroups(width.div_ceil(8), height.div_ceil(8), 1);
13351314
}
1315+
1316+
queue.submit(std::iter::once(encoder.finish()));
1317+
1318+
Ok(self.current_output_view())
13361319
}
13371320

13381321
#[cfg(target_os = "windows")]
@@ -1406,6 +1389,7 @@ impl YuvToRgbaConverter {
14061389
#[cfg(target_os = "windows")]
14071390
pub fn reset_zero_copy_state(&mut self) {
14081391
self.zero_copy_failed = false;
1392+
self.d3d11_interop.invalidate();
14091393
}
14101394

14111395
#[allow(clippy::too_many_arguments)]

0 commit comments

Comments
 (0)