From 5f48e6d7a29cef7e36a282c5fc4a4457e5d23d80 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Wed, 26 Jan 2022 09:30:28 -0800 Subject: [PATCH] d3d12: Move indirect compute to real indirect dispatches Reviewed-by: Sil Vilerino Part-of: --- .../drivers/d3d12/d3d12_cmd_signature.cpp | 10 +- .../drivers/d3d12/d3d12_cmd_signature.h | 10 +- src/gallium/drivers/d3d12/d3d12_draw.cpp | 105 ++++++++++++++---- 3 files changed, 93 insertions(+), 32 deletions(-) diff --git a/src/gallium/drivers/d3d12/d3d12_cmd_signature.cpp b/src/gallium/drivers/d3d12/d3d12_cmd_signature.cpp index 5c52429e62d..8a6d17add77 100644 --- a/src/gallium/drivers/d3d12/d3d12_cmd_signature.cpp +++ b/src/gallium/drivers/d3d12/d3d12_cmd_signature.cpp @@ -41,11 +41,11 @@ create_cmd_signature(struct d3d12_context *ctx, const struct d3d12_cmd_signature D3D12_INDIRECT_ARGUMENT_DESC indirect_args[2] = {}; unsigned num_args = 0; - if (key->draw_params) { + if (key->draw_or_dispatch_params) { indirect_args[num_args].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT; - indirect_args[num_args].Constant.RootParameterIndex = key->draw_params_root_const_param; - indirect_args[num_args].Constant.DestOffsetIn32BitValues = key->draw_params_root_const_offset; - indirect_args[num_args++].Constant.Num32BitValuesToSet = 4; + indirect_args[num_args].Constant.RootParameterIndex = key->params_root_const_param; + indirect_args[num_args].Constant.DestOffsetIn32BitValues = key->params_root_const_offset; + indirect_args[num_args++].Constant.Num32BitValuesToSet = key->compute ? 3 : 4; } indirect_args[num_args++].Type = key->compute ? D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH : @@ -62,7 +62,7 @@ create_cmd_signature(struct d3d12_context *ctx, const struct d3d12_cmd_signature } ID3D12CommandSignature * -d3d12_get_gfx_cmd_signature(struct d3d12_context *ctx, +d3d12_get_cmd_signature(struct d3d12_context *ctx, const struct d3d12_cmd_signature_key *key) { struct hash_entry *entry = _mesa_hash_table_search(ctx->cmd_signature_cache, &key); diff --git a/src/gallium/drivers/d3d12/d3d12_cmd_signature.h b/src/gallium/drivers/d3d12/d3d12_cmd_signature.h index dbf65d0318e..4cd142ef77a 100644 --- a/src/gallium/drivers/d3d12/d3d12_cmd_signature.h +++ b/src/gallium/drivers/d3d12/d3d12_cmd_signature.h @@ -29,10 +29,10 @@ struct d3d12_cmd_signature_key { uint8_t compute:1; uint8_t indexed:1; - uint8_t draw_params:1; + uint8_t draw_or_dispatch_params:1; /* 5 bits padding */ - uint8_t draw_params_root_const_param; - uint8_t draw_params_root_const_offset; + uint8_t params_root_const_param; + uint8_t params_root_const_offset; /* 8 bits padding */ unsigned multi_draw_stride; @@ -48,7 +48,7 @@ void d3d12_cmd_signature_cache_destroy(struct d3d12_context *ctx); ID3D12CommandSignature * -d3d12_get_gfx_cmd_signature(struct d3d12_context *ctx, - const struct d3d12_cmd_signature_key *key); +d3d12_get_cmd_signature(struct d3d12_context *ctx, + const struct d3d12_cmd_signature_key *key); #endif diff --git a/src/gallium/drivers/d3d12/d3d12_draw.cpp b/src/gallium/drivers/d3d12/d3d12_draw.cpp index 78f8fab7fa7..be9c2983bb5 100644 --- a/src/gallium/drivers/d3d12/d3d12_draw.cpp +++ b/src/gallium/drivers/d3d12/d3d12_draw.cpp @@ -370,9 +370,9 @@ fill_graphics_state_vars(struct d3d12_context *ctx, ptr[1] = dinfo->start_instance; ptr[2] = drawid; ptr[3] = dinfo->index_size ? -1 : 0; - cmd_sig_key->draw_params = 1; + cmd_sig_key->draw_or_dispatch_params = 1; cmd_sig_key->root_sig = ctx->gfx_pipeline_state.root_signature; - cmd_sig_key->draw_params_root_const_offset = size; + cmd_sig_key->params_root_const_offset = size; size += 4; break; case D3D12_STATE_VAR_DEPTH_TRANSFORM: @@ -404,7 +404,8 @@ static unsigned fill_compute_state_vars(struct d3d12_context *ctx, const struct pipe_grid_info *info, struct d3d12_shader *shader, - uint32_t *values) + uint32_t *values, + struct d3d12_cmd_signature_key *cmd_sig_key) { unsigned size = 0; @@ -416,6 +417,9 @@ fill_compute_state_vars(struct d3d12_context *ctx, ptr[0] = info->grid[0]; ptr[1] = info->grid[1]; ptr[2] = info->grid[2]; + cmd_sig_key->draw_or_dispatch_params = 1; + cmd_sig_key->root_sig = ctx->compute_pipeline_state.root_signature; + cmd_sig_key->params_root_const_offset = size; size += 4; break; case D3D12_STATE_VAR_TRANSFORM_GENERIC0: { @@ -550,8 +554,8 @@ update_graphics_root_parameters(struct d3d12_context *ctx, if (shader_sel->current->num_state_vars > 0) { uint32_t constants[D3D12_MAX_GRAPHICS_STATE_VARS * 4]; unsigned size = fill_graphics_state_vars(ctx, dinfo, drawid, draw, shader_sel->current, constants, cmd_sig_key); - if (cmd_sig_key->draw_params) - cmd_sig_key->draw_params_root_const_param = num_params; + if (cmd_sig_key->draw_or_dispatch_params) + cmd_sig_key->params_root_const_param = num_params; ctx->cmdlist->SetGraphicsRoot32BitConstants(num_params, size, constants, 0); num_params++; } @@ -563,7 +567,8 @@ static unsigned update_compute_root_parameters(struct d3d12_context *ctx, const struct pipe_grid_info *info, D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES], - int root_desc_indices[MAX_DESCRIPTOR_TABLES]) + int root_desc_indices[MAX_DESCRIPTOR_TABLES], + struct d3d12_cmd_signature_key *cmd_sig_key) { unsigned num_params = 0; unsigned num_root_descriptors = 0; @@ -574,7 +579,9 @@ update_compute_root_parameters(struct d3d12_context *ctx, /* TODO Don't always update state vars */ if (shader_sel->current->num_state_vars > 0) { uint32_t constants[D3D12_MAX_COMPUTE_STATE_VARS * 4]; - unsigned size = fill_compute_state_vars(ctx, info, shader_sel->current, constants); + unsigned size = fill_compute_state_vars(ctx, info, shader_sel->current, constants, cmd_sig_key); + if (cmd_sig_key->draw_or_dispatch_params) + cmd_sig_key->params_root_const_param = num_params; ctx->cmdlist->SetComputeRoot32BitConstants(num_params, size, constants, 0); num_params++; } @@ -1180,7 +1187,7 @@ d3d12_draw_vbo(struct pipe_context *pctx, ctx->cmdlist->SetGraphicsRootDescriptorTable(root_desc_indices[i], root_desc_tables[i]); if (indirect) { - ID3D12CommandSignature *cmd_sig = d3d12_get_gfx_cmd_signature(ctx, &cmd_sig_key); + ID3D12CommandSignature *cmd_sig = d3d12_get_cmd_signature(ctx, &cmd_sig_key); ctx->cmdlist->ExecuteIndirect(cmd_sig, indirect->draw_count, indirect_arg_buf, indirect_arg_offset, indirect_count_buf, indirect_count_offset); } else { @@ -1215,25 +1222,61 @@ d3d12_draw_vbo(struct pipe_context *pctx, pipe_resource_reference(&patched_indirect.buffer, NULL); } +static bool +update_dispatch_indirect_with_sysvals(struct d3d12_context *ctx, + struct pipe_resource **indirect_inout, + unsigned *indirect_offset_inout, + struct pipe_resource **indirect_out) +{ + if (*indirect_inout == nullptr || + ctx->compute_state == nullptr) + return false; + + if (!BITSET_TEST(ctx->compute_state->current->nir->info.system_values_read, SYSTEM_VALUE_NUM_WORKGROUPS)) + return false; + + if (ctx->current_predication) + ctx->cmdlist->SetPredication(nullptr, 0, D3D12_PREDICATION_OP_EQUAL_ZERO); + + auto indirect_in = *indirect_inout; + + /* 6 uints: 2 copies of the indirect arg buffer */ + pipe_resource output_buf_templ = {}; + output_buf_templ.target = PIPE_BUFFER; + output_buf_templ.width0 = sizeof(uint32_t) * 6; + output_buf_templ.height0 = output_buf_templ.depth0 = output_buf_templ.array_size = + output_buf_templ.last_level = 1; + output_buf_templ.usage = PIPE_USAGE_DEFAULT; + *indirect_out = ctx->base.screen->resource_create(ctx->base.screen, &output_buf_templ); + + struct pipe_box src_box = { (int)*indirect_offset_inout, 0, 0, sizeof(uint32_t) * 3, 1, 1 }; + ctx->base.resource_copy_region(&ctx->base, *indirect_out, 0, 0, 0, 0, indirect_in, 0, &src_box); + ctx->base.resource_copy_region(&ctx->base, *indirect_out, 0, src_box.width, 0, 0, indirect_in, 0, &src_box); + + if (ctx->current_predication) + d3d12_enable_predication(ctx); + + *indirect_inout = *indirect_out; + *indirect_offset_inout = 0; + return true; +} + void d3d12_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info) { struct d3d12_context *ctx = d3d12_context(pctx); struct d3d12_batch *batch; + struct pipe_resource *patched_indirect = nullptr; - if (info->indirect) { - /* TODO: Use a compute shader to retrieve state vars if necessary, and do an actual indirect dispatch */ - pipe_box box = { (int)info->indirect_offset, 0, 0, sizeof(info->grid), 1, 1 }; - pipe_transfer *transfer = nullptr; - void *map = pctx->buffer_map(pctx, info->indirect, 0, PIPE_MAP_READ, &box, &transfer); - pipe_grid_info new_info = *info; - new_info.indirect = nullptr; - memcpy(new_info.grid, map, sizeof(new_info.grid)); - pctx->buffer_unmap(pctx, transfer); + struct d3d12_cmd_signature_key cmd_sig_key; + memset(&cmd_sig_key, 0, sizeof(cmd_sig_key)); + cmd_sig_key.compute = 1; + cmd_sig_key.multi_draw_stride = sizeof(D3D12_DISPATCH_ARGUMENTS); - d3d12_launch_grid(pctx, &new_info); - return; - } + struct pipe_resource *indirect = info->indirect; + unsigned indirect_offset = info->indirect_offset; + if (indirect && update_dispatch_indirect_with_sysvals(ctx, &indirect, &indirect_offset, &patched_indirect)) + cmd_sig_key.multi_draw_stride = sizeof(D3D12_DISPATCH_ARGUMENTS) * 2; d3d12_select_compute_shader_variants(ctx, info); d3d12_validate_queries(ctx); @@ -1276,14 +1319,31 @@ d3d12_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info) D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES]; int root_desc_indices[MAX_DESCRIPTOR_TABLES]; - unsigned num_root_descriptors = update_compute_root_parameters(ctx, info, root_desc_tables, root_desc_indices); + unsigned num_root_descriptors = update_compute_root_parameters(ctx, info, root_desc_tables, root_desc_indices, &cmd_sig_key); + + ID3D12Resource *indirect_arg_buf = nullptr; + uint64_t indirect_arg_offset = 0; + if (indirect) { + struct d3d12_resource *indirect_buf = d3d12_resource(indirect); + uint64_t buf_offset = 0; + indirect_arg_buf = d3d12_resource_underlying(indirect_buf, &buf_offset); + indirect_arg_offset = indirect_offset + buf_offset; + d3d12_transition_resource_state(ctx, indirect_buf, + D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT, D3D12_BIND_INVALIDATE_NONE); + d3d12_batch_reference_resource(batch, indirect_buf, false); + } d3d12_apply_resource_states(ctx, ctx->compute_state->is_variant); for (unsigned i = 0; i < num_root_descriptors; ++i) ctx->cmdlist->SetComputeRootDescriptorTable(root_desc_indices[i], root_desc_tables[i]); - ctx->cmdlist->Dispatch(info->grid[0], info->grid[1], info->grid[2]); + if (indirect) { + ID3D12CommandSignature *cmd_sig = d3d12_get_cmd_signature(ctx, &cmd_sig_key); + ctx->cmdlist->ExecuteIndirect(cmd_sig, 1, indirect_arg_buf, indirect_arg_offset, nullptr, 0); + } else { + ctx->cmdlist->Dispatch(info->grid[0], info->grid[1], info->grid[2]); + } ctx->state_dirty &= D3D12_DIRTY_GFX_MASK; ctx->cmdlist_dirty &= D3D12_DIRTY_GFX_MASK; @@ -1293,4 +1353,5 @@ d3d12_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info) batch->pending_memory_barrier = false; ctx->shader_dirty[PIPE_SHADER_COMPUTE] = 0; + pipe_resource_reference(&patched_indirect, nullptr); }