d3d12: Move indirect compute to real indirect dispatches

Reviewed-by: Sil Vilerino <sivileri@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14787>
This commit is contained in:
Jesse Natalie
2022-01-26 09:30:28 -08:00
parent cab0ed52e8
commit 5f48e6d7a2
3 changed files with 93 additions and 32 deletions
@@ -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);
@@ -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
+83 -22
View File
@@ -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);
}