d3d12: Refactor graphics functions from context and blit to separate files
Reviewed-by: Jesse Natalie <jenatali@microsoft.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27997>
This commit is contained in:
@@ -313,12 +313,15 @@ d3d12_end_batch(struct d3d12_context *ctx, struct d3d12_batch *batch)
|
||||
batch->fence = d3d12_create_fence(screen);
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
set_foreach_remove(batch->queries, entry) {
|
||||
d3d12_query *query = (struct d3d12_query *)entry->key;
|
||||
if (pipe_reference(&query->reference, nullptr))
|
||||
d3d12_destroy_query(query);
|
||||
else
|
||||
query->fence_value = screen->fence_value;
|
||||
/* batch->queries is NULL when no grfx supported */
|
||||
if (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0) {
|
||||
set_foreach_remove(batch->queries, entry) {
|
||||
d3d12_query *query = (struct d3d12_query *)entry->key;
|
||||
if (pipe_reference(&query->reference, nullptr))
|
||||
d3d12_destroy_query(query);
|
||||
else
|
||||
query->fence_value = screen->fence_value;
|
||||
}
|
||||
}
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include "d3d12_context.h"
|
||||
#include "d3d12_compiler.h"
|
||||
#include "d3d12_debug.h"
|
||||
#include "d3d12_blit.h"
|
||||
#include "d3d12_format.h"
|
||||
#include "d3d12_query.h"
|
||||
#include "d3d12_resource.h"
|
||||
@@ -35,23 +36,6 @@
|
||||
#include "nir_to_dxil.h"
|
||||
#include "nir_builder.h"
|
||||
|
||||
static void
|
||||
copy_buffer_region_no_barriers(struct d3d12_context *ctx,
|
||||
struct d3d12_resource *dst,
|
||||
uint64_t dst_offset,
|
||||
struct d3d12_resource *src,
|
||||
uint64_t src_offset,
|
||||
uint64_t size)
|
||||
{
|
||||
uint64_t dst_off, src_off;
|
||||
ID3D12Resource *dst_buf = d3d12_resource_underlying(dst, &dst_off);
|
||||
ID3D12Resource *src_buf = d3d12_resource_underlying(src, &src_off);
|
||||
|
||||
ctx->cmdlist->CopyBufferRegion(dst_buf, dst_offset + dst_off,
|
||||
src_buf, src_offset + src_off,
|
||||
size);
|
||||
}
|
||||
|
||||
static bool
|
||||
is_resolve(const struct pipe_blit_info *info)
|
||||
{
|
||||
@@ -253,203 +237,6 @@ direct_copy_supported(struct d3d12_screen *screen,
|
||||
return true;
|
||||
}
|
||||
|
||||
inline static unsigned
|
||||
get_subresource_id(enum pipe_texture_target target, unsigned subres, unsigned stride,
|
||||
unsigned z, unsigned *updated_z, unsigned array_size, unsigned plane_slice)
|
||||
{
|
||||
if (d3d12_subresource_id_uses_layer(target)) {
|
||||
subres += stride * z;
|
||||
if (updated_z)
|
||||
*updated_z = 0;
|
||||
}
|
||||
return subres + plane_slice * array_size * stride;
|
||||
}
|
||||
|
||||
static void
|
||||
copy_subregion_no_barriers(struct d3d12_context *ctx,
|
||||
struct d3d12_resource *dst,
|
||||
unsigned dst_level,
|
||||
unsigned dstx, unsigned dsty, unsigned dstz,
|
||||
struct d3d12_resource *src,
|
||||
unsigned src_level,
|
||||
const struct pipe_box *psrc_box,
|
||||
unsigned mask)
|
||||
{
|
||||
UNUSED struct d3d12_screen *screen = d3d12_screen(ctx->base.screen);
|
||||
D3D12_TEXTURE_COPY_LOCATION src_loc, dst_loc;
|
||||
unsigned src_z = psrc_box->z;
|
||||
|
||||
int src_subres_stride = src->base.b.last_level + 1;
|
||||
int dst_subres_stride = dst->base.b.last_level + 1;
|
||||
|
||||
int src_array_size = src->base.b.array_size;
|
||||
int dst_array_size = dst->base.b.array_size;
|
||||
|
||||
int stencil_src_res_offset = 1;
|
||||
int stencil_dst_res_offset = 1;
|
||||
|
||||
int src_nres = 1;
|
||||
int dst_nres = 1;
|
||||
|
||||
if (dst->base.b.format == PIPE_FORMAT_Z24_UNORM_S8_UINT ||
|
||||
dst->base.b.format == PIPE_FORMAT_S8_UINT_Z24_UNORM ||
|
||||
dst->base.b.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) {
|
||||
stencil_dst_res_offset = dst_subres_stride * dst_array_size;
|
||||
src_nres = 2;
|
||||
}
|
||||
|
||||
if (src->base.b.format == PIPE_FORMAT_Z24_UNORM_S8_UINT ||
|
||||
src->base.b.format == PIPE_FORMAT_S8_UINT_Z24_UNORM ||
|
||||
dst->base.b.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) {
|
||||
stencil_src_res_offset = src_subres_stride * src_array_size;
|
||||
dst_nres = 2;
|
||||
}
|
||||
|
||||
static_assert(PIPE_MASK_S == 0x20 && PIPE_MASK_Z == 0x10, "unexpected ZS format mask");
|
||||
int nsubres = MIN2(src_nres, dst_nres);
|
||||
unsigned subresource_copy_mask = nsubres > 1 ? mask >> 4 : 1;
|
||||
|
||||
for (int subres = 0; subres < nsubres; ++subres) {
|
||||
|
||||
if (!(subresource_copy_mask & (1 << subres)))
|
||||
continue;
|
||||
|
||||
src_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
src_loc.SubresourceIndex = get_subresource_id(src->base.b.target, src_level, src_subres_stride, src_z, &src_z, src_array_size, src->plane_slice) +
|
||||
subres * stencil_src_res_offset;
|
||||
src_loc.pResource = d3d12_resource_resource(src);
|
||||
|
||||
dst_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
dst_loc.SubresourceIndex = get_subresource_id(dst->base.b.target, dst_level, dst_subres_stride, dstz, &dstz, dst_array_size, dst->plane_slice) +
|
||||
subres * stencil_dst_res_offset;
|
||||
dst_loc.pResource = d3d12_resource_resource(dst);
|
||||
|
||||
if (psrc_box->x == 0 && psrc_box->y == 0 && psrc_box->z == 0 &&
|
||||
psrc_box->width == (int)u_minify(src->base.b.width0, src_level) &&
|
||||
psrc_box->height == (int)u_minify(src->base.b.height0, src_level) &&
|
||||
psrc_box->depth == (int)u_minify(src->base.b.depth0, src_level)) {
|
||||
|
||||
assert((dstx == 0 && dsty == 0 && dstz == 0) ||
|
||||
screen->opts2.ProgrammableSamplePositionsTier !=
|
||||
D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED ||
|
||||
(!util_format_is_depth_or_stencil(dst->base.b.format) &&
|
||||
!util_format_is_depth_or_stencil(src->base.b.format) &&
|
||||
dst->base.b.nr_samples == src->base.b.nr_samples));
|
||||
|
||||
ctx->cmdlist->CopyTextureRegion(&dst_loc, dstx, dsty, dstz,
|
||||
&src_loc, NULL);
|
||||
|
||||
} else {
|
||||
D3D12_BOX src_box;
|
||||
src_box.left = psrc_box->x;
|
||||
src_box.right = MIN2(psrc_box->x + psrc_box->width, (int)u_minify(src->base.b.width0, src_level));
|
||||
src_box.top = psrc_box->y;
|
||||
src_box.bottom = MIN2(psrc_box->y + psrc_box->height, (int)u_minify(src->base.b.height0, src_level));
|
||||
src_box.front = src_z;
|
||||
src_box.back = src_z + psrc_box->depth;
|
||||
|
||||
assert((screen->opts2.ProgrammableSamplePositionsTier !=
|
||||
D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED ||
|
||||
(!util_format_is_depth_or_stencil(dst->base.b.format) &&
|
||||
!util_format_is_depth_or_stencil(src->base.b.format))) &&
|
||||
dst->base.b.nr_samples == src->base.b.nr_samples);
|
||||
|
||||
ctx->cmdlist->CopyTextureRegion(&dst_loc, dstx, dsty, dstz,
|
||||
&src_loc, &src_box);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
copy_resource_y_flipped_no_barriers(struct d3d12_context *ctx,
|
||||
struct d3d12_resource *dst,
|
||||
unsigned dst_level,
|
||||
const struct pipe_box *pdst_box,
|
||||
struct d3d12_resource *src,
|
||||
unsigned src_level,
|
||||
const struct pipe_box *psrc_box,
|
||||
unsigned mask)
|
||||
{
|
||||
if (D3D12_DEBUG_BLIT & d3d12_debug) {
|
||||
debug_printf("D3D12 BLIT as COPY: from %s@%d %dx%dx%d + %dx%dx%d\n",
|
||||
util_format_name(src->base.b.format), src_level,
|
||||
psrc_box->x, psrc_box->y, psrc_box->z,
|
||||
psrc_box->width, psrc_box->height, psrc_box->depth);
|
||||
debug_printf(" to %s@%d %dx%dx%d\n",
|
||||
util_format_name(dst->base.b.format), dst_level,
|
||||
pdst_box->x, pdst_box->y, pdst_box->z);
|
||||
}
|
||||
|
||||
struct pipe_box src_box = *psrc_box;
|
||||
int src_inc = psrc_box->height > 0 ? 1 : -1;
|
||||
int dst_inc = pdst_box->height > 0 ? 1 : -1;
|
||||
src_box.height = 1;
|
||||
int rows_to_copy = abs(psrc_box->height);
|
||||
|
||||
if (psrc_box->height < 0)
|
||||
--src_box.y;
|
||||
|
||||
for (int y = 0, dest_y = pdst_box->y; y < rows_to_copy;
|
||||
++y, src_box.y += src_inc, dest_y += dst_inc) {
|
||||
copy_subregion_no_barriers(ctx, dst, dst_level,
|
||||
pdst_box->x, dest_y, pdst_box->z,
|
||||
src, src_level, &src_box, mask);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
d3d12_direct_copy(struct d3d12_context *ctx,
|
||||
struct d3d12_resource *dst,
|
||||
unsigned dst_level,
|
||||
const struct pipe_box *pdst_box,
|
||||
struct d3d12_resource *src,
|
||||
unsigned src_level,
|
||||
const struct pipe_box *psrc_box,
|
||||
unsigned mask)
|
||||
{
|
||||
struct d3d12_batch *batch = d3d12_current_batch(ctx);
|
||||
|
||||
unsigned src_subres = get_subresource_id(src->base.b.target, src_level, src->base.b.last_level + 1,
|
||||
psrc_box->z, nullptr, src->base.b.array_size, src->plane_slice);
|
||||
unsigned dst_subres = get_subresource_id(dst->base.b.target, dst_level, dst->base.b.last_level + 1,
|
||||
pdst_box->z, nullptr, dst->base.b.array_size, dst->plane_slice);
|
||||
|
||||
if (D3D12_DEBUG_BLIT & d3d12_debug)
|
||||
debug_printf("BLIT: Direct copy from subres %d to subres %d\n",
|
||||
src_subres, dst_subres);
|
||||
|
||||
d3d12_transition_subresources_state(ctx, src, src_subres, 1, 0, 1,
|
||||
d3d12_get_format_start_plane(src->base.b.format),
|
||||
d3d12_get_format_num_planes(src->base.b.format),
|
||||
D3D12_RESOURCE_STATE_COPY_SOURCE,
|
||||
D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
|
||||
|
||||
d3d12_transition_subresources_state(ctx, dst, dst_subres, 1, 0, 1,
|
||||
d3d12_get_format_start_plane(dst->base.b.format),
|
||||
d3d12_get_format_num_planes(dst->base.b.format),
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
|
||||
|
||||
d3d12_apply_resource_states(ctx, false);
|
||||
|
||||
d3d12_batch_reference_resource(batch, src, false);
|
||||
d3d12_batch_reference_resource(batch, dst, true);
|
||||
|
||||
if (src->base.b.target == PIPE_BUFFER) {
|
||||
copy_buffer_region_no_barriers(ctx, dst, pdst_box->x,
|
||||
src, psrc_box->x, psrc_box->width);
|
||||
} else if (psrc_box->height == pdst_box->height) {
|
||||
/* No flipping, we can forward this directly to resource_copy_region */
|
||||
copy_subregion_no_barriers(ctx, dst, dst_level,
|
||||
pdst_box->x, pdst_box->y, pdst_box->z,
|
||||
src, src_level, psrc_box, mask);
|
||||
} else {
|
||||
assert(psrc_box->height == -pdst_box->height);
|
||||
copy_resource_y_flipped_no_barriers(ctx, dst, dst_level, pdst_box,
|
||||
src, src_level, psrc_box, mask);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
is_same_resource(const struct pipe_blit_info *info)
|
||||
{
|
||||
@@ -458,66 +245,6 @@ is_same_resource(const struct pipe_blit_info *info)
|
||||
info->src.level == info->dst.level;
|
||||
}
|
||||
|
||||
static struct pipe_resource *
|
||||
create_staging_resource(struct d3d12_context *ctx,
|
||||
struct d3d12_resource *src,
|
||||
unsigned src_level,
|
||||
const struct pipe_box *src_box,
|
||||
struct pipe_box *dst_box,
|
||||
unsigned mask)
|
||||
|
||||
{
|
||||
struct pipe_resource templ = {};
|
||||
struct pipe_resource *staging_res;
|
||||
struct pipe_box copy_src;
|
||||
|
||||
u_box_3d(MIN2(src_box->x, src_box->x + src_box->width),
|
||||
MIN2(src_box->y, src_box->y + src_box->height),
|
||||
MIN2(src_box->z, src_box->z + src_box->depth),
|
||||
abs(src_box->width), abs(src_box->height), abs(src_box->depth),
|
||||
©_src);
|
||||
|
||||
templ.format = src->base.b.format;
|
||||
templ.width0 = copy_src.width;
|
||||
templ.height0 = copy_src.height;
|
||||
templ.depth0 = copy_src.depth;
|
||||
templ.array_size = 1;
|
||||
templ.nr_samples = src->base.b.nr_samples;
|
||||
templ.nr_storage_samples = src->base.b.nr_storage_samples;
|
||||
templ.usage = PIPE_USAGE_STAGING;
|
||||
templ.bind = util_format_is_depth_or_stencil(templ.format) ? PIPE_BIND_DEPTH_STENCIL :
|
||||
util_format_is_compressed(templ.format) ? 0 : PIPE_BIND_RENDER_TARGET;
|
||||
templ.target = src->base.b.target;
|
||||
|
||||
staging_res = ctx->base.screen->resource_create(ctx->base.screen, &templ);
|
||||
|
||||
dst_box->x = 0;
|
||||
dst_box->y = 0;
|
||||
dst_box->z = 0;
|
||||
dst_box->width = copy_src.width;
|
||||
dst_box->height = copy_src.height;
|
||||
dst_box->depth = copy_src.depth;
|
||||
|
||||
d3d12_direct_copy(ctx, d3d12_resource(staging_res), 0, dst_box,
|
||||
src, src_level, ©_src, mask);
|
||||
|
||||
if (src_box->width < 0) {
|
||||
dst_box->x = dst_box->width;
|
||||
dst_box->width = src_box->width;
|
||||
}
|
||||
|
||||
if (src_box->height < 0) {
|
||||
dst_box->y = dst_box->height;
|
||||
dst_box->height = src_box->height;
|
||||
}
|
||||
|
||||
if (src_box->depth < 0) {
|
||||
dst_box->z = dst_box->depth;
|
||||
dst_box->depth = src_box->depth;
|
||||
}
|
||||
return staging_res;
|
||||
}
|
||||
|
||||
static void
|
||||
blit_same_resource(struct d3d12_context *ctx,
|
||||
const struct pipe_blit_info *info)
|
||||
@@ -951,7 +678,6 @@ d3d12_blit(struct pipe_context *pctx,
|
||||
util_format_short_name(info->src.resource->format),
|
||||
util_format_short_name(info->dst.resource->format));
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
if (d3d12_screen(pctx->screen)->max_feature_level >= D3D_FEATURE_LEVEL_11_0) {
|
||||
if (!info->render_condition_enable && ctx->current_predication) {
|
||||
d3d12_enable_predication(ctx);
|
||||
@@ -959,61 +685,10 @@ d3d12_blit(struct pipe_context *pctx,
|
||||
debug_printf("D3D12 BLIT: Re-enable predication\n");
|
||||
}
|
||||
}
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_resource_copy_region(struct pipe_context *pctx,
|
||||
struct pipe_resource *pdst,
|
||||
unsigned dst_level,
|
||||
unsigned dstx, unsigned dsty, unsigned dstz,
|
||||
struct pipe_resource *psrc,
|
||||
unsigned src_level,
|
||||
const struct pipe_box *psrc_box)
|
||||
{
|
||||
struct d3d12_context *ctx = d3d12_context(pctx);
|
||||
struct d3d12_resource *dst = d3d12_resource(pdst);
|
||||
struct d3d12_resource *src = d3d12_resource(psrc);
|
||||
struct pipe_resource *staging_res = NULL;
|
||||
const struct pipe_box *src_box = psrc_box;
|
||||
struct pipe_box staging_box, dst_box;
|
||||
|
||||
if (D3D12_DEBUG_BLIT & d3d12_debug) {
|
||||
debug_printf("D3D12 COPY: from %s@%d msaa:%d mips:%d %dx%dx%d + %dx%dx%d\n",
|
||||
util_format_name(psrc->format), src_level, psrc->nr_samples,
|
||||
psrc->last_level,
|
||||
psrc_box->x, psrc_box->y, psrc_box->z,
|
||||
psrc_box->width, psrc_box->height, psrc_box->depth);
|
||||
debug_printf(" to %s@%d msaa:%d mips:%d %dx%dx%d\n",
|
||||
util_format_name(pdst->format), dst_level, psrc->nr_samples,
|
||||
psrc->last_level, dstx, dsty, dstz);
|
||||
}
|
||||
|
||||
/* Use an intermediate resource if copying from/to the same subresource */
|
||||
if (d3d12_resource_resource(dst) == d3d12_resource_resource(src) && dst_level == src_level) {
|
||||
staging_res = create_staging_resource(ctx, src, src_level, psrc_box, &staging_box, PIPE_MASK_RGBAZS);
|
||||
src = d3d12_resource(staging_res);
|
||||
src_level = 0;
|
||||
src_box = &staging_box;
|
||||
}
|
||||
|
||||
dst_box.x = dstx;
|
||||
dst_box.y = dsty;
|
||||
dst_box.z = dstz;
|
||||
dst_box.width = psrc_box->width;
|
||||
dst_box.height = psrc_box->height;
|
||||
|
||||
d3d12_direct_copy(ctx, dst, dst_level, &dst_box,
|
||||
src, src_level, src_box, PIPE_MASK_RGBAZS);
|
||||
|
||||
if (staging_res)
|
||||
pipe_resource_reference(&staging_res, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
d3d12_context_blit_init(struct pipe_context *ctx)
|
||||
{
|
||||
ctx->resource_copy_region = d3d12_resource_copy_region;
|
||||
ctx->blit = d3d12_blit;
|
||||
}
|
||||
|
@@ -31,6 +31,9 @@ struct pipe_box;
|
||||
void
|
||||
d3d12_context_blit_init(struct pipe_context *ctx);
|
||||
|
||||
void
|
||||
d3d12_context_copy_init(struct pipe_context *ctx);
|
||||
|
||||
void
|
||||
d3d12_direct_copy(struct d3d12_context *ctx,
|
||||
struct d3d12_resource *dst,
|
||||
@@ -40,4 +43,12 @@ d3d12_direct_copy(struct d3d12_context *ctx,
|
||||
unsigned src_level,
|
||||
const struct pipe_box *psrc_box, unsigned mask);
|
||||
|
||||
struct pipe_resource *
|
||||
create_staging_resource(struct d3d12_context *ctx,
|
||||
struct d3d12_resource *src,
|
||||
unsigned src_level,
|
||||
const struct pipe_box *src_box,
|
||||
struct pipe_box *dst_box,
|
||||
unsigned mask);
|
||||
|
||||
#endif // D3D12_BLIT_H
|
||||
|
@@ -168,8 +168,30 @@ struct d3d12_context {
|
||||
struct slab_child_pool transfer_pool_unsync;
|
||||
struct list_head context_list_entry;
|
||||
struct threaded_context *threaded_context;
|
||||
struct primconvert_context *primconvert;
|
||||
struct d3d12_batch batches[8];
|
||||
unsigned current_batch_idx;
|
||||
struct util_dynarray recently_destroyed_bos;
|
||||
struct util_dynarray barrier_scratch;
|
||||
struct set *pending_barriers_bos;
|
||||
struct util_dynarray local_pending_barriers_bos;
|
||||
uint64_t submit_id;
|
||||
ID3D12GraphicsCommandList *cmdlist;
|
||||
ID3D12GraphicsCommandList2 *cmdlist2;
|
||||
ID3D12GraphicsCommandList8 *cmdlist8;
|
||||
ID3D12GraphicsCommandList *state_fixup_cmdlist;
|
||||
struct hash_table_u64 *bo_state_table;
|
||||
struct blitter_context *blitter;
|
||||
uint flags;
|
||||
bool queries_disabled;
|
||||
|
||||
#ifdef __cplusplus
|
||||
ResourceStateManager *resource_state_manager;
|
||||
#else
|
||||
void *resource_state_manager; /* opaque pointer; we don't know about classes in C */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
struct primconvert_context *primconvert;
|
||||
struct u_suballocator query_allocator;
|
||||
struct u_suballocator so_allocator;
|
||||
struct hash_table *pso_cache;
|
||||
@@ -179,15 +201,6 @@ struct d3d12_context {
|
||||
struct hash_table *gs_variant_cache;
|
||||
struct hash_table *tcs_variant_cache;
|
||||
struct hash_table *compute_transform_cache;
|
||||
struct hash_table_u64 *bo_state_table;
|
||||
|
||||
struct d3d12_batch batches[8];
|
||||
unsigned current_batch_idx;
|
||||
|
||||
struct util_dynarray recently_destroyed_bos;
|
||||
struct util_dynarray barrier_scratch;
|
||||
struct set *pending_barriers_bos;
|
||||
struct util_dynarray local_pending_barriers_bos;
|
||||
|
||||
struct pipe_constant_buffer cbufs[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
|
||||
struct pipe_framebuffer_state fb;
|
||||
@@ -245,7 +258,6 @@ struct d3d12_context {
|
||||
bool has_flat_varyings;
|
||||
bool missing_dual_src_outputs;
|
||||
bool manual_depth_range;
|
||||
uint flags;
|
||||
|
||||
struct d3d12_gfx_pipeline_state gfx_pipeline_state;
|
||||
struct d3d12_compute_pipeline_state compute_pipeline_state;
|
||||
@@ -256,14 +268,7 @@ struct d3d12_context {
|
||||
ID3D12PipelineState *current_compute_pso;
|
||||
uint16_t reverse_depth_range;
|
||||
|
||||
uint64_t submit_id;
|
||||
ID3D12GraphicsCommandList *cmdlist;
|
||||
ID3D12GraphicsCommandList2 *cmdlist2;
|
||||
ID3D12GraphicsCommandList8 *cmdlist8;
|
||||
ID3D12GraphicsCommandList *state_fixup_cmdlist;
|
||||
|
||||
struct list_head active_queries;
|
||||
bool queries_disabled;
|
||||
|
||||
struct d3d12_descriptor_pool *sampler_pool;
|
||||
struct d3d12_descriptor_handle null_sampler;
|
||||
@@ -281,16 +286,11 @@ struct d3d12_context {
|
||||
bool queries_suspended;
|
||||
|
||||
uint32_t transform_state_vars[8];
|
||||
|
||||
#ifdef __cplusplus
|
||||
ResourceStateManager *resource_state_manager;
|
||||
#else
|
||||
void *resource_state_manager; /* opaque pointer; we don't know about classes in C */
|
||||
#endif
|
||||
struct pipe_query *timestamp_query;
|
||||
|
||||
/* used by d3d12_blit.cpp */
|
||||
void *stencil_resolve_vs, *stencil_resolve_fs, *stencil_resolve_fs_no_flip, *sampler_state;
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
};
|
||||
|
||||
static inline struct d3d12_context *
|
||||
@@ -384,6 +384,18 @@ d3d12_init_sampler_view_descriptor(struct d3d12_sampler_view *sampler_view);
|
||||
void
|
||||
d3d12_invalidate_context_bindings(struct d3d12_context *ctx, struct d3d12_resource *res);
|
||||
|
||||
void
|
||||
d3d12_rebind_buffer(struct d3d12_context *ctx, struct d3d12_resource *res);
|
||||
|
||||
void
|
||||
d3d12_init_null_sampler(struct d3d12_context *ctx);
|
||||
|
||||
bool
|
||||
d3d12_init_polygon_stipple(struct pipe_context *pctx);
|
||||
|
||||
void
|
||||
d3d12_init_graphics_context_functions(struct d3d12_context *ctx);
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_VIDEO
|
||||
struct pipe_video_codec* d3d12_video_create_codec( struct pipe_context *context,
|
||||
const struct pipe_video_codec *t);
|
||||
|
498
src/gallium/drivers/d3d12/d3d12_context_common.cpp
Normal file
498
src/gallium/drivers/d3d12/d3d12_context_common.cpp
Normal file
@@ -0,0 +1,498 @@
|
||||
/*
|
||||
* Copyright © Microsoft Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "d3d12_blit.h"
|
||||
#include "d3d12_cmd_signature.h"
|
||||
#include "d3d12_context.h"
|
||||
#include "d3d12_compiler.h"
|
||||
#include "d3d12_compute_transforms.h"
|
||||
#include "d3d12_debug.h"
|
||||
#include "d3d12_fence.h"
|
||||
#include "d3d12_format.h"
|
||||
#include "d3d12_query.h"
|
||||
#include "d3d12_resource.h"
|
||||
#include "d3d12_root_signature.h"
|
||||
#include "d3d12_screen.h"
|
||||
#include "d3d12_surface.h"
|
||||
#ifdef HAVE_GALLIUM_D3D12_VIDEO
|
||||
#include "d3d12_video_dec.h"
|
||||
#include "d3d12_video_enc.h"
|
||||
#include "d3d12_video_proc.h"
|
||||
#include "d3d12_video_buffer.h"
|
||||
#endif
|
||||
#include "indices/u_primconvert.h"
|
||||
#include "util/u_atomic.h"
|
||||
#include "util/u_blitter.h"
|
||||
#include "util/u_dual_blend.h"
|
||||
#include "util/u_framebuffer.h"
|
||||
#include "util/u_helpers.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_upload_mgr.h"
|
||||
#include "util/u_pstipple.h"
|
||||
#include "util/u_sample_positions.h"
|
||||
#include "util/u_dl.h"
|
||||
#include "nir_to_dxil.h"
|
||||
|
||||
#include <dxguids/dxguids.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "dxil_validator.h"
|
||||
#endif
|
||||
|
||||
static void
|
||||
d3d12_context_destroy(struct pipe_context *pctx)
|
||||
{
|
||||
struct d3d12_context *ctx = d3d12_context(pctx);
|
||||
|
||||
struct d3d12_screen *screen = d3d12_screen(pctx->screen);
|
||||
mtx_lock(&screen->submit_mutex);
|
||||
list_del(&ctx->context_list_entry);
|
||||
if (ctx->id != D3D12_CONTEXT_NO_ID)
|
||||
screen->context_id_list[screen->context_id_count++] = ctx->id;
|
||||
mtx_unlock(&screen->submit_mutex);
|
||||
|
||||
d3d12_end_batch(ctx, d3d12_current_batch(ctx));
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(ctx->batches); ++i)
|
||||
d3d12_destroy_batch(ctx, &ctx->batches[i]);
|
||||
ctx->cmdlist->Release();
|
||||
if (ctx->cmdlist2)
|
||||
ctx->cmdlist2->Release();
|
||||
if (ctx->cmdlist8)
|
||||
ctx->cmdlist8->Release();
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
if ((screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0) && !(ctx->flags & PIPE_CONTEXT_MEDIA_ONLY)) {
|
||||
#ifdef _WIN32
|
||||
dxil_destroy_validator(ctx->dxil_validator);
|
||||
#endif // _WIN32
|
||||
|
||||
#ifndef _GAMING_XBOX
|
||||
if (ctx->dev_config)
|
||||
ctx->dev_config->Release();
|
||||
#endif // _GAMING_XBOX
|
||||
|
||||
if (ctx->timestamp_query)
|
||||
pctx->destroy_query(pctx, ctx->timestamp_query);
|
||||
|
||||
util_unreference_framebuffer_state(&ctx->fb);
|
||||
util_blitter_destroy(ctx->blitter);
|
||||
d3d12_compute_pipeline_state_cache_destroy(ctx);
|
||||
d3d12_root_signature_cache_destroy(ctx);
|
||||
d3d12_cmd_signature_cache_destroy(ctx);
|
||||
d3d12_compute_transform_cache_destroy(ctx);
|
||||
d3d12_descriptor_pool_free(ctx->sampler_pool);
|
||||
d3d12_gs_variant_cache_destroy(ctx);
|
||||
d3d12_tcs_variant_cache_destroy(ctx);
|
||||
d3d12_gfx_pipeline_state_cache_destroy(ctx);
|
||||
util_primconvert_destroy(ctx->primconvert);
|
||||
pipe_resource_reference(&ctx->pstipple.texture, nullptr);
|
||||
pipe_sampler_view_reference(&ctx->pstipple.sampler_view, nullptr);
|
||||
util_dynarray_fini(&ctx->recently_destroyed_bos);
|
||||
FREE(ctx->pstipple.sampler_cso);
|
||||
if (pctx->stream_uploader)
|
||||
u_upload_destroy(pctx->stream_uploader);
|
||||
if (pctx->const_uploader)
|
||||
u_upload_destroy(pctx->const_uploader);
|
||||
if (!ctx->queries_disabled) {
|
||||
u_suballocator_destroy(&ctx->query_allocator);
|
||||
}
|
||||
}
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
slab_destroy_child(&ctx->transfer_pool);
|
||||
slab_destroy_child(&ctx->transfer_pool_unsync);
|
||||
d3d12_context_state_table_destroy(ctx);
|
||||
|
||||
FREE(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
d3d12_flush_cmdlist(struct d3d12_context *ctx)
|
||||
{
|
||||
d3d12_end_batch(ctx, d3d12_current_batch(ctx));
|
||||
|
||||
ctx->current_batch_idx++;
|
||||
if (ctx->current_batch_idx == ARRAY_SIZE(ctx->batches))
|
||||
ctx->current_batch_idx = 0;
|
||||
|
||||
d3d12_start_batch(ctx, d3d12_current_batch(ctx));
|
||||
}
|
||||
|
||||
void
|
||||
d3d12_flush_cmdlist_and_wait(struct d3d12_context *ctx)
|
||||
{
|
||||
struct d3d12_batch *batch = d3d12_current_batch(ctx);
|
||||
|
||||
d3d12_foreach_submitted_batch(ctx, old_batch)
|
||||
d3d12_reset_batch(ctx, old_batch, OS_TIMEOUT_INFINITE);
|
||||
d3d12_flush_cmdlist(ctx);
|
||||
d3d12_reset_batch(ctx, batch, OS_TIMEOUT_INFINITE);
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_flush(struct pipe_context *pipe,
|
||||
struct pipe_fence_handle **fence,
|
||||
unsigned flags)
|
||||
{
|
||||
struct d3d12_context *ctx = d3d12_context(pipe);
|
||||
struct d3d12_batch *batch = d3d12_current_batch(ctx);
|
||||
|
||||
d3d12_flush_cmdlist(ctx);
|
||||
|
||||
if (fence)
|
||||
d3d12_fence_reference((struct d3d12_fence **)fence, batch->fence);
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_flush_resource(struct pipe_context *pctx,
|
||||
struct pipe_resource *pres)
|
||||
{
|
||||
struct d3d12_context *ctx = d3d12_context(pctx);
|
||||
struct d3d12_resource *res = d3d12_resource(pres);
|
||||
|
||||
d3d12_transition_resource_state(ctx, res,
|
||||
D3D12_RESOURCE_STATE_COMMON,
|
||||
D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
|
||||
d3d12_apply_resource_states(ctx, false);
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_signal(struct pipe_context *pipe,
|
||||
struct pipe_fence_handle *pfence)
|
||||
{
|
||||
struct d3d12_screen *screen = d3d12_screen(pipe->screen);
|
||||
struct d3d12_fence *fence = d3d12_fence(pfence);
|
||||
d3d12_flush_cmdlist(d3d12_context(pipe));
|
||||
screen->cmdqueue->Signal(fence->cmdqueue_fence, fence->value);
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_wait(struct pipe_context *pipe, struct pipe_fence_handle *pfence)
|
||||
{
|
||||
struct d3d12_screen *screen = d3d12_screen(pipe->screen);
|
||||
struct d3d12_fence *fence = d3d12_fence(pfence);
|
||||
d3d12_flush_cmdlist(d3d12_context(pipe));
|
||||
screen->cmdqueue->Wait(fence->cmdqueue_fence, fence->value);
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_replace_buffer_storage(struct pipe_context *pctx,
|
||||
struct pipe_resource *pdst,
|
||||
struct pipe_resource *psrc,
|
||||
unsigned minimum_num_rebinds,
|
||||
uint32_t rebind_mask,
|
||||
uint32_t delete_buffer_id)
|
||||
{
|
||||
struct d3d12_resource *dst = d3d12_resource(pdst);
|
||||
struct d3d12_resource *src = d3d12_resource(psrc);
|
||||
|
||||
struct d3d12_bo *old_bo = dst->bo;
|
||||
d3d12_bo_reference(src->bo);
|
||||
dst->bo = src->bo;
|
||||
p_atomic_inc(&dst->generation_id);
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
struct d3d12_context *ctx = d3d12_context(pctx);
|
||||
if ((d3d12_screen(pctx->screen)->max_feature_level >= D3D_FEATURE_LEVEL_11_0)
|
||||
&& !(ctx->flags & PIPE_CONTEXT_MEDIA_ONLY))
|
||||
d3d12_rebind_buffer(ctx, dst);
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
d3d12_bo_unreference(old_bo);
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_memory_barrier(struct pipe_context *pctx, unsigned flags)
|
||||
{
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
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);
|
||||
}
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_texture_barrier(struct pipe_context *pctx, unsigned flags)
|
||||
{
|
||||
struct d3d12_context *ctx = d3d12_context(pctx);
|
||||
|
||||
/* D3D doesn't really have an equivalent in the legacy barrier model. When using enhanced barriers,
|
||||
* this could be a more specific global barrier. But for now, just flush the world with an aliasing barrier. */
|
||||
D3D12_RESOURCE_BARRIER aliasingBarrier;
|
||||
aliasingBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING;
|
||||
aliasingBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
aliasingBarrier.Aliasing.pResourceBefore = nullptr;
|
||||
aliasingBarrier.Aliasing.pResourceAfter = nullptr;
|
||||
ctx->cmdlist->ResourceBarrier(1, &aliasingBarrier);
|
||||
}
|
||||
|
||||
static enum pipe_reset_status
|
||||
d3d12_get_reset_status(struct pipe_context *pctx)
|
||||
{
|
||||
struct d3d12_screen *screen = d3d12_screen(pctx->screen);
|
||||
HRESULT hr = screen->dev->GetDeviceRemovedReason();
|
||||
switch (hr) {
|
||||
case DXGI_ERROR_DEVICE_HUNG:
|
||||
case DXGI_ERROR_INVALID_CALL:
|
||||
return PIPE_GUILTY_CONTEXT_RESET;
|
||||
case DXGI_ERROR_DEVICE_RESET:
|
||||
return PIPE_INNOCENT_CONTEXT_RESET;
|
||||
default:
|
||||
return SUCCEEDED(hr) ? PIPE_NO_RESET : PIPE_UNKNOWN_CONTEXT_RESET;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_VIDEO
|
||||
struct pipe_video_codec*
|
||||
d3d12_video_create_codec(struct pipe_context *context,
|
||||
const struct pipe_video_codec *templat)
|
||||
{
|
||||
if (templat->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
|
||||
return d3d12_video_encoder_create_encoder(context, templat);
|
||||
} else if (templat->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
|
||||
return d3d12_video_create_decoder(context, templat);
|
||||
} else if (templat->entrypoint == PIPE_VIDEO_ENTRYPOINT_PROCESSING) {
|
||||
return d3d12_video_processor_create(context, templat);
|
||||
} else {
|
||||
debug_printf("D3D12: Unsupported video codec entrypoint %d\n", templat->entrypoint);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct pipe_context *
|
||||
d3d12_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
|
||||
{
|
||||
struct d3d12_screen *screen = d3d12_screen(pscreen);
|
||||
if (FAILED(screen->dev->GetDeviceRemovedReason())) {
|
||||
/* Attempt recovery, but this may fail */
|
||||
screen->deinit(screen);
|
||||
if (!screen->init(screen)) {
|
||||
debug_printf("D3D12: failed to reset screen\n");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if ((screen->max_feature_level < D3D_FEATURE_LEVEL_11_0) &&
|
||||
!(flags & PIPE_CONTEXT_MEDIA_ONLY))
|
||||
{
|
||||
debug_printf("D3D12: Underlying screen maximum supported feature level is lower than D3D_FEATURE_LEVEL_11_0. The caller to context_create must pass PIPE_CONTEXT_MEDIA_ONLY in flags.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef HAVE_GALLIUM_D3D12_VIDEO
|
||||
if (flags & PIPE_CONTEXT_MEDIA_ONLY)
|
||||
{
|
||||
debug_printf("D3D12: context_create passed PIPE_CONTEXT_MEDIA_ONLY in flags but no media support found.\n");
|
||||
return NULL;
|
||||
}
|
||||
#endif // ifndef HAVE_GALLIUM_D3D12_VIDEO
|
||||
|
||||
struct d3d12_context *ctx = CALLOC_STRUCT(d3d12_context);
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
ctx->base.screen = pscreen;
|
||||
ctx->base.priv = priv;
|
||||
|
||||
ctx->base.destroy = d3d12_context_destroy;
|
||||
ctx->base.flush = d3d12_flush;
|
||||
ctx->base.flush_resource = d3d12_flush_resource;
|
||||
ctx->base.fence_server_signal = d3d12_signal;
|
||||
ctx->base.fence_server_sync = d3d12_wait;
|
||||
ctx->base.memory_barrier = d3d12_memory_barrier;
|
||||
ctx->base.texture_barrier = d3d12_texture_barrier;
|
||||
|
||||
ctx->base.get_device_reset_status = d3d12_get_reset_status;
|
||||
ctx->flags = flags;
|
||||
d3d12_context_resource_init(&ctx->base);
|
||||
d3d12_context_copy_init(&ctx->base);
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_VIDEO
|
||||
ctx->base.create_video_codec = d3d12_video_create_codec;
|
||||
ctx->base.create_video_buffer = d3d12_video_buffer_create;
|
||||
ctx->base.video_buffer_from_handle = d3d12_video_buffer_from_handle;
|
||||
#endif
|
||||
|
||||
slab_create_child(&ctx->transfer_pool, &d3d12_screen(pscreen)->transfer_pool);
|
||||
slab_create_child(&ctx->transfer_pool_unsync, &d3d12_screen(pscreen)->transfer_pool);
|
||||
|
||||
d3d12_context_state_table_init(ctx);
|
||||
|
||||
ctx->queries_disabled = true; // Disabled by default, re-enable if supported FL below
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
if ((screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0) && !(flags & PIPE_CONTEXT_MEDIA_ONLY)) {
|
||||
#ifndef _GAMING_XBOX
|
||||
(void)screen->dev->QueryInterface(&ctx->dev_config);
|
||||
#endif
|
||||
|
||||
d3d12_context_blit_init(&ctx->base);
|
||||
|
||||
u_suballocator_init(&ctx->so_allocator, &ctx->base, 4096, 0,
|
||||
PIPE_USAGE_DEFAULT,
|
||||
0, false);
|
||||
|
||||
ctx->has_flat_varyings = false;
|
||||
ctx->missing_dual_src_outputs = false;
|
||||
ctx->manual_depth_range = false;
|
||||
|
||||
d3d12_compute_pipeline_state_cache_init(ctx);
|
||||
d3d12_root_signature_cache_init(ctx);
|
||||
d3d12_cmd_signature_cache_init(ctx);
|
||||
d3d12_compute_transform_cache_init(ctx);
|
||||
|
||||
ctx->D3D12SerializeVersionedRootSignature =
|
||||
(PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)util_dl_get_proc_address(screen->d3d12_mod, "D3D12SerializeVersionedRootSignature");
|
||||
|
||||
ctx->base.stream_uploader = u_upload_create_default(&ctx->base);
|
||||
ctx->base.const_uploader = u_upload_create_default(&ctx->base);
|
||||
|
||||
ctx->base.get_sample_position = u_default_get_sample_position;
|
||||
ctx->base.get_sample_position = u_default_get_sample_position;
|
||||
|
||||
d3d12_init_graphics_context_functions(ctx);
|
||||
|
||||
ctx->gfx_pipeline_state.sample_mask = ~0;
|
||||
|
||||
d3d12_context_surface_init(&ctx->base);
|
||||
d3d12_context_query_init(&ctx->base);
|
||||
ctx->queries_disabled = false;
|
||||
|
||||
struct primconvert_config cfg = {};
|
||||
cfg.primtypes_mask = 1 << MESA_PRIM_POINTS |
|
||||
1 << MESA_PRIM_LINES |
|
||||
1 << MESA_PRIM_LINE_STRIP |
|
||||
1 << MESA_PRIM_TRIANGLES |
|
||||
1 << MESA_PRIM_TRIANGLE_STRIP;
|
||||
cfg.restart_primtypes_mask = cfg.primtypes_mask;
|
||||
cfg.fixed_prim_restart = true;
|
||||
ctx->primconvert = util_primconvert_create_config(&ctx->base, &cfg);
|
||||
if (!ctx->primconvert) {
|
||||
debug_printf("D3D12: failed to create primconvert\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
d3d12_gfx_pipeline_state_cache_init(ctx);
|
||||
d3d12_gs_variant_cache_init(ctx);
|
||||
d3d12_tcs_variant_cache_init(ctx);
|
||||
|
||||
ctx->sampler_pool = d3d12_descriptor_pool_new(screen,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
|
||||
64);
|
||||
if (!ctx->sampler_pool) {
|
||||
FREE(ctx);
|
||||
return NULL;
|
||||
}
|
||||
d3d12_init_null_sampler(ctx);
|
||||
|
||||
ctx->blitter = util_blitter_create(&ctx->base);
|
||||
if (!ctx->blitter)
|
||||
return NULL;
|
||||
|
||||
if (!d3d12_init_polygon_stipple(&ctx->base)) {
|
||||
debug_printf("D3D12: failed to initialize polygon stipple resources\n");
|
||||
FREE(ctx);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
if (!(d3d12_debug & D3D12_DEBUG_EXPERIMENTAL) ||
|
||||
(d3d12_debug & D3D12_DEBUG_DISASS))
|
||||
ctx->dxil_validator = dxil_create_validator(NULL);
|
||||
#endif
|
||||
}
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
ctx->submit_id = (uint64_t)p_atomic_add_return(&screen->ctx_count, 1) << 32ull;
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(ctx->batches); ++i) {
|
||||
if (!d3d12_init_batch(ctx, &ctx->batches[i])) {
|
||||
FREE(ctx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
d3d12_start_batch(ctx, &ctx->batches[0]);
|
||||
|
||||
mtx_lock(&screen->submit_mutex);
|
||||
list_addtail(&ctx->context_list_entry, &screen->context_list);
|
||||
if (screen->context_id_count > 0)
|
||||
ctx->id = screen->context_id_list[--screen->context_id_count];
|
||||
else
|
||||
ctx->id = D3D12_CONTEXT_NO_ID;
|
||||
mtx_unlock(&screen->submit_mutex);
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(ctx->batches); ++i) {
|
||||
ctx->batches[i].ctx_id = ctx->id;
|
||||
ctx->batches[i].ctx_index = i;
|
||||
}
|
||||
|
||||
if (flags & PIPE_CONTEXT_PREFER_THREADED)
|
||||
return threaded_context_create(&ctx->base,
|
||||
&screen->transfer_pool,
|
||||
d3d12_replace_buffer_storage,
|
||||
NULL,
|
||||
&ctx->threaded_context);
|
||||
|
||||
return &ctx->base;
|
||||
}
|
@@ -34,12 +34,6 @@
|
||||
#include "d3d12_root_signature.h"
|
||||
#include "d3d12_screen.h"
|
||||
#include "d3d12_surface.h"
|
||||
#ifdef HAVE_GALLIUM_D3D12_VIDEO
|
||||
#include "d3d12_video_dec.h"
|
||||
#include "d3d12_video_enc.h"
|
||||
#include "d3d12_video_proc.h"
|
||||
#include "d3d12_video_buffer.h"
|
||||
#endif
|
||||
#include "indices/u_primconvert.h"
|
||||
#include "util/u_atomic.h"
|
||||
#include "util/u_blitter.h"
|
||||
@@ -68,74 +62,6 @@ typedef D3D12_DEPTH_STENCILOP_DESC d3d12_depth_stencil_op_desc_type;
|
||||
typedef D3D12_DEPTH_STENCILOP_DESC1 d3d12_depth_stencil_op_desc_type;
|
||||
#endif
|
||||
|
||||
static void
|
||||
d3d12_context_destroy(struct pipe_context *pctx)
|
||||
{
|
||||
struct d3d12_context *ctx = d3d12_context(pctx);
|
||||
|
||||
struct d3d12_screen *screen = d3d12_screen(pctx->screen);
|
||||
mtx_lock(&screen->submit_mutex);
|
||||
list_del(&ctx->context_list_entry);
|
||||
if (ctx->id != D3D12_CONTEXT_NO_ID)
|
||||
screen->context_id_list[screen->context_id_count++] = ctx->id;
|
||||
mtx_unlock(&screen->submit_mutex);
|
||||
|
||||
#ifdef _WIN32
|
||||
dxil_destroy_validator(ctx->dxil_validator);
|
||||
#endif
|
||||
|
||||
#ifndef _GAMING_XBOX
|
||||
if (ctx->dev_config)
|
||||
ctx->dev_config->Release();
|
||||
#endif
|
||||
|
||||
if (ctx->timestamp_query)
|
||||
pctx->destroy_query(pctx, ctx->timestamp_query);
|
||||
|
||||
util_unreference_framebuffer_state(&ctx->fb);
|
||||
d3d12_end_batch(ctx, d3d12_current_batch(ctx));
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(ctx->batches); ++i)
|
||||
d3d12_destroy_batch(ctx, &ctx->batches[i]);
|
||||
ctx->cmdlist->Release();
|
||||
if (ctx->cmdlist2)
|
||||
ctx->cmdlist2->Release();
|
||||
if (ctx->cmdlist8)
|
||||
ctx->cmdlist8->Release();
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
if ((screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0) && !(ctx->flags & PIPE_CONTEXT_MEDIA_ONLY)) {
|
||||
util_blitter_destroy(ctx->blitter);
|
||||
d3d12_compute_pipeline_state_cache_destroy(ctx);
|
||||
d3d12_root_signature_cache_destroy(ctx);
|
||||
d3d12_cmd_signature_cache_destroy(ctx);
|
||||
d3d12_compute_transform_cache_destroy(ctx);
|
||||
d3d12_descriptor_pool_free(ctx->sampler_pool);
|
||||
d3d12_gs_variant_cache_destroy(ctx);
|
||||
d3d12_tcs_variant_cache_destroy(ctx);
|
||||
d3d12_gfx_pipeline_state_cache_destroy(ctx);
|
||||
util_primconvert_destroy(ctx->primconvert);
|
||||
pipe_resource_reference(&ctx->pstipple.texture, nullptr);
|
||||
pipe_sampler_view_reference(&ctx->pstipple.sampler_view, nullptr);
|
||||
util_dynarray_fini(&ctx->recently_destroyed_bos);
|
||||
FREE(ctx->pstipple.sampler_cso);
|
||||
if (pctx->stream_uploader)
|
||||
u_upload_destroy(pctx->stream_uploader);
|
||||
if (pctx->const_uploader)
|
||||
u_upload_destroy(pctx->const_uploader);
|
||||
if (!ctx->queries_disabled) {
|
||||
u_suballocator_destroy(&ctx->query_allocator);
|
||||
}
|
||||
}
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
slab_destroy_child(&ctx->transfer_pool);
|
||||
slab_destroy_child(&ctx->transfer_pool_unsync);
|
||||
d3d12_context_state_table_destroy(ctx);
|
||||
|
||||
FREE(ctx);
|
||||
}
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
static void *
|
||||
d3d12_create_vertex_elements_state(struct pipe_context *pctx,
|
||||
unsigned num_elements,
|
||||
@@ -1296,7 +1222,7 @@ d3d12_delete_compute_state(struct pipe_context *pctx, void *cs)
|
||||
d3d12_shader_free(shader);
|
||||
}
|
||||
|
||||
static bool
|
||||
bool
|
||||
d3d12_init_polygon_stipple(struct pipe_context *pctx)
|
||||
{
|
||||
struct d3d12_context *ctx = d3d12_context(pctx);
|
||||
@@ -1830,33 +1756,6 @@ d3d12_set_shader_images(struct pipe_context *pctx,
|
||||
ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_IMAGE;
|
||||
}
|
||||
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
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, 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) {
|
||||
ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_CONSTBUF;
|
||||
}
|
||||
|
||||
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_SSBO] > 0) {
|
||||
ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SSBO;
|
||||
}
|
||||
|
||||
if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_IMAGE] > 0) {
|
||||
ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_IMAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
bool
|
||||
d3d12_enable_fake_so_buffers(struct d3d12_context *ctx, unsigned factor)
|
||||
{
|
||||
@@ -2019,32 +1918,6 @@ d3d12_disable_fake_so_buffers(struct d3d12_context *ctx)
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
void
|
||||
d3d12_flush_cmdlist(struct d3d12_context *ctx)
|
||||
{
|
||||
d3d12_end_batch(ctx, d3d12_current_batch(ctx));
|
||||
|
||||
ctx->current_batch_idx++;
|
||||
if (ctx->current_batch_idx == ARRAY_SIZE(ctx->batches))
|
||||
ctx->current_batch_idx = 0;
|
||||
|
||||
d3d12_start_batch(ctx, d3d12_current_batch(ctx));
|
||||
}
|
||||
|
||||
void
|
||||
d3d12_flush_cmdlist_and_wait(struct d3d12_context *ctx)
|
||||
{
|
||||
struct d3d12_batch *batch = d3d12_current_batch(ctx);
|
||||
|
||||
d3d12_foreach_submitted_batch(ctx, old_batch)
|
||||
d3d12_reset_batch(ctx, old_batch, OS_TIMEOUT_INFINITE);
|
||||
d3d12_flush_cmdlist(ctx);
|
||||
d3d12_reset_batch(ctx, batch, OS_TIMEOUT_INFINITE);
|
||||
}
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
static void
|
||||
d3d12_clear_render_target(struct pipe_context *pctx,
|
||||
struct pipe_surface *psurf,
|
||||
@@ -2207,57 +2080,7 @@ d3d12_clear(struct pipe_context *pctx,
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
static void
|
||||
d3d12_flush(struct pipe_context *pipe,
|
||||
struct pipe_fence_handle **fence,
|
||||
unsigned flags)
|
||||
{
|
||||
struct d3d12_context *ctx = d3d12_context(pipe);
|
||||
struct d3d12_batch *batch = d3d12_current_batch(ctx);
|
||||
|
||||
d3d12_flush_cmdlist(ctx);
|
||||
|
||||
if (fence)
|
||||
d3d12_fence_reference((struct d3d12_fence **)fence, batch->fence);
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_flush_resource(struct pipe_context *pctx,
|
||||
struct pipe_resource *pres)
|
||||
{
|
||||
struct d3d12_context *ctx = d3d12_context(pctx);
|
||||
struct d3d12_resource *res = d3d12_resource(pres);
|
||||
|
||||
d3d12_transition_resource_state(ctx, res,
|
||||
D3D12_RESOURCE_STATE_COMMON,
|
||||
D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
|
||||
d3d12_apply_resource_states(ctx, false);
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_signal(struct pipe_context *pipe,
|
||||
struct pipe_fence_handle *pfence)
|
||||
{
|
||||
struct d3d12_screen *screen = d3d12_screen(pipe->screen);
|
||||
struct d3d12_fence *fence = d3d12_fence(pfence);
|
||||
d3d12_flush_cmdlist(d3d12_context(pipe));
|
||||
screen->cmdqueue->Signal(fence->cmdqueue_fence, fence->value);
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_wait(struct pipe_context *pipe, struct pipe_fence_handle *pfence)
|
||||
{
|
||||
struct d3d12_screen *screen = d3d12_screen(pipe->screen);
|
||||
struct d3d12_fence *fence = d3d12_fence(pfence);
|
||||
d3d12_flush_cmdlist(d3d12_context(pipe));
|
||||
screen->cmdqueue->Wait(fence->cmdqueue_fence, fence->value);
|
||||
}
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
static void
|
||||
void
|
||||
d3d12_init_null_sampler(struct d3d12_context *ctx)
|
||||
{
|
||||
struct d3d12_screen *screen = d3d12_screen(ctx->base.screen);
|
||||
@@ -2292,10 +2115,7 @@ d3d12_get_timestamp(struct pipe_context *pctx)
|
||||
return result.u64;
|
||||
}
|
||||
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
static void
|
||||
void
|
||||
d3d12_rebind_buffer(struct d3d12_context *ctx, struct d3d12_resource *res)
|
||||
{
|
||||
if (res->base.b.bind & PIPE_BIND_VERTEX_BUFFER) {
|
||||
@@ -2323,94 +2143,6 @@ d3d12_rebind_buffer(struct d3d12_context *ctx, struct d3d12_resource *res)
|
||||
}
|
||||
d3d12_invalidate_context_bindings(ctx, res);
|
||||
}
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
static void
|
||||
d3d12_replace_buffer_storage(struct pipe_context *pctx,
|
||||
struct pipe_resource *pdst,
|
||||
struct pipe_resource *psrc,
|
||||
unsigned minimum_num_rebinds,
|
||||
uint32_t rebind_mask,
|
||||
uint32_t delete_buffer_id)
|
||||
{
|
||||
struct d3d12_resource *dst = d3d12_resource(pdst);
|
||||
struct d3d12_resource *src = d3d12_resource(psrc);
|
||||
|
||||
struct d3d12_bo *old_bo = dst->bo;
|
||||
d3d12_bo_reference(src->bo);
|
||||
dst->bo = src->bo;
|
||||
p_atomic_inc(&dst->generation_id);
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
struct d3d12_context *ctx = d3d12_context(pctx);
|
||||
if ((d3d12_screen(pctx->screen)->max_feature_level >= D3D_FEATURE_LEVEL_11_0)
|
||||
&& !(ctx->flags & PIPE_CONTEXT_MEDIA_ONLY))
|
||||
d3d12_rebind_buffer(ctx, dst);
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_texture_barrier(struct pipe_context *pctx, unsigned flags)
|
||||
{
|
||||
struct d3d12_context *ctx = d3d12_context(pctx);
|
||||
|
||||
/* D3D doesn't really have an equivalent in the legacy barrier model. When using enhanced barriers,
|
||||
* this could be a more specific global barrier. But for now, just flush the world with an aliasing barrier. */
|
||||
D3D12_RESOURCE_BARRIER aliasingBarrier;
|
||||
aliasingBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING;
|
||||
aliasingBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
aliasingBarrier.Aliasing.pResourceBefore = nullptr;
|
||||
aliasingBarrier.Aliasing.pResourceAfter = nullptr;
|
||||
ctx->cmdlist->ResourceBarrier(1, &aliasingBarrier);
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_set_patch_vertices(struct pipe_context *pctx, uint8_t patch_vertices)
|
||||
@@ -2430,286 +2162,6 @@ d3d12_set_tess_state(struct pipe_context *pctx,
|
||||
memcpy(ctx->default_inner_tess_factor, default_inner_level, sizeof(ctx->default_inner_tess_factor));
|
||||
}
|
||||
|
||||
static enum pipe_reset_status
|
||||
d3d12_get_reset_status(struct pipe_context *pctx)
|
||||
{
|
||||
struct d3d12_screen *screen = d3d12_screen(pctx->screen);
|
||||
HRESULT hr = screen->dev->GetDeviceRemovedReason();
|
||||
switch (hr) {
|
||||
case DXGI_ERROR_DEVICE_HUNG:
|
||||
case DXGI_ERROR_INVALID_CALL:
|
||||
return PIPE_GUILTY_CONTEXT_RESET;
|
||||
case DXGI_ERROR_DEVICE_RESET:
|
||||
return PIPE_INNOCENT_CONTEXT_RESET;
|
||||
default:
|
||||
return SUCCEEDED(hr) ? PIPE_NO_RESET : PIPE_UNKNOWN_CONTEXT_RESET;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_VIDEO
|
||||
struct pipe_video_codec*
|
||||
d3d12_video_create_codec(struct pipe_context *context,
|
||||
const struct pipe_video_codec *templat)
|
||||
{
|
||||
if (templat->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
|
||||
return d3d12_video_encoder_create_encoder(context, templat);
|
||||
} else if (templat->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
|
||||
return d3d12_video_create_decoder(context, templat);
|
||||
} else if (templat->entrypoint == PIPE_VIDEO_ENTRYPOINT_PROCESSING) {
|
||||
return d3d12_video_processor_create(context, templat);
|
||||
} else {
|
||||
debug_printf("D3D12: Unsupported video codec entrypoint %d\n", templat->entrypoint);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct pipe_context *
|
||||
d3d12_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
|
||||
{
|
||||
struct d3d12_screen *screen = d3d12_screen(pscreen);
|
||||
if (FAILED(screen->dev->GetDeviceRemovedReason())) {
|
||||
/* Attempt recovery, but this may fail */
|
||||
screen->deinit(screen);
|
||||
if (!screen->init(screen)) {
|
||||
debug_printf("D3D12: failed to reset screen\n");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if ((screen->max_feature_level < D3D_FEATURE_LEVEL_11_0) &&
|
||||
!(flags & PIPE_CONTEXT_MEDIA_ONLY))
|
||||
{
|
||||
debug_printf("D3D12: Underlying screen maximum supported feature level is lower than D3D_FEATURE_LEVEL_11_0. The caller to context_create must pass PIPE_CONTEXT_MEDIA_ONLY in flags.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef HAVE_GALLIUM_D3D12_VIDEO
|
||||
if (flags & PIPE_CONTEXT_MEDIA_ONLY)
|
||||
{
|
||||
debug_printf("D3D12: context_create passed PIPE_CONTEXT_MEDIA_ONLY in flags but no media support found.\n");
|
||||
return NULL;
|
||||
}
|
||||
#endif // ifndef HAVE_GALLIUM_D3D12_VIDEO
|
||||
|
||||
struct d3d12_context *ctx = CALLOC_STRUCT(d3d12_context);
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
ctx->base.screen = pscreen;
|
||||
ctx->base.priv = priv;
|
||||
|
||||
ctx->base.destroy = d3d12_context_destroy;
|
||||
ctx->base.flush = d3d12_flush;
|
||||
ctx->base.flush_resource = d3d12_flush_resource;
|
||||
ctx->base.fence_server_signal = d3d12_signal;
|
||||
ctx->base.fence_server_sync = d3d12_wait;
|
||||
ctx->base.memory_barrier = d3d12_memory_barrier;
|
||||
ctx->base.texture_barrier = d3d12_texture_barrier;
|
||||
|
||||
ctx->base.get_device_reset_status = d3d12_get_reset_status;
|
||||
ctx->has_flat_varyings = false;
|
||||
ctx->missing_dual_src_outputs = false;
|
||||
ctx->manual_depth_range = false;
|
||||
ctx->flags = flags;
|
||||
d3d12_context_resource_init(&ctx->base);
|
||||
d3d12_context_blit_init(&ctx->base);
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_VIDEO
|
||||
ctx->base.create_video_codec = d3d12_video_create_codec;
|
||||
ctx->base.create_video_buffer = d3d12_video_buffer_create;
|
||||
ctx->base.video_buffer_from_handle = d3d12_video_buffer_from_handle;
|
||||
#endif
|
||||
|
||||
slab_create_child(&ctx->transfer_pool, &d3d12_screen(pscreen)->transfer_pool);
|
||||
slab_create_child(&ctx->transfer_pool_unsync, &d3d12_screen(pscreen)->transfer_pool);
|
||||
|
||||
u_suballocator_init(&ctx->so_allocator, &ctx->base, 4096, 0,
|
||||
PIPE_USAGE_DEFAULT,
|
||||
0, false);
|
||||
|
||||
#ifndef _GAMING_XBOX
|
||||
(void)screen->dev->QueryInterface(&ctx->dev_config);
|
||||
#endif
|
||||
|
||||
d3d12_context_state_table_init(ctx);
|
||||
|
||||
ctx->queries_disabled = true; // Disabled by default, re-enable if supported FL below
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
if ((screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0) && !(flags & PIPE_CONTEXT_MEDIA_ONLY)) {
|
||||
ctx->base.create_compute_state = d3d12_create_compute_state;
|
||||
ctx->base.bind_compute_state = d3d12_bind_compute_state;
|
||||
ctx->base.delete_compute_state = d3d12_delete_compute_state;
|
||||
ctx->base.set_shader_buffers = d3d12_set_shader_buffers;
|
||||
|
||||
d3d12_compute_pipeline_state_cache_init(ctx);
|
||||
d3d12_root_signature_cache_init(ctx);
|
||||
d3d12_cmd_signature_cache_init(ctx);
|
||||
d3d12_compute_transform_cache_init(ctx);
|
||||
|
||||
ctx->D3D12SerializeVersionedRootSignature =
|
||||
(PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)util_dl_get_proc_address(screen->d3d12_mod, "D3D12SerializeVersionedRootSignature");
|
||||
|
||||
ctx->base.create_sampler_view = d3d12_create_sampler_view;
|
||||
ctx->base.sampler_view_destroy = d3d12_destroy_sampler_view;
|
||||
|
||||
ctx->base.stream_uploader = u_upload_create_default(&ctx->base);
|
||||
ctx->base.const_uploader = u_upload_create_default(&ctx->base);
|
||||
|
||||
ctx->base.get_sample_position = u_default_get_sample_position;
|
||||
|
||||
ctx->base.create_vertex_elements_state = d3d12_create_vertex_elements_state;
|
||||
ctx->base.bind_vertex_elements_state = d3d12_bind_vertex_elements_state;
|
||||
ctx->base.delete_vertex_elements_state = d3d12_delete_vertex_elements_state;
|
||||
|
||||
ctx->base.create_blend_state = d3d12_create_blend_state;
|
||||
ctx->base.bind_blend_state = d3d12_bind_blend_state;
|
||||
ctx->base.delete_blend_state = d3d12_delete_blend_state;
|
||||
|
||||
ctx->base.create_depth_stencil_alpha_state = d3d12_create_depth_stencil_alpha_state;
|
||||
ctx->base.bind_depth_stencil_alpha_state = d3d12_bind_depth_stencil_alpha_state;
|
||||
ctx->base.delete_depth_stencil_alpha_state = d3d12_delete_depth_stencil_alpha_state;
|
||||
|
||||
ctx->base.create_rasterizer_state = d3d12_create_rasterizer_state;
|
||||
ctx->base.bind_rasterizer_state = d3d12_bind_rasterizer_state;
|
||||
ctx->base.delete_rasterizer_state = d3d12_delete_rasterizer_state;
|
||||
|
||||
ctx->base.create_sampler_state = d3d12_create_sampler_state;
|
||||
ctx->base.bind_sampler_states = d3d12_bind_sampler_states;
|
||||
ctx->base.delete_sampler_state = d3d12_delete_sampler_state;
|
||||
|
||||
ctx->base.set_sampler_views = d3d12_set_sampler_views;
|
||||
|
||||
ctx->base.create_vs_state = d3d12_create_vs_state;
|
||||
ctx->base.bind_vs_state = d3d12_bind_vs_state;
|
||||
ctx->base.delete_vs_state = d3d12_delete_vs_state;
|
||||
|
||||
ctx->base.create_fs_state = d3d12_create_fs_state;
|
||||
ctx->base.bind_fs_state = d3d12_bind_fs_state;
|
||||
ctx->base.delete_fs_state = d3d12_delete_fs_state;
|
||||
|
||||
ctx->base.create_gs_state = d3d12_create_gs_state;
|
||||
ctx->base.bind_gs_state = d3d12_bind_gs_state;
|
||||
ctx->base.delete_gs_state = d3d12_delete_gs_state;
|
||||
|
||||
ctx->base.create_tcs_state = d3d12_create_tcs_state;
|
||||
ctx->base.bind_tcs_state = d3d12_bind_tcs_state;
|
||||
ctx->base.delete_tcs_state = d3d12_delete_tcs_state;
|
||||
|
||||
ctx->base.create_tes_state = d3d12_create_tes_state;
|
||||
ctx->base.bind_tes_state = d3d12_bind_tes_state;
|
||||
ctx->base.delete_tes_state = d3d12_delete_tes_state;
|
||||
|
||||
ctx->base.set_patch_vertices = d3d12_set_patch_vertices;
|
||||
ctx->base.set_tess_state = d3d12_set_tess_state;
|
||||
|
||||
ctx->base.set_polygon_stipple = d3d12_set_polygon_stipple;
|
||||
ctx->base.set_vertex_buffers = d3d12_set_vertex_buffers;
|
||||
ctx->base.set_viewport_states = d3d12_set_viewport_states;
|
||||
ctx->base.set_scissor_states = d3d12_set_scissor_states;
|
||||
ctx->base.set_constant_buffer = d3d12_set_constant_buffer;
|
||||
ctx->base.set_framebuffer_state = d3d12_set_framebuffer_state;
|
||||
ctx->base.set_clip_state = d3d12_set_clip_state;
|
||||
ctx->base.set_blend_color = d3d12_set_blend_color;
|
||||
ctx->base.set_sample_mask = d3d12_set_sample_mask;
|
||||
ctx->base.set_stencil_ref = d3d12_set_stencil_ref;
|
||||
|
||||
ctx->base.create_stream_output_target = d3d12_create_stream_output_target;
|
||||
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_images = d3d12_set_shader_images;
|
||||
|
||||
ctx->base.clear = d3d12_clear;
|
||||
ctx->base.clear_render_target = d3d12_clear_render_target;
|
||||
ctx->base.clear_depth_stencil = d3d12_clear_depth_stencil;
|
||||
ctx->base.draw_vbo = d3d12_draw_vbo;
|
||||
ctx->base.launch_grid = d3d12_launch_grid;
|
||||
ctx->base.get_timestamp = d3d12_get_timestamp;
|
||||
ctx->base.get_sample_position = u_default_get_sample_position;
|
||||
ctx->gfx_pipeline_state.sample_mask = ~0;
|
||||
|
||||
d3d12_context_surface_init(&ctx->base);
|
||||
d3d12_context_query_init(&ctx->base);
|
||||
ctx->queries_disabled = false;
|
||||
|
||||
struct primconvert_config cfg = {};
|
||||
cfg.primtypes_mask = 1 << MESA_PRIM_POINTS |
|
||||
1 << MESA_PRIM_LINES |
|
||||
1 << MESA_PRIM_LINE_STRIP |
|
||||
1 << MESA_PRIM_TRIANGLES |
|
||||
1 << MESA_PRIM_TRIANGLE_STRIP;
|
||||
cfg.restart_primtypes_mask = cfg.primtypes_mask;
|
||||
cfg.fixed_prim_restart = true;
|
||||
ctx->primconvert = util_primconvert_create_config(&ctx->base, &cfg);
|
||||
if (!ctx->primconvert) {
|
||||
debug_printf("D3D12: failed to create primconvert\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
d3d12_gfx_pipeline_state_cache_init(ctx);
|
||||
d3d12_gs_variant_cache_init(ctx);
|
||||
d3d12_tcs_variant_cache_init(ctx);
|
||||
|
||||
ctx->sampler_pool = d3d12_descriptor_pool_new(screen,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
|
||||
64);
|
||||
if (!ctx->sampler_pool) {
|
||||
FREE(ctx);
|
||||
return NULL;
|
||||
}
|
||||
d3d12_init_null_sampler(ctx);
|
||||
|
||||
ctx->blitter = util_blitter_create(&ctx->base);
|
||||
if (!ctx->blitter)
|
||||
return NULL;
|
||||
|
||||
if (!d3d12_init_polygon_stipple(&ctx->base)) {
|
||||
debug_printf("D3D12: failed to initialize polygon stipple resources\n");
|
||||
FREE(ctx);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
if (!(d3d12_debug & D3D12_DEBUG_EXPERIMENTAL) ||
|
||||
(d3d12_debug & D3D12_DEBUG_DISASS))
|
||||
ctx->dxil_validator = dxil_create_validator(NULL);
|
||||
#endif
|
||||
}
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
ctx->submit_id = (uint64_t)p_atomic_add_return(&screen->ctx_count, 1) << 32ull;
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(ctx->batches); ++i) {
|
||||
if (!d3d12_init_batch(ctx, &ctx->batches[i])) {
|
||||
FREE(ctx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
d3d12_start_batch(ctx, &ctx->batches[0]);
|
||||
|
||||
mtx_lock(&screen->submit_mutex);
|
||||
list_addtail(&ctx->context_list_entry, &screen->context_list);
|
||||
if (screen->context_id_count > 0)
|
||||
ctx->id = screen->context_id_list[--screen->context_id_count];
|
||||
else
|
||||
ctx->id = D3D12_CONTEXT_NO_ID;
|
||||
mtx_unlock(&screen->submit_mutex);
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(ctx->batches); ++i) {
|
||||
ctx->batches[i].ctx_id = ctx->id;
|
||||
ctx->batches[i].ctx_index = i;
|
||||
}
|
||||
|
||||
if (flags & PIPE_CONTEXT_PREFER_THREADED)
|
||||
return threaded_context_create(&ctx->base,
|
||||
&screen->transfer_pool,
|
||||
d3d12_replace_buffer_storage,
|
||||
NULL,
|
||||
&ctx->threaded_context);
|
||||
|
||||
return &ctx->base;
|
||||
}
|
||||
|
||||
bool
|
||||
d3d12_need_zero_one_depth_range(struct d3d12_context *ctx)
|
||||
{
|
||||
@@ -2751,3 +2203,106 @@ d3d12_need_zero_one_depth_range(struct d3d12_context *ctx)
|
||||
|
||||
return fs && fs->initial->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DEPTH);
|
||||
}
|
||||
|
||||
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, 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) {
|
||||
ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_CONSTBUF;
|
||||
}
|
||||
|
||||
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_SSBO] > 0) {
|
||||
ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SSBO;
|
||||
}
|
||||
|
||||
if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_IMAGE] > 0) {
|
||||
ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_IMAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
d3d12_init_graphics_context_functions(struct d3d12_context *ctx)
|
||||
{
|
||||
ctx->base.create_compute_state = d3d12_create_compute_state;
|
||||
ctx->base.bind_compute_state = d3d12_bind_compute_state;
|
||||
ctx->base.delete_compute_state = d3d12_delete_compute_state;
|
||||
ctx->base.set_shader_buffers = d3d12_set_shader_buffers;
|
||||
|
||||
ctx->base.create_sampler_view = d3d12_create_sampler_view;
|
||||
ctx->base.sampler_view_destroy = d3d12_destroy_sampler_view;
|
||||
|
||||
ctx->base.create_vertex_elements_state = d3d12_create_vertex_elements_state;
|
||||
ctx->base.bind_vertex_elements_state = d3d12_bind_vertex_elements_state;
|
||||
ctx->base.delete_vertex_elements_state = d3d12_delete_vertex_elements_state;
|
||||
|
||||
ctx->base.create_blend_state = d3d12_create_blend_state;
|
||||
ctx->base.bind_blend_state = d3d12_bind_blend_state;
|
||||
ctx->base.delete_blend_state = d3d12_delete_blend_state;
|
||||
|
||||
ctx->base.create_depth_stencil_alpha_state = d3d12_create_depth_stencil_alpha_state;
|
||||
ctx->base.bind_depth_stencil_alpha_state = d3d12_bind_depth_stencil_alpha_state;
|
||||
ctx->base.delete_depth_stencil_alpha_state = d3d12_delete_depth_stencil_alpha_state;
|
||||
|
||||
ctx->base.create_rasterizer_state = d3d12_create_rasterizer_state;
|
||||
ctx->base.bind_rasterizer_state = d3d12_bind_rasterizer_state;
|
||||
ctx->base.delete_rasterizer_state = d3d12_delete_rasterizer_state;
|
||||
|
||||
ctx->base.create_sampler_state = d3d12_create_sampler_state;
|
||||
ctx->base.bind_sampler_states = d3d12_bind_sampler_states;
|
||||
ctx->base.delete_sampler_state = d3d12_delete_sampler_state;
|
||||
|
||||
ctx->base.set_sampler_views = d3d12_set_sampler_views;
|
||||
|
||||
ctx->base.create_vs_state = d3d12_create_vs_state;
|
||||
ctx->base.bind_vs_state = d3d12_bind_vs_state;
|
||||
ctx->base.delete_vs_state = d3d12_delete_vs_state;
|
||||
|
||||
ctx->base.create_fs_state = d3d12_create_fs_state;
|
||||
ctx->base.bind_fs_state = d3d12_bind_fs_state;
|
||||
ctx->base.delete_fs_state = d3d12_delete_fs_state;
|
||||
|
||||
ctx->base.create_gs_state = d3d12_create_gs_state;
|
||||
ctx->base.bind_gs_state = d3d12_bind_gs_state;
|
||||
ctx->base.delete_gs_state = d3d12_delete_gs_state;
|
||||
|
||||
ctx->base.create_tcs_state = d3d12_create_tcs_state;
|
||||
ctx->base.bind_tcs_state = d3d12_bind_tcs_state;
|
||||
ctx->base.delete_tcs_state = d3d12_delete_tcs_state;
|
||||
|
||||
ctx->base.create_tes_state = d3d12_create_tes_state;
|
||||
ctx->base.bind_tes_state = d3d12_bind_tes_state;
|
||||
ctx->base.delete_tes_state = d3d12_delete_tes_state;
|
||||
|
||||
ctx->base.set_patch_vertices = d3d12_set_patch_vertices;
|
||||
ctx->base.set_tess_state = d3d12_set_tess_state;
|
||||
|
||||
ctx->base.set_polygon_stipple = d3d12_set_polygon_stipple;
|
||||
ctx->base.set_vertex_buffers = d3d12_set_vertex_buffers;
|
||||
ctx->base.set_viewport_states = d3d12_set_viewport_states;
|
||||
ctx->base.set_scissor_states = d3d12_set_scissor_states;
|
||||
ctx->base.set_constant_buffer = d3d12_set_constant_buffer;
|
||||
ctx->base.set_framebuffer_state = d3d12_set_framebuffer_state;
|
||||
ctx->base.set_clip_state = d3d12_set_clip_state;
|
||||
ctx->base.set_blend_color = d3d12_set_blend_color;
|
||||
ctx->base.set_sample_mask = d3d12_set_sample_mask;
|
||||
ctx->base.set_stencil_ref = d3d12_set_stencil_ref;
|
||||
|
||||
ctx->base.create_stream_output_target = d3d12_create_stream_output_target;
|
||||
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_images = d3d12_set_shader_images;
|
||||
|
||||
ctx->base.clear = d3d12_clear;
|
||||
ctx->base.clear_render_target = d3d12_clear_render_target;
|
||||
ctx->base.clear_depth_stencil = d3d12_clear_depth_stencil;
|
||||
ctx->base.draw_vbo = d3d12_draw_vbo;
|
||||
ctx->base.launch_grid = d3d12_launch_grid;
|
||||
ctx->base.get_timestamp = d3d12_get_timestamp;
|
||||
}
|
364
src/gallium/drivers/d3d12/d3d12_copy.cpp
Normal file
364
src/gallium/drivers/d3d12/d3d12_copy.cpp
Normal file
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
* Copyright © Microsoft Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "d3d12_context.h"
|
||||
#include "d3d12_compiler.h"
|
||||
#include "d3d12_debug.h"
|
||||
#include "d3d12_format.h"
|
||||
#include "d3d12_query.h"
|
||||
#include "d3d12_resource.h"
|
||||
#include "d3d12_screen.h"
|
||||
|
||||
#include "util/u_blitter.h"
|
||||
#include "util/format/u_format.h"
|
||||
|
||||
#include "nir_to_dxil.h"
|
||||
#include "nir_builder.h"
|
||||
|
||||
static void
|
||||
copy_buffer_region_no_barriers(struct d3d12_context *ctx,
|
||||
struct d3d12_resource *dst,
|
||||
uint64_t dst_offset,
|
||||
struct d3d12_resource *src,
|
||||
uint64_t src_offset,
|
||||
uint64_t size)
|
||||
{
|
||||
uint64_t dst_off, src_off;
|
||||
ID3D12Resource *dst_buf = d3d12_resource_underlying(dst, &dst_off);
|
||||
ID3D12Resource *src_buf = d3d12_resource_underlying(src, &src_off);
|
||||
|
||||
ctx->cmdlist->CopyBufferRegion(dst_buf, dst_offset + dst_off,
|
||||
src_buf, src_offset + src_off,
|
||||
size);
|
||||
}
|
||||
|
||||
inline static unsigned
|
||||
get_subresource_id(enum pipe_texture_target target, unsigned subres, unsigned stride,
|
||||
unsigned z, unsigned *updated_z, unsigned array_size, unsigned plane_slice)
|
||||
{
|
||||
if (d3d12_subresource_id_uses_layer(target)) {
|
||||
subres += stride * z;
|
||||
if (updated_z)
|
||||
*updated_z = 0;
|
||||
}
|
||||
return subres + plane_slice * array_size * stride;
|
||||
}
|
||||
|
||||
static void
|
||||
copy_subregion_no_barriers(struct d3d12_context *ctx,
|
||||
struct d3d12_resource *dst,
|
||||
unsigned dst_level,
|
||||
unsigned dstx, unsigned dsty, unsigned dstz,
|
||||
struct d3d12_resource *src,
|
||||
unsigned src_level,
|
||||
const struct pipe_box *psrc_box,
|
||||
unsigned mask)
|
||||
{
|
||||
UNUSED struct d3d12_screen *screen = d3d12_screen(ctx->base.screen);
|
||||
D3D12_TEXTURE_COPY_LOCATION src_loc, dst_loc;
|
||||
unsigned src_z = psrc_box->z;
|
||||
|
||||
int src_subres_stride = src->base.b.last_level + 1;
|
||||
int dst_subres_stride = dst->base.b.last_level + 1;
|
||||
|
||||
int src_array_size = src->base.b.array_size;
|
||||
int dst_array_size = dst->base.b.array_size;
|
||||
|
||||
int stencil_src_res_offset = 1;
|
||||
int stencil_dst_res_offset = 1;
|
||||
|
||||
int src_nres = 1;
|
||||
int dst_nres = 1;
|
||||
|
||||
if (dst->base.b.format == PIPE_FORMAT_Z24_UNORM_S8_UINT ||
|
||||
dst->base.b.format == PIPE_FORMAT_S8_UINT_Z24_UNORM ||
|
||||
dst->base.b.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) {
|
||||
stencil_dst_res_offset = dst_subres_stride * dst_array_size;
|
||||
src_nres = 2;
|
||||
}
|
||||
|
||||
if (src->base.b.format == PIPE_FORMAT_Z24_UNORM_S8_UINT ||
|
||||
src->base.b.format == PIPE_FORMAT_S8_UINT_Z24_UNORM ||
|
||||
dst->base.b.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) {
|
||||
stencil_src_res_offset = src_subres_stride * src_array_size;
|
||||
dst_nres = 2;
|
||||
}
|
||||
|
||||
static_assert(PIPE_MASK_S == 0x20 && PIPE_MASK_Z == 0x10, "unexpected ZS format mask");
|
||||
int nsubres = MIN2(src_nres, dst_nres);
|
||||
unsigned subresource_copy_mask = nsubres > 1 ? mask >> 4 : 1;
|
||||
|
||||
for (int subres = 0; subres < nsubres; ++subres) {
|
||||
|
||||
if (!(subresource_copy_mask & (1 << subres)))
|
||||
continue;
|
||||
|
||||
src_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
src_loc.SubresourceIndex = get_subresource_id(src->base.b.target, src_level, src_subres_stride, src_z, &src_z, src_array_size, src->plane_slice) +
|
||||
subres * stencil_src_res_offset;
|
||||
src_loc.pResource = d3d12_resource_resource(src);
|
||||
|
||||
dst_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
dst_loc.SubresourceIndex = get_subresource_id(dst->base.b.target, dst_level, dst_subres_stride, dstz, &dstz, dst_array_size, dst->plane_slice) +
|
||||
subres * stencil_dst_res_offset;
|
||||
dst_loc.pResource = d3d12_resource_resource(dst);
|
||||
|
||||
if (psrc_box->x == 0 && psrc_box->y == 0 && psrc_box->z == 0 &&
|
||||
psrc_box->width == (int)u_minify(src->base.b.width0, src_level) &&
|
||||
psrc_box->height == (int)u_minify(src->base.b.height0, src_level) &&
|
||||
psrc_box->depth == (int)u_minify(src->base.b.depth0, src_level)) {
|
||||
|
||||
assert((dstx == 0 && dsty == 0 && dstz == 0) ||
|
||||
screen->opts2.ProgrammableSamplePositionsTier !=
|
||||
D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED ||
|
||||
(!util_format_is_depth_or_stencil(dst->base.b.format) &&
|
||||
!util_format_is_depth_or_stencil(src->base.b.format) &&
|
||||
dst->base.b.nr_samples == src->base.b.nr_samples));
|
||||
|
||||
ctx->cmdlist->CopyTextureRegion(&dst_loc, dstx, dsty, dstz,
|
||||
&src_loc, NULL);
|
||||
|
||||
} else {
|
||||
D3D12_BOX src_box;
|
||||
src_box.left = psrc_box->x;
|
||||
src_box.right = MIN2(psrc_box->x + psrc_box->width, (int)u_minify(src->base.b.width0, src_level));
|
||||
src_box.top = psrc_box->y;
|
||||
src_box.bottom = MIN2(psrc_box->y + psrc_box->height, (int)u_minify(src->base.b.height0, src_level));
|
||||
src_box.front = src_z;
|
||||
src_box.back = src_z + psrc_box->depth;
|
||||
|
||||
assert((screen->opts2.ProgrammableSamplePositionsTier !=
|
||||
D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED ||
|
||||
(!util_format_is_depth_or_stencil(dst->base.b.format) &&
|
||||
!util_format_is_depth_or_stencil(src->base.b.format))) &&
|
||||
dst->base.b.nr_samples == src->base.b.nr_samples);
|
||||
|
||||
ctx->cmdlist->CopyTextureRegion(&dst_loc, dstx, dsty, dstz,
|
||||
&src_loc, &src_box);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
copy_resource_y_flipped_no_barriers(struct d3d12_context *ctx,
|
||||
struct d3d12_resource *dst,
|
||||
unsigned dst_level,
|
||||
const struct pipe_box *pdst_box,
|
||||
struct d3d12_resource *src,
|
||||
unsigned src_level,
|
||||
const struct pipe_box *psrc_box,
|
||||
unsigned mask)
|
||||
{
|
||||
if (D3D12_DEBUG_BLIT & d3d12_debug) {
|
||||
debug_printf("D3D12 BLIT as COPY: from %s@%d %dx%dx%d + %dx%dx%d\n",
|
||||
util_format_name(src->base.b.format), src_level,
|
||||
psrc_box->x, psrc_box->y, psrc_box->z,
|
||||
psrc_box->width, psrc_box->height, psrc_box->depth);
|
||||
debug_printf(" to %s@%d %dx%dx%d\n",
|
||||
util_format_name(dst->base.b.format), dst_level,
|
||||
pdst_box->x, pdst_box->y, pdst_box->z);
|
||||
}
|
||||
|
||||
struct pipe_box src_box = *psrc_box;
|
||||
int src_inc = psrc_box->height > 0 ? 1 : -1;
|
||||
int dst_inc = pdst_box->height > 0 ? 1 : -1;
|
||||
src_box.height = 1;
|
||||
int rows_to_copy = abs(psrc_box->height);
|
||||
|
||||
if (psrc_box->height < 0)
|
||||
--src_box.y;
|
||||
|
||||
for (int y = 0, dest_y = pdst_box->y; y < rows_to_copy;
|
||||
++y, src_box.y += src_inc, dest_y += dst_inc) {
|
||||
copy_subregion_no_barriers(ctx, dst, dst_level,
|
||||
pdst_box->x, dest_y, pdst_box->z,
|
||||
src, src_level, &src_box, mask);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
d3d12_direct_copy(struct d3d12_context *ctx,
|
||||
struct d3d12_resource *dst,
|
||||
unsigned dst_level,
|
||||
const struct pipe_box *pdst_box,
|
||||
struct d3d12_resource *src,
|
||||
unsigned src_level,
|
||||
const struct pipe_box *psrc_box,
|
||||
unsigned mask)
|
||||
{
|
||||
struct d3d12_batch *batch = d3d12_current_batch(ctx);
|
||||
|
||||
unsigned src_subres = get_subresource_id(src->base.b.target, src_level, src->base.b.last_level + 1,
|
||||
psrc_box->z, nullptr, src->base.b.array_size, src->plane_slice);
|
||||
unsigned dst_subres = get_subresource_id(dst->base.b.target, dst_level, dst->base.b.last_level + 1,
|
||||
pdst_box->z, nullptr, dst->base.b.array_size, dst->plane_slice);
|
||||
|
||||
if (D3D12_DEBUG_BLIT & d3d12_debug)
|
||||
debug_printf("BLIT: Direct copy from subres %d to subres %d\n",
|
||||
src_subres, dst_subres);
|
||||
|
||||
d3d12_transition_subresources_state(ctx, src, src_subres, 1, 0, 1,
|
||||
d3d12_get_format_start_plane(src->base.b.format),
|
||||
d3d12_get_format_num_planes(src->base.b.format),
|
||||
D3D12_RESOURCE_STATE_COPY_SOURCE,
|
||||
D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
|
||||
|
||||
d3d12_transition_subresources_state(ctx, dst, dst_subres, 1, 0, 1,
|
||||
d3d12_get_format_start_plane(dst->base.b.format),
|
||||
d3d12_get_format_num_planes(dst->base.b.format),
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
|
||||
|
||||
d3d12_apply_resource_states(ctx, false);
|
||||
|
||||
d3d12_batch_reference_resource(batch, src, false);
|
||||
d3d12_batch_reference_resource(batch, dst, true);
|
||||
|
||||
if (src->base.b.target == PIPE_BUFFER) {
|
||||
copy_buffer_region_no_barriers(ctx, dst, pdst_box->x,
|
||||
src, psrc_box->x, psrc_box->width);
|
||||
} else if (psrc_box->height == pdst_box->height) {
|
||||
/* No flipping, we can forward this directly to resource_copy_region */
|
||||
copy_subregion_no_barriers(ctx, dst, dst_level,
|
||||
pdst_box->x, pdst_box->y, pdst_box->z,
|
||||
src, src_level, psrc_box, mask);
|
||||
} else {
|
||||
assert(psrc_box->height == -pdst_box->height);
|
||||
copy_resource_y_flipped_no_barriers(ctx, dst, dst_level, pdst_box,
|
||||
src, src_level, psrc_box, mask);
|
||||
}
|
||||
}
|
||||
|
||||
struct pipe_resource *
|
||||
create_staging_resource(struct d3d12_context *ctx,
|
||||
struct d3d12_resource *src,
|
||||
unsigned src_level,
|
||||
const struct pipe_box *src_box,
|
||||
struct pipe_box *dst_box,
|
||||
unsigned mask)
|
||||
|
||||
{
|
||||
struct pipe_resource templ = {};
|
||||
struct pipe_resource *staging_res;
|
||||
struct pipe_box copy_src;
|
||||
|
||||
u_box_3d(MIN2(src_box->x, src_box->x + src_box->width),
|
||||
MIN2(src_box->y, src_box->y + src_box->height),
|
||||
MIN2(src_box->z, src_box->z + src_box->depth),
|
||||
abs(src_box->width), abs(src_box->height), abs(src_box->depth),
|
||||
©_src);
|
||||
|
||||
templ.format = src->base.b.format;
|
||||
templ.width0 = copy_src.width;
|
||||
templ.height0 = copy_src.height;
|
||||
templ.depth0 = copy_src.depth;
|
||||
templ.array_size = 1;
|
||||
templ.nr_samples = src->base.b.nr_samples;
|
||||
templ.nr_storage_samples = src->base.b.nr_storage_samples;
|
||||
templ.usage = PIPE_USAGE_STAGING;
|
||||
templ.bind = util_format_is_depth_or_stencil(templ.format) ? PIPE_BIND_DEPTH_STENCIL :
|
||||
util_format_is_compressed(templ.format) ? 0 : PIPE_BIND_RENDER_TARGET;
|
||||
templ.target = src->base.b.target;
|
||||
|
||||
staging_res = ctx->base.screen->resource_create(ctx->base.screen, &templ);
|
||||
|
||||
dst_box->x = 0;
|
||||
dst_box->y = 0;
|
||||
dst_box->z = 0;
|
||||
dst_box->width = copy_src.width;
|
||||
dst_box->height = copy_src.height;
|
||||
dst_box->depth = copy_src.depth;
|
||||
|
||||
d3d12_direct_copy(ctx, d3d12_resource(staging_res), 0, dst_box,
|
||||
src, src_level, ©_src, mask);
|
||||
|
||||
if (src_box->width < 0) {
|
||||
dst_box->x = dst_box->width;
|
||||
dst_box->width = src_box->width;
|
||||
}
|
||||
|
||||
if (src_box->height < 0) {
|
||||
dst_box->y = dst_box->height;
|
||||
dst_box->height = src_box->height;
|
||||
}
|
||||
|
||||
if (src_box->depth < 0) {
|
||||
dst_box->z = dst_box->depth;
|
||||
dst_box->depth = src_box->depth;
|
||||
}
|
||||
return staging_res;
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_resource_copy_region(struct pipe_context *pctx,
|
||||
struct pipe_resource *pdst,
|
||||
unsigned dst_level,
|
||||
unsigned dstx, unsigned dsty, unsigned dstz,
|
||||
struct pipe_resource *psrc,
|
||||
unsigned src_level,
|
||||
const struct pipe_box *psrc_box)
|
||||
{
|
||||
struct d3d12_context *ctx = d3d12_context(pctx);
|
||||
struct d3d12_resource *dst = d3d12_resource(pdst);
|
||||
struct d3d12_resource *src = d3d12_resource(psrc);
|
||||
struct pipe_resource *staging_res = NULL;
|
||||
const struct pipe_box *src_box = psrc_box;
|
||||
struct pipe_box staging_box, dst_box;
|
||||
|
||||
if (D3D12_DEBUG_BLIT & d3d12_debug) {
|
||||
debug_printf("D3D12 COPY: from %s@%d msaa:%d mips:%d %dx%dx%d + %dx%dx%d\n",
|
||||
util_format_name(psrc->format), src_level, psrc->nr_samples,
|
||||
psrc->last_level,
|
||||
psrc_box->x, psrc_box->y, psrc_box->z,
|
||||
psrc_box->width, psrc_box->height, psrc_box->depth);
|
||||
debug_printf(" to %s@%d msaa:%d mips:%d %dx%dx%d\n",
|
||||
util_format_name(pdst->format), dst_level, psrc->nr_samples,
|
||||
psrc->last_level, dstx, dsty, dstz);
|
||||
}
|
||||
|
||||
/* Use an intermediate resource if copying from/to the same subresource */
|
||||
if (d3d12_resource_resource(dst) == d3d12_resource_resource(src) && dst_level == src_level) {
|
||||
staging_res = create_staging_resource(ctx, src, src_level, psrc_box, &staging_box, PIPE_MASK_RGBAZS);
|
||||
src = d3d12_resource(staging_res);
|
||||
src_level = 0;
|
||||
src_box = &staging_box;
|
||||
}
|
||||
|
||||
dst_box.x = dstx;
|
||||
dst_box.y = dsty;
|
||||
dst_box.z = dstz;
|
||||
dst_box.width = psrc_box->width;
|
||||
dst_box.height = psrc_box->height;
|
||||
|
||||
d3d12_direct_copy(ctx, dst, dst_level, &dst_box,
|
||||
src, src_level, src_box, PIPE_MASK_RGBAZS);
|
||||
|
||||
if (staging_res)
|
||||
pipe_resource_reference(&staging_res, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
d3d12_context_copy_init(struct pipe_context *ctx)
|
||||
{
|
||||
ctx->resource_copy_region = d3d12_resource_copy_region;
|
||||
}
|
@@ -1307,6 +1307,7 @@ transfer_image_to_buf(struct d3d12_context *ctx,
|
||||
}
|
||||
|
||||
struct pipe_resource *resolved_resource = nullptr;
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
if (res->base.b.nr_samples > 1) {
|
||||
struct pipe_resource tmpl = res->base.b;
|
||||
tmpl.nr_samples = 0;
|
||||
@@ -1327,7 +1328,7 @@ transfer_image_to_buf(struct d3d12_context *ctx,
|
||||
d3d12_blit(&ctx->base, &resolve_info);
|
||||
res = (struct d3d12_resource *)resolved_resource;
|
||||
}
|
||||
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
if (res->base.b.target == PIPE_TEXTURE_3D) {
|
||||
transfer_image_part_to_buf(ctx, res, staging_res, trans, resid,
|
||||
|
@@ -472,8 +472,11 @@ d3d12_transition_resource_state(struct d3d12_context *ctx,
|
||||
D3D12_RESOURCE_STATES state,
|
||||
d3d12_transition_flags flags)
|
||||
{
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
if (flags & D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS)
|
||||
d3d12_invalidate_context_bindings(ctx, res);
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
d3d12_context_state_table_entry *state_entry = find_or_create_state_entry(ctx, res->bo);
|
||||
bool pending_memory_barrier = (flags & D3D12_TRANSITION_FLAG_PENDING_MEMORY_BARRIER) != 0;
|
||||
@@ -507,8 +510,11 @@ d3d12_transition_subresources_state(struct d3d12_context *ctx,
|
||||
D3D12_RESOURCE_STATES state,
|
||||
d3d12_transition_flags flags)
|
||||
{
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
if(flags & D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS)
|
||||
d3d12_invalidate_context_bindings(ctx, res);
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
d3d12_context_state_table_entry *state_entry = find_or_create_state_entry(ctx, res->bo);
|
||||
bool is_whole_resource = num_levels * num_layers * num_planes == state_entry->batch_end.num_subresources;
|
||||
|
@@ -1629,7 +1629,12 @@ d3d12_init_screen(struct d3d12_screen *screen, IUnknown *adapter)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
screen->max_feature_level = feature_levels.MaxSupportedFeatureLevel;
|
||||
#else
|
||||
screen->max_feature_level = D3D_FEATURE_LEVEL_1_0_GENERIC;
|
||||
#endif // HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
||||
screen->queue_type = (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0) ? D3D12_COMMAND_LIST_TYPE_DIRECT : D3D12_COMMAND_LIST_TYPE_COMPUTE;
|
||||
|
||||
#ifdef HAVE_GALLIUM_D3D12_GRAPHICS
|
||||
|
@@ -33,21 +33,23 @@ endif
|
||||
|
||||
files_libd3d12 = files(
|
||||
'd3d12_batch.cpp',
|
||||
'd3d12_blit.cpp',
|
||||
'd3d12_copy.cpp',
|
||||
'd3d12_bufmgr.cpp',
|
||||
'd3d12_context.cpp',
|
||||
'd3d12_draw.cpp',
|
||||
'd3d12_context_common.cpp',
|
||||
'd3d12_fence.cpp',
|
||||
'd3d12_format.c',
|
||||
'd3d12_residency.cpp',
|
||||
'd3d12_resource.cpp',
|
||||
'd3d12_resource_state.cpp',
|
||||
'd3d12_screen.cpp',
|
||||
'd3d12_surface.cpp',
|
||||
)
|
||||
|
||||
if with_gallium_d3d12_graphics
|
||||
files_libd3d12 += [
|
||||
'd3d12_blit.cpp',
|
||||
'd3d12_draw.cpp',
|
||||
'd3d12_surface.cpp',
|
||||
'd3d12_context_graphics.cpp',
|
||||
'd3d12_cmd_signature.cpp',
|
||||
'd3d12_compiler.cpp',
|
||||
'd3d12_compute_transforms.cpp',
|
||||
|
Reference in New Issue
Block a user