@@ -28,17 +28,6 @@ internal enum CompositePipelineBlendMode
2828/// </summary>
2929internal sealed unsafe class WebGPUFlushContext : IDisposable
3030{
31- private bool disposed ;
32- private bool ownsTargetTexture ;
33- private bool ownsTargetView ;
34- private readonly WebGPUDeviceHandle deviceHandle ;
35- private readonly WebGPUQueueHandle queueHandle ;
36- private readonly WebGPUTextureHandle targetTextureHandle ;
37- private readonly WebGPUTextureViewHandle targetTextureViewHandle ;
38- private WebGPUHandle . HandleReference ? deviceReference ;
39- private WebGPUHandle . HandleReference ? queueReference ;
40- private WebGPUHandle . HandleReference ? targetTextureReference ;
41- private WebGPUHandle . HandleReference ? targetTextureViewReference ;
4231 private readonly List < nint > transientBindGroups = [ ] ;
4332 private readonly List < nint > transientBuffers = [ ] ;
4433 private readonly List < nint > transientTextureViews = [ ] ;
@@ -49,6 +38,8 @@ internal sealed unsafe class WebGPUFlushContext : IDisposable
4938 // Handles are released when this flush context is disposed.
5039 private readonly Dictionary < Image , nint > cachedSourceTextureViews = new ( ReferenceEqualityComparer . Instance ) ;
5140
41+ private bool disposed ;
42+
5243 private WebGPUFlushContext (
5344 WebGPU api ,
5445 Wgpu wgpuExtension ,
@@ -63,10 +54,10 @@ private WebGPUFlushContext(
6354 {
6455 this . Api = api ;
6556 this . WgpuExtension = wgpuExtension ;
66- this . deviceHandle = deviceHandle ;
67- this . queueHandle = queueHandle ;
68- this . targetTextureHandle = targetTextureHandle ;
69- this . targetTextureViewHandle = targetTextureViewHandle ;
57+ this . DeviceHandle = deviceHandle ;
58+ this . QueueHandle = queueHandle ;
59+ this . TargetTextureHandle = targetTextureHandle ;
60+ this . TargetTextureViewHandle = targetTextureViewHandle ;
7061 this . TargetBounds = targetBounds ;
7162 this . TextureFormat = textureFormat ;
7263 this . MemoryAllocator = memoryAllocator ;
@@ -84,14 +75,32 @@ private WebGPUFlushContext(
8475 public WebGPU Api { get ; }
8576
8677 /// <summary>
87- /// Gets the device used to create and execute GPU resources.
78+ /// Gets the safe handle for the device used to create and execute GPU resources.
79+ /// Acquire a scoped reference with <see cref="WebGPUHandle.AcquireReference"/> for the
80+ /// duration of any native call that uses the underlying pointer.
81+ /// </summary>
82+ public WebGPUDeviceHandle DeviceHandle { get ; }
83+
84+ /// <summary>
85+ /// Gets the safe handle for the queue used to submit GPU work.
86+ /// Acquire a scoped reference with <see cref="WebGPUHandle.AcquireReference"/> for the
87+ /// duration of any native call that uses the underlying pointer.
8888 /// </summary>
89- public Device * Device { get ; private set ; }
89+ public WebGPUQueueHandle QueueHandle { get ; }
9090
9191 /// <summary>
92- /// Gets the queue used to submit GPU work.
92+ /// Gets the safe handle for the target texture receiving render/composite output.
93+ /// Acquire a scoped reference with <see cref="WebGPUHandle.AcquireReference"/> for the
94+ /// duration of any native call that uses the underlying pointer.
9395 /// </summary>
94- public Queue * Queue { get ; private set ; }
96+ public WebGPUTextureHandle TargetTextureHandle { get ; }
97+
98+ /// <summary>
99+ /// Gets the safe handle for the texture view used when binding the target texture.
100+ /// Acquire a scoped reference with <see cref="WebGPUHandle.AcquireReference"/> for the
101+ /// duration of any native call that uses the underlying pointer.
102+ /// </summary>
103+ public WebGPUTextureViewHandle TargetTextureViewHandle { get ; }
95104
96105 /// <summary>
97106 /// Gets the target bounds for this flush context.
@@ -113,16 +122,6 @@ private WebGPUFlushContext(
113122 /// </summary>
114123 public WebGPURuntime . DeviceSharedState DeviceState { get ; }
115124
116- /// <summary>
117- /// Gets the target texture receiving render/composite output.
118- /// </summary>
119- public Texture * TargetTexture { get ; private set ; }
120-
121- /// <summary>
122- /// Gets the texture view used when binding the target texture.
123- /// </summary>
124- public TextureView * TargetView { get ; private set ; }
125-
126125 /// <summary>
127126 /// Gets the shared instance-data buffer used for parameter uploads.
128127 /// </summary>
@@ -198,7 +197,7 @@ private WebGPUFlushContext(
198197 return null ;
199198 }
200199
201- WebGPUFlushContext context = new (
200+ return new WebGPUFlushContext (
202201 api ,
203202 WebGPURuntime . GetWgpuExtension ( ) ,
204203 nativeCapability . DeviceHandle ,
@@ -209,21 +208,6 @@ private WebGPUFlushContext(
209208 textureFormat ,
210209 memoryAllocator ,
211210 deviceState ) ;
212- try
213- {
214- if ( ! context . InitializeNativeTarget ( ) )
215- {
216- context . Dispose ( ) ;
217- return null ;
218- }
219- }
220- catch
221- {
222- context . Dispose ( ) ;
223- throw ;
224- }
225-
226- return context ;
227211 }
228212
229213 /// <summary>
@@ -253,7 +237,8 @@ public bool EnsureInstanceBufferCapacity(nuint requiredBytes, nuint minimumCapac
253237 Size = targetSize
254238 } ;
255239
256- this . InstanceBuffer = this . Api . DeviceCreateBuffer ( this . Device , in descriptor ) ;
240+ using WebGPUHandle . HandleReference deviceReference = this . DeviceHandle . AcquireReference ( ) ;
241+ this . InstanceBuffer = this . Api . DeviceCreateBuffer ( ( Device * ) deviceReference . Handle , in descriptor ) ;
257242 if ( this . InstanceBuffer is null )
258243 {
259244 return false ;
@@ -275,7 +260,8 @@ public bool EnsureCommandEncoder()
275260 }
276261
277262 CommandEncoderDescriptor descriptor = default ;
278- this . CommandEncoder = this . Api . DeviceCreateCommandEncoder ( this . Device , in descriptor ) ;
263+ using WebGPUHandle . HandleReference deviceReference = this . DeviceHandle . AcquireReference ( ) ;
264+ this . CommandEncoder = this . Api . DeviceCreateCommandEncoder ( ( Device * ) deviceReference . Handle , in descriptor ) ;
279265 return this . CommandEncoder is not null ;
280266 }
281267
@@ -469,16 +455,6 @@ public void Dispose()
469455
470456 this . InstanceBufferWriteOffset = 0 ;
471457
472- if ( this . ownsTargetView && this . TargetView is not null )
473- {
474- this . Api . TextureViewRelease ( this . TargetView ) ;
475- }
476-
477- if ( this . ownsTargetTexture && this . TargetTexture is not null )
478- {
479- this . Api . TextureRelease ( this . TargetTexture ) ;
480- }
481-
482458 for ( int i = 0 ; i < this . transientBindGroups . Count ; i ++ )
483459 {
484460 this . Api . BindGroupRelease ( ( BindGroup * ) this . transientBindGroups [ i ] ) ;
@@ -507,52 +483,9 @@ public void Dispose()
507483 // Cache entries point to transient texture views that are released above.
508484 this . cachedSourceTextureViews . Clear ( ) ;
509485
510- this . TargetView = null ;
511- this . TargetTexture = null ;
512- this . ownsTargetView = false ;
513- this . ownsTargetTexture = false ;
514- this . DisposeNativeHandleReferences ( ) ;
515-
516486 this . disposed = true ;
517487 }
518488
519- /// <summary>
520- /// Adopts the texture and texture view provided by a native WebGPU surface capability.
521- /// </summary>
522- /// <returns><see langword="true"/> when all required native handles were acquired successfully; otherwise, <see langword="false"/>.</returns>
523- private bool InitializeNativeTarget ( )
524- {
525- // The flush context caches raw native pointers and reuses them across the full flush,
526- // so each safe handle must stay add-ref'd until the context is disposed. These fields are
527- // assigned immediately so Dispose can unwind partial initialization if a later acquire throws.
528- this . deviceReference = this . deviceHandle . AcquireReference ( ) ;
529- this . queueReference = this . queueHandle . AcquireReference ( ) ;
530- this . targetTextureReference = this . targetTextureHandle . AcquireReference ( ) ;
531- this . targetTextureViewReference = this . targetTextureViewHandle . AcquireReference ( ) ;
532- this . Device = ( Device * ) this . deviceReference . Value . Handle ;
533- this . Queue = ( Queue * ) this . queueReference . Value . Handle ;
534- this . TargetTexture = ( Texture * ) this . targetTextureReference . Value . Handle ;
535- this . TargetView = ( TextureView * ) this . targetTextureViewReference . Value . Handle ;
536- this . ownsTargetTexture = false ;
537- this . ownsTargetView = false ;
538- return true ;
539- }
540-
541- /// <summary>
542- /// Releases the scoped safe-handle references that keep the cached raw pointers valid for this flush.
543- /// </summary>
544- private void DisposeNativeHandleReferences ( )
545- {
546- this . targetTextureViewReference ? . Dispose ( ) ;
547- this . targetTextureViewReference = null ;
548- this . targetTextureReference ? . Dispose ( ) ;
549- this . targetTextureReference = null ;
550- this . queueReference ? . Dispose ( ) ;
551- this . queueReference = null ;
552- this . deviceReference ? . Dispose ( ) ;
553- this . deviceReference = null ;
554- }
555-
556489 /// <summary>
557490 /// Tries to obtain a native WebGPU surface capability from the canvas frame.
558491 /// </summary>
0 commit comments