Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend ID3D12DXVKInteropDevice into ID3D12DXVKInteropDevice1 to add VkCommandBuffer interop #2053

Conversation

liam-middlebrook
Copy link
Contributor

Add functionality for grabbing the VkCommandBuffer which is internal to a ID3D12CommandList object. This allows for applications to do interop using DX12 synchronization primitives but enqueue work onto queues which are otherwise not exposed through traditional DX12 APIs.

This will be used as a basis for dxvk-nvapi to create a DX12 offering of the VK_NV_optical_flow functionality. Tagging @jp7677 and @Saancreed from that project as any feedback received here will be relevant to a follow-up pull request I will be making there.

Two open points of discussion:

Interface Naming

Should this be called ID3D12DXVKInteropDevice1 ? It has a high overlap in functionality with ID3D12DXVKInteropDevice so it seemed appropriate for it to inherit the methods. Saancreed suggested via Discord that it may make sense to rename ID3D12DXVKInteropDevice to ID3D12VKInteropDevice (keeping the same GUID, thus preserving ABI).

Scope of VkCommandBuffer retrieval

I chose to keep a simpler implementation where we can only retrieve the internal VkCommandBuffer from command lists which are reset with an interop-enabled ID3D12CommandAllocator. We could also in theory define some more fine-grained synchronization contracts so that the internal command buffer could be retrieved from non-interop command lists.

I don't see a pressing use-case for that to be needed right now, but I can think of plenty reasons why it may be attractive though. One may be to move the VK calls for CubinComputeShader* functionality back into dxvk-nvapi, where it can just record dispatches into the command-buffer directly rather than relying on vkd3d-proton to be updated in order to support new functions in that space. I'm unclear on what the maintenance burden would be for supporting this kind of thing (I know that vkd3d-proton does commandlist-internal work tracking and this would definitely complicate that if it had to account for a mix of internally+externally recorded work).

@liam-middlebrook liam-middlebrook force-pushed the interop-cmdbuf-sharing branch 2 times, most recently from 7cdb3d7 to 6aa1b2c Compare July 31, 2024 21:26
Copy link
Owner

@HansKristian-Work HansKristian-Work left a comment

Choose a reason for hiding this comment

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

The headers for commits should be vkd3d: not command:.

As for the name of the interface, I don't really care if it's ID3D12VKInterop or not, that's more up to @doitsujin.

libs/vkd3d/command.c Outdated Show resolved Hide resolved
libs/vkd3d/command.c Outdated Show resolved Hide resolved
libs/vkd3d/command.c Outdated Show resolved Hide resolved
libs/vkd3d/command.c Outdated Show resolved Hide resolved
include/vkd3d_device_vkd3d_ext.idl Outdated Show resolved Hide resolved
include/vkd3d_device_vkd3d_ext.idl Outdated Show resolved Hide resolved
libs/vkd3d/device_vkd3d_ext.c Show resolved Hide resolved
libs/vkd3d/device_vkd3d_ext.c Outdated Show resolved Hide resolved
libs/vkd3d/device_vkd3d_ext.c Outdated Show resolved Hide resolved
@HansKristian-Work
Copy link
Owner

HansKristian-Work commented Aug 1, 2024

I'm unclear on what the maintenance burden would be for supporting this kind of thing (I know that vkd3d-proton does commandlist-internal work tracking and this would definitely complicate that if it had to account for a mix of internally+externally recorded work).

I think this could work if there's a "begin interop" where we effectively invalidate all state in the command list (d3d12_invalidate_all_state), and flush any pending tracking. That basically means doing work that Close command list does.

Invalidation in vkd3d-proton won't work if the interop command buffer does really silly stuff like enabling things like queries and predication and not restoring that state, but that should be the responsibility of the interop client.

Comment on lines 100 to 104
if (FAILED(ID3D12DXVKInteropDevice1_BeginVkCommandBufferInterop(interop_device,
(ID3D12CommandList*)command_list,
&vkCmdBuf)))
{
ok(hr == S_OK, "ID3D12DXVKInteropDevice1_GetVulkanCmdHandles failed %#x.\n", hr);
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this now be something like the following?

Suggested change
if (FAILED(ID3D12DXVKInteropDevice1_BeginVkCommandBufferInterop(interop_device,
(ID3D12CommandList*)command_list,
&vkCmdBuf)))
{
ok(hr == S_OK, "ID3D12DXVKInteropDevice1_GetVulkanCmdHandles failed %#x.\n", hr);
if (FAILED(hr = ID3D12DXVKInteropDevice1_BeginVkCommandBufferInterop(interop_device,
(ID3D12CommandList*)command_list,
&vkCmdBuf)))
{
ok(hr == S_OK, "ID3D12DXVKInteropDevice1_BeginVkCommandBufferInterop failed %#x.\n", hr);

if (!cmd_list)
return E_INVALIDARG;

d3d12_command_list_invalidate_all_state(cmd_list);
Copy link
Owner

Choose a reason for hiding this comment

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

This isn't quite enough to make the interop work, but it's a start. We can probably flesh that out after this lands. Just add a FIXME comment here for now.

return;
}

if (FAILED(ID3D12DXVKInteropDevice1_BeginVkCommandBufferInterop(interop_device,
Copy link
Owner

Choose a reason for hiding this comment

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

hr is not set here.

ID3D12DXVKInteropDevice1_GetVulkanResourceInfo1(interop_device,
buffer,
(uint64_t*)&vkBuffer,
&offset,
Copy link
Owner

Choose a reason for hiding this comment

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

This needs to be UINT64 to get the 8 byte alignment on 32-bit. Both the handle and offset it seems.

@@ -599,21 +599,30 @@ void vkd3d_breadcrumb_tracer_report_device_lost(struct vkd3d_breadcrumb_tracer *
if (device->vk_info.NV_device_diagnostic_checkpoints)
{
/* vkGetQueueCheckpointDataNV does not require us to synchronize access to the queue. */
queue_family_info = d3d12_device_get_vkd3d_queue_family(device, D3D12_COMMAND_LIST_TYPE_DIRECT);
queue_family_info = d3d12_device_get_vkd3d_queue_family(device,
D3D12_COMMAND_LIST_TYPE_DIRECT,
Copy link
Owner

Choose a reason for hiding this comment

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

Just keep this on one line, the indents here are a bit goofy. Ditto the similar code below.

HRESULT GetVulkanResourceInfo1(ID3D12Resource *resource, UINT64 *vk_handle, UINT64 *buffer_offset, VkFormat *format);
HRESULT CreateInteropCommandQueue(const D3D12_COMMAND_QUEUE_DESC *pDesc, UINT32 vk_queue_family_index, ID3D12CommandQueue **ppQueue);
HRESULT CreateInteropCommandAllocator(D3D12_COMMAND_LIST_TYPE type, UINT32 vk_queue_family_index, ID3D12CommandAllocator **ppAllocator);
HRESULT BeginVkCommandBufferInterop(ID3D12CommandList *pCmdList, VkCommandBuffer *pCommandBuffer);
Copy link
Owner

@HansKristian-Work HansKristian-Work Aug 2, 2024

Choose a reason for hiding this comment

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

I think we need an EndVkCommandBufferInterop as well, just in case we need to support certain things in the future like conditional rendering and queries. For now, just implement it as a noop.

Copy link
Owner

@HansKristian-Work HansKristian-Work left a comment

Choose a reason for hiding this comment

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

The overall approach is reasonable I think and is not that invasive. Mostly nits now.

Copy link
Owner

@HansKristian-Work HansKristian-Work left a comment

Choose a reason for hiding this comment

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

This LGTM now, but needs to change the command: to vkd3d: on the commits as requested earlier.

…_info

Signed-off-by: Liam Middlebrook <lmiddlebrook@nvidia.com>
…ly indices

Signed-off-by: Liam Middlebrook <lmiddlebrook@nvidia.com>
Prepare for ID3D12DxvkInteropDevice1 by replacing usage of
ID3D12DXVKInteropDevice * with a new typedefed
d3d12_dxvk_interop_device_iface *.

Signed-off-by: Liam Middlebrook <lmiddlebrook@nvidia.com>
Used for creating+submitting VkCommandBuffer handles in the context of
D3D12 synchronization primitives.

Signed-off-by: Liam Middlebrook <lmiddlebrook@nvidia.com>
Signed-off-by: Liam Middlebrook <lmiddlebrook@nvidia.com>
Copy link
Owner

@HansKristian-Work HansKristian-Work left a comment

Choose a reason for hiding this comment

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

LGTM. Passes test suite on both NV and RADV.

@HansKristian-Work HansKristian-Work merged commit 1e873ca into HansKristian-Work:master Aug 13, 2024
3 checks passed
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