d3d12: Add UAV barriers for UAVs that are being used by compute transforms

If an indirect arg buffer is being produced by a compute shader, then when
we go to consume it as an SSBO in a compute transform pass, we need to insert
a UAV barrier to prevent the two dispatches from overlapping. For app dispatches,
this is the app's responsibility via explicit barrier APIs, and if they don't,
then they're allowed to overlap.

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 08:31:33 -08:00
parent 31aaf92b7d
commit 1d43e75228
9 changed files with 33 additions and 22 deletions

View File

@@ -123,7 +123,7 @@ blit_resolve(struct d3d12_context *ctx, const struct pipe_blit_info *info)
D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_RESOLVE_DEST,
D3D12_BIND_INVALIDATE_FULL); D3D12_BIND_INVALIDATE_FULL);
d3d12_apply_resource_states(ctx); d3d12_apply_resource_states(ctx, false);
d3d12_batch_reference_resource(batch, src, false); d3d12_batch_reference_resource(batch, src, false);
d3d12_batch_reference_resource(batch, dst, true); d3d12_batch_reference_resource(batch, dst, true);
@@ -432,7 +432,7 @@ d3d12_direct_copy(struct d3d12_context *ctx,
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_BIND_INVALIDATE_FULL); D3D12_BIND_INVALIDATE_FULL);
d3d12_apply_resource_states(ctx); d3d12_apply_resource_states(ctx, false);
d3d12_batch_reference_resource(batch, src, false); d3d12_batch_reference_resource(batch, src, false);
d3d12_batch_reference_resource(batch, dst, true); d3d12_batch_reference_resource(batch, dst, true);
@@ -826,7 +826,7 @@ blit_resolve_stencil(struct d3d12_context *ctx,
0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1,
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_BIND_INVALIDATE_FULL); D3D12_BIND_INVALIDATE_FULL);
d3d12_apply_resource_states(ctx); d3d12_apply_resource_states(ctx, false);
struct d3d12_batch *batch = d3d12_current_batch(ctx); struct d3d12_batch *batch = d3d12_current_batch(ctx);
d3d12_batch_reference_resource(batch, d3d12_resource(tmp), false); d3d12_batch_reference_resource(batch, d3d12_resource(tmp), false);

View File

@@ -141,6 +141,7 @@ d3d12_get_compute_transform(struct d3d12_context *ctx, const d3d12_compute_trans
return NULL; return NULL;
} }
data->shader->is_variant = true;
entry = _mesa_hash_table_insert(ctx->compute_transform_cache, &data->key, data); entry = _mesa_hash_table_insert(ctx->compute_transform_cache, &data->key, data);
assert(entry); assert(entry);
} }

View File

@@ -1906,9 +1906,9 @@ d3d12_transition_subresources_state(struct d3d12_context *ctx,
} }
void void
d3d12_apply_resource_states(struct d3d12_context *ctx) d3d12_apply_resource_states(struct d3d12_context *ctx, bool is_implicit_dispatch)
{ {
ctx->resource_state_manager->ApplyAllResourceTransitions(ctx->cmdlist, ctx->fence_value); ctx->resource_state_manager->ApplyAllResourceTransitions(ctx->cmdlist, ctx->fence_value, is_implicit_dispatch);
} }
static void static void
@@ -1929,7 +1929,7 @@ d3d12_clear_render_target(struct pipe_context *pctx,
d3d12_transition_resource_state(ctx, res, d3d12_transition_resource_state(ctx, res,
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_BIND_INVALIDATE_FULL); D3D12_BIND_INVALIDATE_FULL);
d3d12_apply_resource_states(ctx); d3d12_apply_resource_states(ctx, false);
enum pipe_format format = psurf->texture->format; enum pipe_format format = psurf->texture->format;
float clear_color[4]; float clear_color[4];
@@ -1988,7 +1988,7 @@ d3d12_clear_depth_stencil(struct pipe_context *pctx,
d3d12_transition_resource_state(ctx, res, d3d12_transition_resource_state(ctx, res,
D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_DEPTH_WRITE,
D3D12_BIND_INVALIDATE_FULL); D3D12_BIND_INVALIDATE_FULL);
d3d12_apply_resource_states(ctx); d3d12_apply_resource_states(ctx, false);
D3D12_RECT rect = { (int)dstx, (int)dsty, D3D12_RECT rect = { (int)dstx, (int)dsty,
(int)dstx + (int)width, (int)dstx + (int)width,
@@ -2057,7 +2057,7 @@ d3d12_flush_resource(struct pipe_context *pctx,
d3d12_transition_resource_state(ctx, res, d3d12_transition_resource_state(ctx, res,
D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COMMON,
D3D12_BIND_INVALIDATE_FULL); D3D12_BIND_INVALIDATE_FULL);
d3d12_apply_resource_states(ctx); d3d12_apply_resource_states(ctx, false);
} }
static void static void

View File

@@ -325,7 +325,7 @@ d3d12_transition_subresources_state(struct d3d12_context *ctx,
d3d12_bind_invalidate_option bind_invalidate); d3d12_bind_invalidate_option bind_invalidate);
void void
d3d12_apply_resource_states(struct d3d12_context* ctx); d3d12_apply_resource_states(struct d3d12_context* ctx, bool is_implicit_dispatch);
void void
d3d12_draw_vbo(struct pipe_context *pctx, d3d12_draw_vbo(struct pipe_context *pctx,

View File

@@ -1174,7 +1174,7 @@ d3d12_draw_vbo(struct pipe_context *pctx,
assert(!indirect->count_from_stream_output); assert(!indirect->count_from_stream_output);
} }
d3d12_apply_resource_states(ctx); d3d12_apply_resource_states(ctx, false);
for (unsigned i = 0; i < num_root_descriptors; ++i) for (unsigned i = 0; i < num_root_descriptors; ++i)
ctx->cmdlist->SetGraphicsRootDescriptorTable(root_desc_indices[i], root_desc_tables[i]); ctx->cmdlist->SetGraphicsRootDescriptorTable(root_desc_indices[i], root_desc_tables[i]);
@@ -1278,7 +1278,7 @@ d3d12_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info)
int root_desc_indices[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);
d3d12_apply_resource_states(ctx); d3d12_apply_resource_states(ctx, ctx->compute_state->is_variant);
for (unsigned i = 0; i < num_root_descriptors; ++i) for (unsigned i = 0; i < num_root_descriptors; ++i)
ctx->cmdlist->SetComputeRootDescriptorTable(root_desc_indices[i], root_desc_tables[i]); ctx->cmdlist->SetComputeRootDescriptorTable(root_desc_indices[i], root_desc_tables[i]);

View File

@@ -377,7 +377,7 @@ end_query(struct d3d12_context *ctx, struct d3d12_query *q)
offset += q->buffer_offset + resolve_index * q->query_size; offset += q->buffer_offset + resolve_index * q->query_size;
ctx->cmdlist->EndQuery(q->query_heap, q->d3d12qtype, end_index); ctx->cmdlist->EndQuery(q->query_heap, q->d3d12qtype, end_index);
d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_BIND_INVALIDATE_FULL); d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_BIND_INVALIDATE_FULL);
d3d12_apply_resource_states(ctx); d3d12_apply_resource_states(ctx, false);
ctx->cmdlist->ResolveQueryData(q->query_heap, q->d3d12qtype, resolve_index, ctx->cmdlist->ResolveQueryData(q->query_heap, q->d3d12qtype, resolve_index,
resolve_count, d3d12_res, offset); resolve_count, d3d12_res, offset);
@@ -494,13 +494,13 @@ d3d12_render_condition(struct pipe_context *pctx,
struct d3d12_resource *res = (struct d3d12_resource *)query->buffer; struct d3d12_resource *res = (struct d3d12_resource *)query->buffer;
d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_BIND_INVALIDATE_FULL); d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_BIND_INVALIDATE_FULL);
d3d12_transition_resource_state(ctx, query->predicate, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_BIND_INVALIDATE_NONE); d3d12_transition_resource_state(ctx, query->predicate, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_BIND_INVALIDATE_NONE);
d3d12_apply_resource_states(ctx); d3d12_apply_resource_states(ctx, false);
ctx->cmdlist->CopyBufferRegion(d3d12_resource_resource(query->predicate), 0, ctx->cmdlist->CopyBufferRegion(d3d12_resource_resource(query->predicate), 0,
d3d12_resource_resource(res), 0, d3d12_resource_resource(res), 0,
sizeof(uint64_t)); sizeof(uint64_t));
d3d12_transition_resource_state(ctx, query->predicate, D3D12_RESOURCE_STATE_PREDICATION, D3D12_BIND_INVALIDATE_NONE); d3d12_transition_resource_state(ctx, query->predicate, D3D12_RESOURCE_STATE_PREDICATION, D3D12_BIND_INVALIDATE_NONE);
d3d12_apply_resource_states(ctx); d3d12_apply_resource_states(ctx, false);
ctx->current_predication = query->predicate; ctx->current_predication = query->predicate;
ctx->predication_condition = condition; ctx->predication_condition = condition;

View File

@@ -699,7 +699,7 @@ copy_texture_region(struct d3d12_context *ctx,
d3d12_batch_reference_resource(batch, info.dst, true); d3d12_batch_reference_resource(batch, info.dst, true);
d3d12_transition_resource_state(ctx, info.src, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_BIND_INVALIDATE_FULL); d3d12_transition_resource_state(ctx, info.src, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_BIND_INVALIDATE_FULL);
d3d12_transition_resource_state(ctx, info.dst, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_BIND_INVALIDATE_FULL); d3d12_transition_resource_state(ctx, info.dst, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_BIND_INVALIDATE_FULL);
d3d12_apply_resource_states(ctx); d3d12_apply_resource_states(ctx, false);
ctx->cmdlist->CopyTextureRegion(&info.dst_loc, info.dst_x, info.dst_y, info.dst_z, ctx->cmdlist->CopyTextureRegion(&info.dst_loc, info.dst_x, info.dst_y, info.dst_z,
&info.src_loc, info.src_box); &info.src_loc, info.src_box);
} }
@@ -890,7 +890,7 @@ transfer_buf_to_buf(struct d3d12_context *ctx,
assert(src_d3d12 != dst_d3d12); assert(src_d3d12 != dst_d3d12);
d3d12_transition_resource_state(ctx, src, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_BIND_INVALIDATE_FULL); d3d12_transition_resource_state(ctx, src, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_BIND_INVALIDATE_FULL);
d3d12_transition_resource_state(ctx, dst, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_BIND_INVALIDATE_FULL); d3d12_transition_resource_state(ctx, dst, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_BIND_INVALIDATE_FULL);
d3d12_apply_resource_states(ctx); d3d12_apply_resource_states(ctx, false);
ctx->cmdlist->CopyBufferRegion(dst_d3d12, dst_offset, ctx->cmdlist->CopyBufferRegion(dst_d3d12, dst_offset,
src_d3d12, src_offset, src_d3d12, src_offset,
width); width);

View File

@@ -191,8 +191,9 @@ void ResourceStateManager::TransitionSubresource(TransitionableResourceState& Re
} }
//---------------------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------------------
void ResourceStateManager::ApplyResourceTransitionsPreamble() void ResourceStateManager::ApplyResourceTransitionsPreamble(bool IsImplicitDispatch)
{ {
m_IsImplicitDispatch = IsImplicitDispatch;
m_vResourceBarriers.clear(); m_vResourceBarriers.clear();
} }
@@ -335,7 +336,15 @@ void ResourceStateManager::ProcessTransitioningSubresourceExplicit(
if ( D3D12_RESOURCE_STATE_COMMON == StateIfPromoted ) if ( D3D12_RESOURCE_STATE_COMMON == StateIfPromoted )
{ {
if (TransitionRequired(CurrentLogicalState.State, /*inout*/ after)) if (CurrentLogicalState.State == D3D12_RESOURCE_STATE_UNORDERED_ACCESS &&
after == D3D12_RESOURCE_STATE_UNORDERED_ACCESS &&
m_IsImplicitDispatch)
{
D3D12_RESOURCE_BARRIER UAVBarrier = { D3D12_RESOURCE_BARRIER_TYPE_UAV };
UAVBarrier.UAV.pResource = TransitionDesc.Transition.pResource;
m_vResourceBarriers.push_back(UAVBarrier);
}
else if (TransitionRequired(CurrentLogicalState.State, /*inout*/ after))
{ {
// Insert a single concrete barrier (for non-simultaneous access resources). // Insert a single concrete barrier (for non-simultaneous access resources).
TransitionDesc.Transition.StateBefore = D3D12_RESOURCE_STATES(CurrentLogicalState.State); TransitionDesc.Transition.StateBefore = D3D12_RESOURCE_STATES(CurrentLogicalState.State);
@@ -388,9 +397,9 @@ void ResourceStateManager::TransitionSubresource(TransitionableResourceState* pR
} }
//---------------------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------------------
void ResourceStateManager::ApplyAllResourceTransitions(ID3D12GraphicsCommandList *pCommandList, UINT64 ExecutionId) void ResourceStateManager::ApplyAllResourceTransitions(ID3D12GraphicsCommandList *pCommandList, UINT64 ExecutionId, bool IsImplicitDispatch)
{ {
ApplyResourceTransitionsPreamble(); ApplyResourceTransitionsPreamble(IsImplicitDispatch);
ForEachTransitioningResource([=](TransitionableResourceState& ResourceBase) ForEachTransitioningResource([=](TransitionableResourceState& ResourceBase)
{ {

View File

@@ -211,6 +211,7 @@ protected:
struct list_head m_TransitionListHead; struct list_head m_TransitionListHead;
std::vector<D3D12_RESOURCE_BARRIER> m_vResourceBarriers; std::vector<D3D12_RESOURCE_BARRIER> m_vResourceBarriers;
bool m_IsImplicitDispatch;
public: public:
ResourceStateManager(); ResourceStateManager();
@@ -234,7 +235,7 @@ public:
D3D12_RESOURCE_STATES State); D3D12_RESOURCE_STATES State);
// Submit all barriers and queue sync. // Submit all barriers and queue sync.
void ApplyAllResourceTransitions(ID3D12GraphicsCommandList *pCommandList, UINT64 ExecutionId); void ApplyAllResourceTransitions(ID3D12GraphicsCommandList *pCommandList, UINT64 ExecutionId, bool IsImplicitDispatch);
private: private:
// These methods set the destination state of the resource/subresources and ensure it's in the transition list. // These methods set the destination state of the resource/subresources and ensure it's in the transition list.
@@ -245,7 +246,7 @@ private:
D3D12_RESOURCE_STATES State); D3D12_RESOURCE_STATES State);
// Clear out any state from previous iterations. // Clear out any state from previous iterations.
void ApplyResourceTransitionsPreamble(); void ApplyResourceTransitionsPreamble(bool IsImplicitDispatch);
// What to do with the resource, in the context of the transition list, after processing it. // What to do with the resource, in the context of the transition list, after processing it.
enum class TransitionResult enum class TransitionResult