@@ -9,7 +9,7 @@ use crate::iosurface_texture::{
99use 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" ) ]
1515use 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
425427impl 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