Skip to content

Commit 7e7d599

Browse files
vkd3d: Implement baseline workgraph functionality.
Good enough to bring up SimpleClassify and ComputeRasterizer demos. Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
1 parent fe76abb commit 7e7d599

6 files changed

Lines changed: 3372 additions & 7 deletions

File tree

include/vkd3d_shader.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,21 @@ enum vkd3d_shader_node_launch_type
974974
VKD3D_SHADER_NODE_LAUNCH_TYPE_THREAD = 3
975975
};
976976

977+
/* For emulation path. */
978+
struct vkd3d_shader_node_input_push_signature
979+
{
980+
VkDeviceAddress node_payload_bda;
981+
VkDeviceAddress node_linear_offset_bda;
982+
VkDeviceAddress node_total_nodes_bda;
983+
VkDeviceAddress node_payload_stride_or_offsets_bda;
984+
VkDeviceAddress node_payload_output_bda;
985+
VkDeviceAddress node_payload_output_atomic_bda;
986+
VkDeviceAddress local_root_signature_bda;
987+
uint32_t node_payload_output_offset;
988+
uint32_t node_payload_output_stride;
989+
uint32_t node_remaining_recursion_levels;
990+
};
991+
977992
struct vkd3d_shader_node_input_data
978993
{
979994
const char *node_id; /* This is often same as entry point name, but does not have to be. */

libs/vkd3d/command.c

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5701,6 +5701,7 @@ static void d3d12_command_list_reset_api_state(struct d3d12_command_list *list,
57015701

57025702
list->state = NULL;
57035703
list->rt_state = NULL;
5704+
memset(&list->wg_state, 0, sizeof(list->wg_state));
57045705
list->active_pipeline_type = VKD3D_PIPELINE_TYPE_NONE;
57055706

57065707
memset(list->so_buffers, 0, sizeof(list->so_buffers));
@@ -16869,14 +16870,52 @@ static void STDMETHODCALLTYPE d3d12_command_list_IASetIndexBufferStripCutValue(d
1686916870
}
1687016871
}
1687116872

16872-
static void STDMETHODCALLTYPE d3d12_command_list_SetProgram(d3d12_command_list_iface *iface, const D3D12_SET_PROGRAM_DESC *desc)
16873+
static void STDMETHODCALLTYPE d3d12_command_list_SetProgram(
16874+
d3d12_command_list_iface *iface, const D3D12_SET_PROGRAM_DESC *desc)
1687316875
{
16874-
FIXME("iface %p, desc %p, stub!\n", iface, desc);
16876+
struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList(iface);
16877+
struct d3d12_wg_state_object *wg_state;
16878+
uint32_t wg_state_program_index;
16879+
TRACE("iface %p, desc %p\n", iface, desc);
16880+
16881+
if (desc->Type != D3D12_PROGRAM_TYPE_WORK_GRAPH)
16882+
{
16883+
FIXME("Unsupported type %u.\n", desc->Type);
16884+
memset(&list->wg_state, 0, sizeof(list->wg_state));
16885+
return;
16886+
}
16887+
16888+
list->wg_state = desc->WorkGraph;
16889+
16890+
/* We only get program identifier, not the state object? Spicy ... */
16891+
wg_state = (struct d3d12_wg_state_object *)(uintptr_t)desc->WorkGraph.ProgramIdentifier.OpaqueData[1];
16892+
wg_state_program_index = desc->WorkGraph.ProgramIdentifier.OpaqueData[0];
16893+
16894+
if (wg_state)
16895+
{
16896+
if (wg_state_program_index >= wg_state->programs_count)
16897+
{
16898+
ERR("program index %u is out of bounds (%u programs).\n",
16899+
wg_state_program_index, wg_state->programs_count);
16900+
memset(&list->wg_state, 0, sizeof(list->wg_state));
16901+
return;
16902+
}
16903+
16904+
if (desc->WorkGraph.Flags & D3D12_SET_WORK_GRAPH_FLAG_INITIALIZE)
16905+
{
16906+
/* It's somewhat ambiguous if we should initialize scratch on SetProgram time or not.
16907+
* Assume we can. */
16908+
d3d12_command_list_workgraph_initialize_scratch(list);
16909+
}
16910+
}
1687516911
}
1687616912

16877-
static void STDMETHODCALLTYPE d3d12_command_list_DispatchGraph(d3d12_command_list_iface *iface, const D3D12_DISPATCH_GRAPH_DESC *desc)
16913+
static void STDMETHODCALLTYPE d3d12_command_list_DispatchGraph(
16914+
d3d12_command_list_iface *iface, const D3D12_DISPATCH_GRAPH_DESC *desc)
1687816915
{
16879-
FIXME("iface %p, desc %p, stub!\n", iface, desc);
16916+
struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList(iface);
16917+
TRACE("iface %p, desc %p\n", iface, desc);
16918+
d3d12_command_list_workgraph_dispatch(list, desc);
1688016919
}
1688116920

1688216921
#define VKD3D_DECLARE_D3D12_GRAPHICS_COMMAND_LIST_VARIANT(name, set_table_variant) \

libs/vkd3d/device.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6951,8 +6951,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateStateObject(d3d12_device_ifa
69516951

69526952
if (desc->Type == D3D12_STATE_OBJECT_TYPE_EXECUTABLE)
69536953
{
6954-
FIXME("Workgraph PSOs currently not supported.\n");
6955-
return E_NOTIMPL;
6954+
struct d3d12_wg_state_object *state;
6955+
if (FAILED(hr = d3d12_wg_state_object_create(device, desc, &state)))
6956+
return hr;
6957+
return return_interface(&state->ID3D12StateObject_iface, &IID_ID3D12StateObject, iid, state_object);
69566958
}
69576959
else
69586960
{

libs/vkd3d/meson.build

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ vkd3d_src = [
8282
'acceleration_structure.c',
8383
'swapchain.c',
8484
'queue_timeline.c',
85-
'address_binding_tracker.c'
85+
'address_binding_tracker.c',
86+
'workgraphs.c'
8687
]
8788

8889
if enable_renderdoc

libs/vkd3d/vkd3d_private.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2949,6 +2949,7 @@ struct d3d12_command_list
29492949

29502950
struct d3d12_pipeline_state *state;
29512951
struct d3d12_rt_state_object *rt_state;
2952+
D3D12_SET_WORK_GRAPH_DESC wg_state;
29522953
const struct d3d12_rt_state_object_variant *rt_state_variant;
29532954
uint32_t current_compute_meta_flags;
29542955

@@ -5372,6 +5373,7 @@ HRESULT d3d_blob_create(void *buffer, SIZE_T size, struct d3d_blob **blob);
53725373
/* ID3D12StateObject */
53735374
typedef ID3D12StateObject d3d12_state_object_iface;
53745375
typedef ID3D12StateObjectProperties1 d3d12_state_object_properties_iface;
5376+
typedef ID3D12WorkGraphProperties d3d12_work_graph_properties_iface;
53755377

53765378
struct d3d12_rt_state_object_identifier
53775379
{
@@ -5547,6 +5549,54 @@ static inline struct d3d12_rt_state_object *rt_impl_from_ID3D12StateObject(ID3D1
55475549
return CONTAINING_RECORD(iface, struct d3d12_rt_state_object, ID3D12StateObject_iface);
55485550
}
55495551

5552+
struct d3d12_wg_state_object_program;
5553+
struct d3d12_wg_state_object_module;
5554+
5555+
struct d3d12_wg_state_object_ring
5556+
{
5557+
VkBuffer vk_buffer;
5558+
VkDeviceAddress va;
5559+
struct vkd3d_device_memory_allocation allocation;
5560+
};
5561+
5562+
struct d3d12_wg_state_object
5563+
{
5564+
d3d12_state_object_iface ID3D12StateObject_iface;
5565+
d3d12_state_object_properties_iface ID3D12StateObjectProperties1_iface;
5566+
d3d12_work_graph_properties_iface ID3D12WorkGraphProperties_iface;
5567+
LONG refcount;
5568+
LONG internal_refcount;
5569+
D3D12_STATE_OBJECT_TYPE type;
5570+
struct d3d12_device *device;
5571+
5572+
struct d3d12_wg_state_object_program *programs;
5573+
size_t programs_count;
5574+
5575+
struct vkd3d_shader_library_entry_point *entry_points;
5576+
size_t entry_points_count;
5577+
5578+
struct d3d12_wg_state_object_module *modules;
5579+
size_t modules_count;
5580+
5581+
/* Very hacky. Allocate huge scratch buffers that can hold execution state.
5582+
* Generally speaking, these buffers should be allocated in ring-buffers on device. */
5583+
struct d3d12_wg_state_object_ring unrolled_offsets;
5584+
struct d3d12_wg_state_object_ring payload[2];
5585+
5586+
struct vkd3d_private_store private_store;
5587+
};
5588+
5589+
void d3d12_command_list_workgraph_initialize_scratch(struct d3d12_command_list *list);
5590+
void d3d12_command_list_workgraph_dispatch(struct d3d12_command_list *list, const D3D12_DISPATCH_GRAPH_DESC *desc);
5591+
5592+
static inline struct d3d12_wg_state_object *wg_impl_from_ID3D12StateObject(ID3D12StateObject *iface)
5593+
{
5594+
return CONTAINING_RECORD(iface, struct d3d12_wg_state_object, ID3D12StateObject_iface);
5595+
}
5596+
5597+
HRESULT d3d12_wg_state_object_create(struct d3d12_device *device, const D3D12_STATE_OBJECT_DESC *desc,
5598+
struct d3d12_wg_state_object **object);
5599+
55505600
/* ID3D12MetaCommand */
55515601
struct d3d12_meta_command;
55525602

0 commit comments

Comments
 (0)