Skip to content

Add Queue::submit() for command buffer submission#1057

Open
MarijnS95 wants to merge 2 commits intollvm:mainfrom
Traverse-Research:queue-submit
Open

Add Queue::submit() for command buffer submission#1057
MarijnS95 wants to merge 2 commits intollvm:mainfrom
Traverse-Research:queue-submit

Conversation

@MarijnS95
Copy link
Copy Markdown
Contributor

@MarijnS95 MarijnS95 commented Apr 2, 2026

Depends on #1033

Move command buffer submission logic from each backend's Device into Queue::submit(), which takes ownership of the command buffers. For now it blocks internally until completion; a TODO marks that it will return a Fence once the Fence abstraction from PR #1007 is available.

  • Metal: commit() + waitUntilCompleted()
  • Vulkan: vkEndCommandBuffer() + vkQueueSubmit() with temporary fence + vkWaitForFences()
  • DX12: CmdList::Close() + ExecuteCommandLists() + Queue::Signal()/Fence::SetEventOnCompletion() wait

VulkanQueue now stores a VkDevice handle (with a TODO for lifetime management) so it can create/destroy fences independently.

Co-Authored-By: Claude Opus 4.6 (1M context) [email protected]

MarijnS95 and others added 2 commits April 2, 2026 16:15
Command buffer creation and management was previously spread across
each backend's executeProgram() with no shared interface, making it
impossible to manage command buffers from backend-agnostic code. This
introduces a CommandBuffer base class on Device so that higher-level
code can create and pass around command buffers without knowing the
backend. Per-object allocator/pool ownership also prepares for future
async execution where multiple command buffers may be in-flight with
independent lifetimes.

- DX: DXCommandBuffer owns Allocator, CmdList, Fence, Event
- VK: VKCommandBuffer owns CmdPool, CmdBuffer; each submission
  creates a new CommandBuffer for independent lifetime management
- MTL: MTLCommandBuffer wraps MTL::CommandBuffer

Device::createCommandBuffer() returns Expected<unique_ptr<CommandBuffer>>
with a default "not supported" implementation.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Move command buffer submission logic from each backend's Device into
Queue::submit(), which takes ownership of the command buffers. For now
it blocks internally until completion; a TODO marks that it will return
a Fence once the Fence abstraction from PR llvm#1007 is available.

- Metal: commit() + waitUntilCompleted()
- Vulkan: vkEndCommandBuffer() + vkQueueSubmit() with temporary fence + vkWaitForFences()
- DX12: CmdList::Close() + ExecuteCommandLists() + Queue::Signal()/Fence::SetEventOnCompletion() wait

VulkanQueue now stores a VkDevice handle (with a TODO for lifetime
management) so it can create/destroy fences independently.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Comment on lines +327 to +332
ComPtr<ID3D12Fence> Fence;
#ifdef _WIN32
HANDLE Event = nullptr;
#else // WSL
int Event = -1;
#endif
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's merge the abstract fence PR (#1007 ) first and then use it here instead of using API specific fences/timeline semaphores.

@MarijnS95
Copy link
Copy Markdown
Contributor Author

Looks like this needs some more TLC, from CI:

# | D3D: ID3D12CommandAllocator::LUCPrepareForDestruction: A command allocator 0x00000136B8B29B10:'Unnamed ID3D12CommandAllocator Object' is being reset before previous executions associated with the allocator have completed.
# | Exception Code: 0x0000087A
...
# | #11 0x00007ffa7089c1e4 (C:\WINDOWS\SYSTEM32\D3D12SDKLayers.dll+0x3c1e4)
# | #12 0x00007ff6c4440df9 `anonymous namespace'::DXCommandBuffer::~DXCommandBuffer E:\actions-runner\_work\offload-test-suite\offload-test-suite\OffloadTest\lib\API\DX\Device.cpp:364:0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants