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

Experimentally implement workgraphs #2163

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion include/vkd3d_shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -1007,7 +1007,6 @@ struct vkd3d_shader_node_input_push_signature
VkDeviceAddress node_payload_output_atomic_bda;
VkDeviceAddress local_root_signature_bda;
uint32_t node_payload_output_offset;
uint32_t node_payload_output_stride;
uint32_t node_remaining_recursion_levels;
};

Expand Down
47 changes: 43 additions & 4 deletions libs/vkd3d/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -5626,6 +5626,7 @@

list->state = NULL;
list->rt_state = NULL;
memset(&list->wg_state, 0, sizeof(list->wg_state));
list->active_pipeline_type = VKD3D_PIPELINE_TYPE_NONE;

memset(list->so_buffers, 0, sizeof(list->so_buffers));
Expand Down Expand Up @@ -16879,14 +16880,52 @@
}
}

static void STDMETHODCALLTYPE d3d12_command_list_SetProgram(d3d12_command_list_iface *iface, const D3D12_SET_PROGRAM_DESC *desc)
static void STDMETHODCALLTYPE d3d12_command_list_SetProgram(
d3d12_command_list_iface *iface, const D3D12_SET_PROGRAM_DESC *desc)
{
FIXME("iface %p, desc %p, stub!\n", iface, desc);
struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList(iface);
struct d3d12_wg_state_object *wg_state;
uint32_t wg_state_program_index;
TRACE("iface %p, desc %p\n", iface, desc);

if (desc->Type != D3D12_PROGRAM_TYPE_WORK_GRAPH)
{
FIXME("Unsupported type %u.\n", desc->Type);
memset(&list->wg_state, 0, sizeof(list->wg_state));
return;
}

list->wg_state = desc->WorkGraph;

/* We only get program identifier, not the state object? Spicy ... */
wg_state = (struct d3d12_wg_state_object *)(uintptr_t)desc->WorkGraph.ProgramIdentifier.OpaqueData[1];
wg_state_program_index = desc->WorkGraph.ProgramIdentifier.OpaqueData[0];

if (wg_state)
{
if (wg_state_program_index >= wg_state->programs_count)
{
ERR("program index %u is out of bounds (%u programs).\n",

Check warning on line 16908 in libs/vkd3d/command.c

View workflow job for this annotation

GitHub Actions / build-set-linux

format ‘%u’ expects argument of type ‘unsigned int’, but argument 6 has type ‘size_t’ {aka ‘long unsigned int’} [-Wformat=]

Check warning on line 16908 in libs/vkd3d/command.c

View workflow job for this annotation

GitHub Actions / build-set-linux

format ‘%u’ expects argument of type ‘unsigned int’, but argument 6 has type ‘size_t’ {aka ‘long unsigned int’} [-Wformat=]
wg_state_program_index, wg_state->programs_count);
memset(&list->wg_state, 0, sizeof(list->wg_state));
return;
}

if (desc->WorkGraph.Flags & D3D12_SET_WORK_GRAPH_FLAG_INITIALIZE)
{
/* It's somewhat ambiguous if we should initialize scratch on SetProgram time or not.
* Assume we can. */
d3d12_command_list_workgraph_initialize_scratch(list);
}
}
}

static void STDMETHODCALLTYPE d3d12_command_list_DispatchGraph(d3d12_command_list_iface *iface, const D3D12_DISPATCH_GRAPH_DESC *desc)
static void STDMETHODCALLTYPE d3d12_command_list_DispatchGraph(
d3d12_command_list_iface *iface, const D3D12_DISPATCH_GRAPH_DESC *desc)
{
FIXME("iface %p, desc %p, stub!\n", iface, desc);
struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList(iface);
TRACE("iface %p, desc %p\n", iface, desc);
d3d12_command_list_workgraph_dispatch(list, desc);
}

#define VKD3D_DECLARE_D3D12_GRAPHICS_COMMAND_LIST_VARIANT(name, set_table_variant) \
Expand Down
10 changes: 7 additions & 3 deletions libs/vkd3d/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -7019,8 +7019,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateStateObject(d3d12_device_ifa

if (desc->Type == D3D12_STATE_OBJECT_TYPE_EXECUTABLE)
{
FIXME("Workgraph PSOs currently not supported.\n");
return E_NOTIMPL;
struct d3d12_wg_state_object *state;
if (FAILED(hr = d3d12_wg_state_object_create(device, desc, &state)))
return hr;
return return_interface(&state->ID3D12StateObject_iface, &IID_ID3D12StateObject, iid, state_object);
}
else
{
Expand Down Expand Up @@ -8299,7 +8301,9 @@ static void d3d12_device_caps_init_feature_options21(struct d3d12_device *device
{
D3D12_FEATURE_DATA_D3D12_OPTIONS21 *options21 = &device->d3d12_caps.options21;

options21->WorkGraphsTier = D3D12_WORK_GRAPHS_TIER_NOT_SUPPORTED;
options21->WorkGraphsTier = (vkd3d_config_flags & VKD3D_CONFIG_FLAG_ENABLE_EXPERIMENTAL_FEATURES) &&
device->device_info.shader_maximal_reconvergence_features.shaderMaximalReconvergence ?
D3D12_WORK_GRAPHS_TIER_1_0 : D3D12_WORK_GRAPHS_TIER_NOT_SUPPORTED;
options21->ExecuteIndirectTier = device->device_info.device_generated_commands_features_ext.deviceGeneratedCommands ?
D3D12_EXECUTE_INDIRECT_TIER_1_1 : D3D12_EXECUTE_INDIRECT_TIER_1_0;
options21->SampleCmpGradientAndBiasSupported = device->d3d12_caps.max_shader_model >= D3D_SHADER_MODEL_6_8 &&
Expand Down
3 changes: 2 additions & 1 deletion libs/vkd3d/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ vkd3d_src = [
'acceleration_structure.c',
'swapchain.c',
'queue_timeline.c',
'address_binding_tracker.c'
'address_binding_tracker.c',
'workgraphs.c'
]

if enable_renderdoc
Expand Down
2 changes: 1 addition & 1 deletion libs/vkd3d/meta.c
Original file line number Diff line number Diff line change
Expand Up @@ -2111,7 +2111,7 @@ static HRESULT vkd3d_workgraph_ops_init(struct vkd3d_workgraph_indirect_ops *wor
spec_data[0] = device->device_info.vulkan_1_3_properties.maxSubgroupSize;
spec_data[1] = device->device_info.vulkan_1_3_properties.maxSubgroupSize;
spec_data[2] = 0;
spec_data[3] = device->device_info.properties2.properties.limits.maxComputeWorkGroupCount[0] >=
spec_data[3] = device->device_info.properties2.properties.limits.maxComputeWorkGroupCount[0] <
VKD3D_WORKGRAPH_MAX_WGX_NO_PRIMARY_EXECUTION_THRESHOLD;

memset(&required, 0, sizeof(required));
Expand Down
50 changes: 50 additions & 0 deletions libs/vkd3d/vkd3d_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -2965,6 +2965,7 @@ struct d3d12_command_list

struct d3d12_pipeline_state *state;
struct d3d12_rt_state_object *rt_state;
D3D12_SET_WORK_GRAPH_DESC wg_state;
const struct d3d12_rt_state_object_variant *rt_state_variant;
uint32_t current_compute_meta_flags;

Expand Down Expand Up @@ -5434,6 +5435,7 @@ HRESULT d3d_blob_create(void *buffer, SIZE_T size, struct d3d_blob **blob);
/* ID3D12StateObject */
typedef ID3D12StateObject d3d12_state_object_iface;
typedef ID3D12StateObjectProperties1 d3d12_state_object_properties_iface;
typedef ID3D12WorkGraphProperties d3d12_work_graph_properties_iface;

struct d3d12_rt_state_object_identifier
{
Expand Down Expand Up @@ -5609,6 +5611,54 @@ static inline struct d3d12_rt_state_object *rt_impl_from_ID3D12StateObject(ID3D1
return CONTAINING_RECORD(iface, struct d3d12_rt_state_object, ID3D12StateObject_iface);
}

struct d3d12_wg_state_object_program;
struct d3d12_wg_state_object_module;

struct d3d12_wg_state_object_ring
{
VkBuffer vk_buffer;
VkDeviceAddress va;
struct vkd3d_device_memory_allocation allocation;
};

struct d3d12_wg_state_object
{
d3d12_state_object_iface ID3D12StateObject_iface;
d3d12_state_object_properties_iface ID3D12StateObjectProperties1_iface;
d3d12_work_graph_properties_iface ID3D12WorkGraphProperties_iface;
LONG refcount;
LONG internal_refcount;
D3D12_STATE_OBJECT_TYPE type;
struct d3d12_device *device;

struct d3d12_wg_state_object_program *programs;
size_t programs_count;

struct vkd3d_shader_library_entry_point *entry_points;
size_t entry_points_count;

struct d3d12_wg_state_object_module *modules;
size_t modules_count;

/* Very hacky. Allocate huge scratch buffers that can hold execution state.
* Generally speaking, these buffers should be allocated in ring-buffers on device. */
struct d3d12_wg_state_object_ring unrolled_offsets;
struct d3d12_wg_state_object_ring payload[2];

struct vkd3d_private_store private_store;
};

void d3d12_command_list_workgraph_initialize_scratch(struct d3d12_command_list *list);
void d3d12_command_list_workgraph_dispatch(struct d3d12_command_list *list, const D3D12_DISPATCH_GRAPH_DESC *desc);

static inline struct d3d12_wg_state_object *wg_impl_from_ID3D12StateObject(ID3D12StateObject *iface)
{
return CONTAINING_RECORD(iface, struct d3d12_wg_state_object, ID3D12StateObject_iface);
}

HRESULT d3d12_wg_state_object_create(struct d3d12_device *device, const D3D12_STATE_OBJECT_DESC *desc,
struct d3d12_wg_state_object **object);

/* ID3D12MetaCommand */
struct d3d12_meta_command;

Expand Down
Loading