@@ -60,8 +60,12 @@ impl super::Device {
6060 auxil:: dxgi:: exception:: register_exception_handler ( ) ;
6161 }
6262
63- let mem_allocator =
64- suballocation:: Allocator :: new ( & raw , memory_hints, memory_budget_thresholds) ?;
63+ let mem_allocator = suballocation:: Allocator :: new (
64+ & raw ,
65+ memory_hints,
66+ & private_caps,
67+ memory_budget_thresholds,
68+ ) ?;
6569
6670 let idle_fence: Direct3D12 :: ID3D12Fence = unsafe {
6771 profiling:: scope!( "ID3D12Device::CreateFence" ) ;
@@ -2293,26 +2297,17 @@ impl crate::Device for super::Device {
22932297 ) ,
22942298 } ;
22952299
2296- if let Some ( threshold) = self
2300+ // Query heaps allocate device memory outside the pool machinery, so we
2301+ // gate them through the allocator's budget probe. Assume each query is
2302+ // 256 bytes. On an AMD W6800 with driver version 32.0.12030.9, occlusion
2303+ // and pipeline statistics are 256 bytes, timestamp is 8.
2304+ let query_bytes = ( desc. count as u64 ) . saturating_mul ( 256 ) ;
2305+ let tracked_query_bytes = self
22972306 . mem_allocator
2298- . memory_budget_thresholds
2299- . for_resource_creation
2300- {
2301- let info = self
2302- . shared
2303- . adapter
2304- . query_video_memory_info ( Dxgi :: DXGI_MEMORY_SEGMENT_GROUP_LOCAL ) ?;
2305-
2306- // Assume each query is 256 bytes.
2307- // On an AMD W6800 with driver version 32.0.12030.9, occlusion and pipeline statistics are 256, timestamp is 8.
2308-
2309- if info. CurrentUsage + desc. count as u64 * 256 >= info. Budget / 100 * threshold as u64 {
2310- return Err ( crate :: DeviceError :: OutOfMemory ) ;
2311- }
2312- }
2307+ . add_external_allocation ( & self . shared . adapter , query_bytes) ?;
23132308
23142309 let mut raw = None :: < Direct3D12 :: ID3D12QueryHeap > ;
2315- unsafe {
2310+ let create_result = unsafe {
23162311 self . raw . CreateQueryHeap (
23172312 & Direct3D12 :: D3D12_QUERY_HEAP_DESC {
23182313 Type : heap_ty,
@@ -2322,20 +2317,39 @@ impl crate::Device for super::Device {
23222317 & mut raw,
23232318 )
23242319 }
2325- . into_device_result ( "Query heap creation" ) ?;
2320+ . into_device_result ( "Query heap creation" ) ;
2321+ if let Err ( error) = create_result {
2322+ self . mem_allocator
2323+ . remove_external_allocation ( tracked_query_bytes) ;
2324+ return Err ( error) ;
2325+ }
23262326
2327- let raw = raw. ok_or ( crate :: DeviceError :: Unexpected ) ?;
2327+ let Some ( raw) = raw else {
2328+ self . mem_allocator
2329+ . remove_external_allocation ( tracked_query_bytes) ;
2330+ return Err ( crate :: DeviceError :: Unexpected ) ;
2331+ } ;
23282332
23292333 if let Some ( label) = desc. label {
2330- raw. set_name ( label) ?;
2334+ if let Err ( error) = raw. set_name ( label) {
2335+ self . mem_allocator
2336+ . remove_external_allocation ( tracked_query_bytes) ;
2337+ return Err ( error) ;
2338+ }
23312339 }
23322340
23332341 self . counters . query_sets . add ( 1 ) ;
23342342
2335- Ok ( super :: QuerySet { raw, raw_ty } )
2343+ Ok ( super :: QuerySet {
2344+ raw,
2345+ raw_ty,
2346+ tracked_query_bytes,
2347+ } )
23362348 }
23372349
2338- unsafe fn destroy_query_set ( & self , _set : super :: QuerySet ) {
2350+ unsafe fn destroy_query_set ( & self , set : super :: QuerySet ) {
2351+ self . mem_allocator
2352+ . remove_external_allocation ( set. tracked_query_bytes ) ;
23392353 self . counters . query_sets . sub ( 1 ) ;
23402354 }
23412355
0 commit comments