}
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) {
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;
+ }
}
}
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;
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 | \
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,
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;
}
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)
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)
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,
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;
}
enum d3d12_resource_binding_type {
D3D12_RESOURCE_BINDING_TYPE_SRV,
D3D12_RESOURCE_BINDING_TYPE_CBV,
+ D3D12_RESOURCE_BINDING_TYPE_UAV,
D3D12_RESOURCE_BINDING_TYPES
};