From 32375789e56a4f8696562ba9ad20bb8508b05e40 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Tue, 21 Dec 2021 16:24:55 -0800 Subject: [PATCH] d3d12: Support setting SSBOs on the context and turning them into descriptors Reviewed-by: Sil Vilerino Part-of: --- src/gallium/drivers/d3d12/d3d12_context.cpp | 61 ++++++++++++++++++++++++++++- src/gallium/drivers/d3d12/d3d12_context.h | 5 ++- src/gallium/drivers/d3d12/d3d12_draw.cpp | 50 ++++++++++++++++++++++- src/gallium/drivers/d3d12/d3d12_resource.h | 1 + 4 files changed, 114 insertions(+), 3 deletions(-) diff --git a/src/gallium/drivers/d3d12/d3d12_context.cpp b/src/gallium/drivers/d3d12/d3d12_context.cpp index 72aad42..b208c5c 100644 --- a/src/gallium/drivers/d3d12/d3d12_context.cpp +++ b/src/gallium/drivers/d3d12/d3d12_context.cpp @@ -1461,8 +1461,61 @@ d3d12_set_stream_output_targets(struct pipe_context *pctx, } static void +d3d12_decrement_uav_bind_count(struct d3d12_context *ctx, + enum pipe_shader_type shader, + struct d3d12_resource *res) { + assert(res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_UAV] > 0); + res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_UAV]--; +} + +static void +d3d12_increment_uav_bind_count(struct d3d12_context *ctx, + enum pipe_shader_type shader, + struct d3d12_resource *res) { + res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_UAV]++; +} + +static void +d3d12_set_shader_buffers(struct pipe_context *pctx, + enum pipe_shader_type shader, + unsigned start_slot, unsigned count, + const struct pipe_shader_buffer *buffers, + unsigned writable_bitmask) +{ + struct d3d12_context *ctx = d3d12_context(pctx); + for (unsigned i = 0; i < count; ++i) { + struct pipe_shader_buffer *slot = &ctx->ssbo_views[shader][i + start_slot]; + if (slot->buffer) { + d3d12_decrement_uav_bind_count(ctx, shader, d3d12_resource(slot->buffer)); + pipe_resource_reference(&slot->buffer, NULL); + } + + if (buffers && buffers[i].buffer) { + pipe_resource_reference(&slot->buffer, buffers[i].buffer); + slot->buffer_offset = buffers[i].buffer_offset; + slot->buffer_size = buffers[i].buffer_size; + d3d12_increment_uav_bind_count(ctx, shader, d3d12_resource(buffers[i].buffer)); + } else + memset(slot, 0, sizeof(*slot)); + } + + if (buffers) { + ctx->num_ssbo_views[shader] = MAX2(ctx->num_ssbo_views[shader], count + start_slot); + } else { + ctx->num_ssbo_views[shader] = 0; + for (int i = start_slot + count - 1; i >= (int)start_slot; --i) { + if (ctx->ssbo_views[shader][i].buffer) { + ctx->num_ssbo_views[shader] = i; + break; + } + } + } + ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_UAVS; +} + +static void d3d12_invalidate_context_bindings(struct d3d12_context *ctx, struct d3d12_resource *res) { - // For each shader type, if the resource is currently bound as CBV or SRV + // For each shader type, if the resource is currently bound as CBV, SRV, or UAV // set the context shader_dirty bit. for (uint i = 0; i < PIPE_SHADER_TYPES; ++i) { if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_CBV] > 0) { @@ -1472,6 +1525,10 @@ d3d12_invalidate_context_bindings(struct d3d12_context *ctx, struct d3d12_resour if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_SRV] > 0) { ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS; } + + if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_UAV] > 0) { + ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_UAVS; + } } } @@ -1966,6 +2023,8 @@ d3d12_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) ctx->base.stream_output_target_destroy = d3d12_stream_output_target_destroy; ctx->base.set_stream_output_targets = d3d12_set_stream_output_targets; + ctx->base.set_shader_buffers = d3d12_set_shader_buffers; + ctx->base.get_timestamp = d3d12_get_timestamp; ctx->base.clear = d3d12_clear; diff --git a/src/gallium/drivers/d3d12/d3d12_context.h b/src/gallium/drivers/d3d12/d3d12_context.h index 089e93b..5be0b06 100644 --- a/src/gallium/drivers/d3d12/d3d12_context.h +++ b/src/gallium/drivers/d3d12/d3d12_context.h @@ -69,6 +69,7 @@ enum d3d12_shader_dirty_flags D3D12_SHADER_DIRTY_CONSTBUF = (1 << 0), D3D12_SHADER_DIRTY_SAMPLER_VIEWS = (1 << 1), D3D12_SHADER_DIRTY_SAMPLERS = (1 << 2), + D3D12_SHADER_DIRTY_UAVS = (1 << 3), }; #define D3D12_DIRTY_PSO (D3D12_DIRTY_BLEND | D3D12_DIRTY_RASTERIZER | D3D12_DIRTY_ZSA | \ @@ -78,7 +79,7 @@ enum d3d12_shader_dirty_flags D3D12_DIRTY_STRIP_CUT_VALUE) #define D3D12_SHADER_DIRTY_ALL (D3D12_SHADER_DIRTY_CONSTBUF | D3D12_SHADER_DIRTY_SAMPLER_VIEWS | \ - D3D12_SHADER_DIRTY_SAMPLERS) + D3D12_SHADER_DIRTY_SAMPLERS | D3D12_SHADER_DIRTY_UAVS) enum d3d12_binding_type { D3D12_BINDING_CONSTANT_BUFFER, @@ -181,6 +182,8 @@ struct d3d12_context { struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS]; unsigned num_sampler_views[PIPE_SHADER_TYPES]; unsigned has_int_samplers; + struct pipe_shader_buffer ssbo_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS]; + unsigned num_ssbo_views[PIPE_SHADER_TYPES]; struct d3d12_sampler_state *samplers[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; unsigned num_samplers[PIPE_SHADER_TYPES]; D3D12_INDEX_BUFFER_VIEW ibv; diff --git a/src/gallium/drivers/d3d12/d3d12_draw.cpp b/src/gallium/drivers/d3d12/d3d12_draw.cpp index 77372b7..5097c75 100644 --- a/src/gallium/drivers/d3d12/d3d12_draw.cpp +++ b/src/gallium/drivers/d3d12/d3d12_draw.cpp @@ -139,6 +139,45 @@ fill_srv_descriptors(struct d3d12_context *ctx, } static D3D12_GPU_DESCRIPTOR_HANDLE +fill_uav_descriptors(struct d3d12_context *ctx, + const struct d3d12_shader *shader, + int stage) +{ + struct d3d12_batch *batch = d3d12_current_batch(ctx); + struct d3d12_descriptor_handle table_start; + + d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start); + + for (unsigned i = 0; i < shader->nir->info.num_ssbos; i++) + { + struct pipe_shader_buffer *view = &ctx->ssbo_views[stage][i]; + + D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc; + uav_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; + uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; + uav_desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; + uav_desc.Buffer.StructureByteStride = 0; + uav_desc.Buffer.CounterOffsetInBytes = 0; + ID3D12Resource *d3d12_res = nullptr; + if (view->buffer) { + struct d3d12_resource *res = d3d12_resource(view->buffer); + uint64_t res_offset = 0; + d3d12_res = d3d12_resource_underlying(res, &res_offset); + d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_BIND_INVALIDATE_NONE); + uav_desc.Buffer.FirstElement = (view->buffer_offset + res_offset) / 4; + uav_desc.Buffer.NumElements = DIV_ROUND_UP(view->buffer_size, 4); + d3d12_batch_reference_resource(batch, res, true); + } + + struct d3d12_descriptor_handle handle; + d3d12_descriptor_heap_alloc_handle(batch->view_heap, &handle); + d3d12_screen(ctx->base.screen)->dev->CreateUnorderedAccessView(d3d12_res, nullptr, &uav_desc, handle.cpu_handle); + } + + return table_start.gpu_handle; +} + +static D3D12_GPU_DESCRIPTOR_HANDLE fill_sampler_descriptors(struct d3d12_context *ctx, const struct d3d12_shader_selector *shader_sel, unsigned stage) @@ -229,6 +268,7 @@ check_descriptors_left(struct d3d12_context *ctx) needed_descs += shader->current->num_cb_bindings; needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding; + needed_descs += shader->current->nir->info.num_ssbos; } if (d3d12_descriptor_heap_get_remaining_handles(batch->view_heap) < needed_descs) @@ -250,7 +290,7 @@ check_descriptors_left(struct d3d12_context *ctx) return true; } -#define MAX_DESCRIPTOR_TABLES (D3D12_GFX_SHADER_STAGES * 3) +#define MAX_DESCRIPTOR_TABLES (D3D12_GFX_SHADER_STAGES * 4) static unsigned update_graphics_root_parameters(struct d3d12_context *ctx, @@ -300,6 +340,14 @@ update_graphics_root_parameters(struct d3d12_context *ctx, ctx->cmdlist->SetGraphicsRoot32BitConstants(num_params, size, constants, 0); num_params++; } + if (shader->nir->info.num_ssbos > 0) { + if (dirty & D3D12_SHADER_DIRTY_UAVS) { + assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES); + root_desc_tables[num_root_desciptors] = fill_uav_descriptors(ctx, shader, i); + root_desc_indices[num_root_desciptors++] = num_params; + } + num_params++; + } } return num_root_desciptors; } diff --git a/src/gallium/drivers/d3d12/d3d12_resource.h b/src/gallium/drivers/d3d12/d3d12_resource.h index 49b7077..e9532d1 100644 --- a/src/gallium/drivers/d3d12/d3d12_resource.h +++ b/src/gallium/drivers/d3d12/d3d12_resource.h @@ -35,6 +35,7 @@ struct pipe_screen; enum d3d12_resource_binding_type { D3D12_RESOURCE_BINDING_TYPE_SRV, D3D12_RESOURCE_BINDING_TYPE_CBV, + D3D12_RESOURCE_BINDING_TYPE_UAV, D3D12_RESOURCE_BINDING_TYPES }; -- 2.7.4