@@ -6,9 +6,9 @@ module HAL:API.CommandList;
66import stl.core;
77import Core;
88import :CommandAllocator; // full definition needed: allocator.vk_command_pool
9- import :RootSignature; // API ::RootSignature::get_vk_pipeline_layout( )
9+ import :RootSignature; // HAL ::RootSignature::ptr (signature parameter types )
1010import :API .Device; // API::Device::get_native_device()
11- import :API .DescriptorHeap; // API::DescriptorHeap::get_vk_set()
11+ import :API .DescriptorHeap; // API::DescriptorHeap::get_device_address() etc.
1212import :API .QueryHeap; // API::QueryHeap::get_native()
1313
1414namespace HAL ::API
@@ -448,28 +448,39 @@ namespace HAL::API
448448 // Re-set topology — dynamic topology state doesn't survive a CB split.
449449 vkCmdSetPrimitiveTopology (vk_cmd, current_topology);
450450
451- // Re-push the staged push-constant block (carries the bindless descriptor
452- // indices the shader reads as _hal_push.sN). 128 bytes = the range declared
453- // by the root signature's VkPushConstantRange.
454- if (current_pipeline_layout != VK_NULL_HANDLE )
455- vkCmdPushConstants (vk_cmd, current_pipeline_layout, VK_SHADER_STAGE_ALL ,
456- 0 , 128 , push_constants.data ());
451+ // Re-push the staged push-data block (carries the bindless descriptor
452+ // indices the shader reads as _hal_push.sN). No pipeline layout required
453+ // with VK_EXT_descriptor_heap — vkCmdPushDataEXT takes a raw host pointer.
454+ {
455+ VkPushDataInfoEXT pi{ VK_STRUCTURE_TYPE_PUSH_DATA_INFO_EXT };
456+ pi.offset = 0 ;
457+ pi.data .address = push_constants.data ();
458+ pi.data .size = push_constants.size () * sizeof (uint32_t );
459+ vkCmdPushDataEXT (vk_cmd, &pi);
460+ }
457461 }
458462
459- void CommandList::flush_descriptor_sets ()
463+ void CommandList::flush_heaps ()
460464 {
461- if (!descriptor_sets_dirty || current_pipeline_layout == VK_NULL_HANDLE ) return ;
462- descriptor_sets_dirty = false ;
463-
464- VkDescriptorSet sets[2 ] = { cbv_srv_uav_set, sampler_set };
465- uint32_t set_count = 0 ;
466- if (sets[0 ] != VK_NULL_HANDLE ) set_count = 1 ;
467- if (sets[1 ] != VK_NULL_HANDLE ) set_count = 2 ;
468- if (set_count == 0 ) return ;
465+ if (!heaps_dirty) return ;
466+ heaps_dirty = false ;
469467
470- // Bind for both graphics and compute so set is available regardless of pipeline type.
471- vkCmdBindDescriptorSets (vk_cmd, VK_PIPELINE_BIND_POINT_GRAPHICS ,
472- current_pipeline_layout, 0 , set_count, sets, 0 , nullptr );
468+ if (cbv_srv_uav_addr != 0 )
469+ {
470+ VkBindHeapInfoEXT bi{ VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT };
471+ bi.heapRange = { cbv_srv_uav_addr, cbv_srv_uav_size };
472+ bi.reservedRangeOffset = 0 ;
473+ bi.reservedRangeSize = cbv_srv_uav_reserved;
474+ vkCmdBindResourceHeapEXT (vk_cmd, &bi);
475+ }
476+ if (sampler_addr != 0 )
477+ {
478+ VkBindHeapInfoEXT bi{ VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT };
479+ bi.heapRange = { sampler_addr, sampler_size };
480+ bi.reservedRangeOffset = 0 ;
481+ bi.reservedRangeSize = sampler_reserved;
482+ vkCmdBindSamplerHeapEXT (vk_cmd, &bi);
483+ }
473484 }
474485
475486 // ---- Pipeline binding ---------------------------------------------------
@@ -493,22 +504,12 @@ namespace HAL::API
493504 }
494505
495506 vkCmdBindPipeline (vk_cmd, bind_point, pipeline->vk_pipeline );
496- flush_descriptor_sets ();
507+ flush_heaps ();
497508 }
498509
499- void CommandList::set_graphics_signature (const HAL ::RootSignature::ptr& sig)
500- {
501- if (!sig) return ;
502- current_pipeline_layout = static_cast <API ::RootSignature&>(*sig).get_vk_pipeline_layout ();
503- descriptor_sets_dirty = true ;
504- }
505-
506- void CommandList::set_compute_signature (const HAL ::RootSignature::ptr& sig)
507- {
508- if (!sig) return ;
509- current_pipeline_layout = static_cast <API ::RootSignature&>(*sig).get_vk_pipeline_layout ();
510- descriptor_sets_dirty = true ;
511- }
510+ // With VK_EXT_descriptor_heap there is no VkPipelineLayout — no-ops.
511+ void CommandList::set_graphics_signature (const HAL ::RootSignature::ptr&) {}
512+ void CommandList::set_compute_signature (const HAL ::RootSignature::ptr&) {}
512513
513514 // ---- Descriptor heap binding -------------------------------------------
514515
@@ -517,9 +518,23 @@ namespace HAL::API
517518 auto * api_cbv = static_cast <API ::DescriptorHeap*>(cbv);
518519 auto * api_sampler = static_cast <API ::DescriptorHeap*>(sampler);
519520
520- cbv_srv_uav_set = api_cbv ? api_cbv->get_vk_set () : VK_NULL_HANDLE ;
521- sampler_set = api_sampler ? api_sampler->get_vk_set () : VK_NULL_HANDLE ;
522- descriptor_sets_dirty = true ;
521+ if (api_cbv)
522+ {
523+ cbv_srv_uav_addr = api_cbv->get_device_address ();
524+ cbv_srv_uav_size = api_cbv->get_total_size ();
525+ cbv_srv_uav_reserved = api_cbv->get_reserved_size ();
526+ }
527+ else { cbv_srv_uav_addr = 0 ; cbv_srv_uav_size = 0 ; cbv_srv_uav_reserved = 0 ; }
528+
529+ if (api_sampler)
530+ {
531+ sampler_addr = api_sampler->get_device_address ();
532+ sampler_size = api_sampler->get_total_size ();
533+ sampler_reserved = api_sampler->get_reserved_size ();
534+ }
535+ else { sampler_addr = 0 ; sampler_size = 0 ; sampler_reserved = 0 ; }
536+
537+ heaps_dirty = true ;
523538 }
524539
525540 // ---- Draw / dispatch ---------------------------------------------------
@@ -531,7 +546,7 @@ namespace HAL::API
531546 ensure_rendering_active ();
532547 if (!in_render_pass) return ; // no RTV set — skip rather than crash validation
533548 reapply_draw_state ();
534- flush_descriptor_sets ();
549+ flush_heaps ();
535550 vkCmdDraw (vk_cmd, vertex_count, instance_count, vertex_offset, instance_offset);
536551 }
537552
@@ -544,24 +559,16 @@ namespace HAL::API
544559 reapply_draw_state ();
545560 if (current_index_buffer != VK_NULL_HANDLE )
546561 vkCmdBindIndexBuffer (vk_cmd, current_index_buffer, current_index_offset, current_index_type);
547- flush_descriptor_sets ();
562+ flush_heaps ();
548563 vkCmdDrawIndexed (vk_cmd, index_count, instance_count,
549564 index_offset, static_cast <int32_t >(vertex_offset), instance_offset);
550565 }
551566
552567 void CommandList::dispatch (ivec3 v)
553568 {
554569 if (vk_cmd == VK_NULL_HANDLE ) return ;
555- // Compute doesn't use a render pass — end any active one first.
556570 end_rendering_if_active ();
557- if (current_pipeline_layout != VK_NULL_HANDLE &&
558- (cbv_srv_uav_set != VK_NULL_HANDLE || sampler_set != VK_NULL_HANDLE ))
559- {
560- VkDescriptorSet sets[2 ] = { cbv_srv_uav_set, sampler_set };
561- uint32_t count = (sampler_set != VK_NULL_HANDLE ) ? 2 : 1 ;
562- vkCmdBindDescriptorSets (vk_cmd, VK_PIPELINE_BIND_POINT_COMPUTE ,
563- current_pipeline_layout, 0 , count, sets, 0 , nullptr );
564- }
571+ flush_heaps ();
565572 vkCmdDispatch (vk_cmd, static_cast <uint32_t >(v.x ),
566573 static_cast <uint32_t >(v.y ),
567574 static_cast <uint32_t >(v.z ));
@@ -638,25 +645,30 @@ namespace HAL::API
638645
639646 void CommandList::graphics_set_constant (UINT slot, UINT offset, UINT value)
640647 {
641- if (vk_cmd == VK_NULL_HANDLE || current_pipeline_layout == VK_NULL_HANDLE ) return ;
642- uint32_t byte_offset = (slot + offset) * sizeof (uint32_t );
643- // Stage so reapply_draw_state() can re-push before each draw — vkCmdPushConstants
644- // does not survive a command-buffer split; without re-pushing, the shader reads 0
645- // for every bindless descriptor index (s4, …) → all bindless reads fail → black UI.
646- if ((slot + offset) < push_constants.size ())
647- push_constants[slot + offset] = value;
648- vkCmdPushConstants (vk_cmd, current_pipeline_layout,
649- VK_SHADER_STAGE_ALL , // must cover all stages in pipeline layout range
650- byte_offset, sizeof (uint32_t ), &value);
648+ if (vk_cmd == VK_NULL_HANDLE ) return ;
649+ uint32_t idx = slot + offset;
650+ // Stage so reapply_draw_state() can re-push before each draw — push data state
651+ // does not survive a command-buffer split; without re-pushing, bindless indices fail.
652+ if (idx < push_constants.size ())
653+ push_constants[idx] = value;
654+ VkPushDataInfoEXT pi{ VK_STRUCTURE_TYPE_PUSH_DATA_INFO_EXT };
655+ pi.offset = idx * sizeof (uint32_t );
656+ pi.data .address = &value;
657+ pi.data .size = sizeof (uint32_t );
658+ vkCmdPushDataEXT (vk_cmd, &pi);
651659 }
652660
653661 void CommandList::compute_set_constant (UINT slot, UINT offset, UINT value)
654662 {
655- if (vk_cmd == VK_NULL_HANDLE || current_pipeline_layout == VK_NULL_HANDLE ) return ;
656- uint32_t byte_offset = (slot + offset) * sizeof (uint32_t );
657- vkCmdPushConstants (vk_cmd, current_pipeline_layout,
658- VK_SHADER_STAGE_ALL , // must cover all stages in pipeline layout range
659- byte_offset, sizeof (uint32_t ), &value);
663+ if (vk_cmd == VK_NULL_HANDLE ) return ;
664+ uint32_t idx = slot + offset;
665+ if (idx < push_constants.size ())
666+ push_constants[idx] = value;
667+ VkPushDataInfoEXT pi{ VK_STRUCTURE_TYPE_PUSH_DATA_INFO_EXT };
668+ pi.offset = idx * sizeof (uint32_t );
669+ pi.data .address = &value;
670+ pi.data .size = sizeof (uint32_t );
671+ vkCmdPushDataEXT (vk_cmd, &pi);
660672 }
661673
662674 // Phase 5: push descriptors for inline CBV binding
0 commit comments