return false;
}
batch->has_errors = false;
+ batch->pending_memory_barrier = false;
return true;
}
struct d3d12_descriptor_heap *sampler_heap;
struct d3d12_descriptor_heap *view_heap;
bool has_errors;
+ bool pending_memory_barrier;
};
bool
d3d12_bo_unreference(old_bo);
}
+static void
+d3d12_memory_barrier(struct pipe_context *pctx, unsigned flags)
+{
+ struct d3d12_context *ctx = d3d12_context(pctx);
+ if (flags & PIPE_BARRIER_VERTEX_BUFFER)
+ ctx->state_dirty |= D3D12_DIRTY_VERTEX_BUFFERS;
+ if (flags & PIPE_BARRIER_INDEX_BUFFER)
+ ctx->state_dirty |= D3D12_DIRTY_INDEX_BUFFER;
+ if (flags & PIPE_BARRIER_FRAMEBUFFER)
+ ctx->state_dirty |= D3D12_DIRTY_FRAMEBUFFER;
+ if (flags & PIPE_BARRIER_STREAMOUT_BUFFER)
+ ctx->state_dirty |= D3D12_DIRTY_STREAM_OUTPUT;
+
+ /* TODO:
+ * PIPE_BARRIER_INDIRECT_BUFFER
+ */
+
+ for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) {
+ if (flags & PIPE_BARRIER_CONSTANT_BUFFER)
+ ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_CONSTBUF;
+ if (flags & PIPE_BARRIER_TEXTURE)
+ ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS;
+ if (flags & PIPE_BARRIER_SHADER_BUFFER)
+ ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SSBO;
+ if (flags & PIPE_BARRIER_IMAGE)
+ ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_IMAGE;
+ }
+
+ /* Indicate that UAVs shouldn't override transitions. Ignore barriers that are only
+ * for UAVs or other fixed-function state that doesn't need a draw to resolve.
+ */
+ const unsigned ignored_barrier_flags =
+ PIPE_BARRIER_IMAGE |
+ PIPE_BARRIER_SHADER_BUFFER |
+ PIPE_BARRIER_UPDATE |
+ PIPE_BARRIER_MAPPED_BUFFER |
+ PIPE_BARRIER_QUERY_BUFFER;
+ d3d12_current_batch(ctx)->pending_memory_barrier = (flags & ~ignored_barrier_flags) != 0;
+
+ if (flags & (PIPE_BARRIER_IMAGE | PIPE_BARRIER_SHADER_BUFFER)) {
+ D3D12_RESOURCE_BARRIER uavBarrier;
+ uavBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
+ uavBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ uavBarrier.UAV.pResource = nullptr;
+ ctx->cmdlist->ResourceBarrier(1, &uavBarrier);
+ }
+}
+
struct pipe_context *
d3d12_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
{
ctx->base.flush = d3d12_flush;
ctx->base.flush_resource = d3d12_flush_resource;
+ ctx->base.memory_barrier = d3d12_memory_barrier;
+
ctx->gfx_pipeline_state.sample_mask = ~0;
d3d12_context_surface_init(&ctx->base);
unreachable("Unexpected image view dimension");
}
- if (res->base.b.target == PIPE_BUFFER) {
- d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_BIND_INVALIDATE_NONE);
- } else {
- unsigned transition_first_layer = view->u.tex.first_layer;
- unsigned transition_array_size = array_size;
- if (res->base.b.target == PIPE_TEXTURE_3D) {
- transition_first_layer = 0;
- transition_array_size = 0;
+ if (!batch->pending_memory_barrier) {
+ if (res->base.b.target == PIPE_BUFFER) {
+ d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_BIND_INVALIDATE_NONE);
+ } else {
+ unsigned transition_first_layer = view->u.tex.first_layer;
+ unsigned transition_array_size = array_size;
+ if (res->base.b.target == PIPE_TEXTURE_3D) {
+ transition_first_layer = 0;
+ transition_array_size = 0;
+ }
+ d3d12_transition_subresources_state(ctx, res,
+ view->u.tex.level, 1,
+ transition_first_layer, transition_array_size,
+ 0, 1,
+ D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
+ D3D12_BIND_INVALIDATE_NONE);
}
- d3d12_transition_subresources_state(ctx, res,
- view->u.tex.level, 1,
- transition_first_layer, transition_array_size,
- 0, 1,
- D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
- D3D12_BIND_INVALIDATE_NONE);
}
d3d12_batch_reference_resource(batch, res, true);
draws[0].start, dinfo->start_instance);
ctx->state_dirty = 0;
+ batch->pending_memory_barrier = false;
if (index_buffer)
ctx->cmdlist_dirty = 0;
continue;
}
+ // This is a transition into a state that is both write and non-write.
+ // This is invalid according to D3D12. We're venturing into undefined behavior
+ // land, but let's just pick the write state.
+ if (IsD3D12WriteState(after) &&
+ (after & ~RESOURCE_STATE_ALL_WRITE_BITS) != 0)
+ {
+ after &= RESOURCE_STATE_ALL_WRITE_BITS;
+
+ // For now, this is the only way I've seen where this can happen.
+ assert(after == D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
+ }
+
ProcessTransitioningSubresourceExplicit(
CurrentState,
i,