From 2074da0c396b3ae7cfd48b753cc84f84f5606f51 Mon Sep 17 00:00:00 2001 From: Sil Vilerino Date: Tue, 5 Mar 2024 18:35:24 -0500 Subject: [PATCH] d3d12: Refactor graphics functions from context and blit to separate files Reviewed-by: Jesse Natalie Part-of: --- src/gallium/drivers/d3d12/d3d12_batch.cpp | 15 +- src/gallium/drivers/d3d12/d3d12_blit.cpp | 327 +-------- src/gallium/drivers/d3d12/d3d12_blit.h | 11 + src/gallium/drivers/d3d12/d3d12_context.h | 60 +- .../drivers/d3d12/d3d12_context_common.cpp | 498 +++++++++++++ ...context.cpp => d3d12_context_graphics.cpp} | 657 +++--------------- src/gallium/drivers/d3d12/d3d12_copy.cpp | 364 ++++++++++ src/gallium/drivers/d3d12/d3d12_resource.cpp | 3 +- .../drivers/d3d12/d3d12_resource_state.cpp | 6 + src/gallium/drivers/d3d12/d3d12_screen.cpp | 5 + src/gallium/drivers/d3d12/meson.build | 10 +- 11 files changed, 1044 insertions(+), 912 deletions(-) create mode 100644 src/gallium/drivers/d3d12/d3d12_context_common.cpp rename src/gallium/drivers/d3d12/{d3d12_context.cpp => d3d12_context_graphics.cpp} (82%) create mode 100644 src/gallium/drivers/d3d12/d3d12_copy.cpp diff --git a/src/gallium/drivers/d3d12/d3d12_batch.cpp b/src/gallium/drivers/d3d12/d3d12_batch.cpp index 39b45ae8441..c29629d14cf 100644 --- a/src/gallium/drivers/d3d12/d3d12_batch.cpp +++ b/src/gallium/drivers/d3d12/d3d12_batch.cpp @@ -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 diff --git a/src/gallium/drivers/d3d12/d3d12_blit.cpp b/src/gallium/drivers/d3d12/d3d12_blit.cpp index efaaec744f2..7bf411476d7 100644 --- a/src/gallium/drivers/d3d12/d3d12_blit.cpp +++ b/src/gallium/drivers/d3d12/d3d12_blit.cpp @@ -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; } diff --git a/src/gallium/drivers/d3d12/d3d12_blit.h b/src/gallium/drivers/d3d12/d3d12_blit.h index f1ddc64b69d..c560bb78cc4 100644 --- a/src/gallium/drivers/d3d12/d3d12_blit.h +++ b/src/gallium/drivers/d3d12/d3d12_blit.h @@ -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 diff --git a/src/gallium/drivers/d3d12/d3d12_context.h b/src/gallium/drivers/d3d12/d3d12_context.h index 8e4aad03eae..68822cc30aa 100644 --- a/src/gallium/drivers/d3d12/d3d12_context.h +++ b/src/gallium/drivers/d3d12/d3d12_context.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); diff --git a/src/gallium/drivers/d3d12/d3d12_context_common.cpp b/src/gallium/drivers/d3d12/d3d12_context_common.cpp new file mode 100644 index 00000000000..502eda7d2a3 --- /dev/null +++ b/src/gallium/drivers/d3d12/d3d12_context_common.cpp @@ -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 + +#include + +#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; +} diff --git a/src/gallium/drivers/d3d12/d3d12_context.cpp b/src/gallium/drivers/d3d12/d3d12_context_graphics.cpp similarity index 82% rename from src/gallium/drivers/d3d12/d3d12_context.cpp rename to src/gallium/drivers/d3d12/d3d12_context_graphics.cpp index e050a751461..ccc7e028fa1 100644 --- a/src/gallium/drivers/d3d12/d3d12_context.cpp +++ b/src/gallium/drivers/d3d12/d3d12_context_graphics.cpp @@ -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; +} diff --git a/src/gallium/drivers/d3d12/d3d12_copy.cpp b/src/gallium/drivers/d3d12/d3d12_copy.cpp new file mode 100644 index 00000000000..f8356c1e172 --- /dev/null +++ b/src/gallium/drivers/d3d12/d3d12_copy.cpp @@ -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; +} diff --git a/src/gallium/drivers/d3d12/d3d12_resource.cpp b/src/gallium/drivers/d3d12/d3d12_resource.cpp index c098dbb062d..f912a719ad8 100644 --- a/src/gallium/drivers/d3d12/d3d12_resource.cpp +++ b/src/gallium/drivers/d3d12/d3d12_resource.cpp @@ -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, diff --git a/src/gallium/drivers/d3d12/d3d12_resource_state.cpp b/src/gallium/drivers/d3d12/d3d12_resource_state.cpp index def73aee8fb..8a4a91e00bb 100644 --- a/src/gallium/drivers/d3d12/d3d12_resource_state.cpp +++ b/src/gallium/drivers/d3d12/d3d12_resource_state.cpp @@ -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; diff --git a/src/gallium/drivers/d3d12/d3d12_screen.cpp b/src/gallium/drivers/d3d12/d3d12_screen.cpp index 73254d69416..259d78b5646 100644 --- a/src/gallium/drivers/d3d12/d3d12_screen.cpp +++ b/src/gallium/drivers/d3d12/d3d12_screen.cpp @@ -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 diff --git a/src/gallium/drivers/d3d12/meson.build b/src/gallium/drivers/d3d12/meson.build index 86aa2679288..3d4f5995f56 100644 --- a/src/gallium/drivers/d3d12/meson.build +++ b/src/gallium/drivers/d3d12/meson.build @@ -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',