d3d12: Support setting SSBOs on the context and turning them into descriptors

Reviewed-by: Sil Vilerino <sivileri@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14294>
This commit is contained in:
Jesse Natalie 2021-12-21 16:24:55 -08:00 committed by Marge Bot
parent 49cf325d82
commit 32375789e5
4 changed files with 114 additions and 3 deletions

View file

@ -1460,9 +1460,62 @@ d3d12_set_stream_output_targets(struct pipe_context *pctx,
ctx->state_dirty |= D3D12_DIRTY_STREAM_OUTPUT;
}
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;

View file

@ -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;

View file

@ -138,6 +138,45 @@ fill_srv_descriptors(struct d3d12_context *ctx,
return table_start.gpu_handle;
}
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,
@ -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;
}

View file

@ -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
};