xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/d3d12/d3d12_blit.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © Microsoft Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "d3d12_context.h"
25 #include "d3d12_compiler.h"
26 #include "d3d12_debug.h"
27 #include "d3d12_blit.h"
28 #include "d3d12_format.h"
29 #include "d3d12_query.h"
30 #include "d3d12_resource.h"
31 #include "d3d12_screen.h"
32 
33 #include "util/u_blitter.h"
34 #include "util/format/u_format.h"
35 
36 #include "nir_to_dxil.h"
37 #include "nir_builder.h"
38 
39 static bool
is_resolve(const struct pipe_blit_info * info)40 is_resolve(const struct pipe_blit_info *info)
41 {
42    return info->src.resource->nr_samples > 1 &&
43           info->dst.resource->nr_samples <= 1;
44 }
45 
46 static bool
resolve_supported(const struct pipe_blit_info * info)47 resolve_supported(const struct pipe_blit_info *info)
48 {
49    assert(is_resolve(info));
50 
51    // check for unsupported operations
52    if (util_format_is_depth_or_stencil(info->src.format) &&
53        info->mask != PIPE_MASK_Z) {
54       return false;
55    } else {
56       if (util_format_get_mask(info->dst.format) != info->mask ||
57           util_format_get_mask(info->src.format) != info->mask ||
58           util_format_has_alpha1(info->src.format))
59          return false;
60    }
61 
62    if (info->filter != PIPE_TEX_FILTER_NEAREST ||
63        info->scissor_enable ||
64        info->num_window_rectangles > 0 ||
65        info->alpha_blend)
66       return false;
67 
68    // formats need to match
69    struct d3d12_resource *src = d3d12_resource(info->src.resource);
70    struct d3d12_resource *dst = d3d12_resource(info->dst.resource);
71    if (src->dxgi_format != dst->dxgi_format)
72       return false;
73 
74    if (util_format_is_pure_integer(src->base.b.format))
75       return false;
76 
77    // sizes needs to match
78    if (info->src.box.width != info->dst.box.width ||
79        info->src.box.height != info->dst.box.height)
80       return false;
81 
82    // can only resolve full subresource
83    if (info->src.box.width != (int)u_minify(info->src.resource->width0,
84                                             info->src.level) ||
85        info->src.box.height != (int)u_minify(info->src.resource->height0,
86                                              info->src.level) ||
87        info->dst.box.width != (int)u_minify(info->dst.resource->width0,
88                                             info->dst.level) ||
89        info->dst.box.height != (int)u_minify(info->dst.resource->height0,
90                                              info->dst.level))
91       return false;
92 
93    return true;
94 }
95 
96 static void
blit_resolve(struct d3d12_context * ctx,const struct pipe_blit_info * info)97 blit_resolve(struct d3d12_context *ctx, const struct pipe_blit_info *info)
98 {
99    struct d3d12_batch *batch = d3d12_current_batch(ctx);
100    struct d3d12_resource *src = d3d12_resource(info->src.resource);
101    struct d3d12_resource *dst = d3d12_resource(info->dst.resource);
102 
103    d3d12_transition_resource_state(ctx, src,
104                                    D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
105                                    D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
106    d3d12_transition_resource_state(ctx, dst,
107                                    D3D12_RESOURCE_STATE_RESOLVE_DEST,
108                                    D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
109 
110    d3d12_apply_resource_states(ctx, false);
111 
112    d3d12_batch_reference_resource(batch, src, false);
113    d3d12_batch_reference_resource(batch, dst, true);
114 
115    DXGI_FORMAT dxgi_format = d3d12_get_resource_srv_format(src->base.b.format, src->base.b.target);
116 
117    assert(src->dxgi_format == dst->dxgi_format);
118    ctx->cmdlist->ResolveSubresource(
119       d3d12_resource_resource(dst), info->dst.level,
120       d3d12_resource_resource(src), info->src.level,
121       dxgi_format);
122 }
123 
124 static bool
formats_are_copy_compatible(enum pipe_format src,enum pipe_format dst)125 formats_are_copy_compatible(enum pipe_format src, enum pipe_format dst)
126 {
127    if (src == dst)
128       return true;
129 
130    /* We can skip the stencil copy */
131    if (util_format_get_depth_only(src) == dst ||
132        util_format_get_depth_only(dst) == src)
133       return true;
134 
135    return false;
136 }
137 
138 static bool
box_fits(const struct pipe_box * box,const struct pipe_resource * res,int level)139 box_fits(const struct pipe_box *box, const struct pipe_resource *res, int level)
140 {
141    unsigned lwidth = u_minify(res->width0, level);
142    unsigned lheight= u_minify(res->height0, level);
143    unsigned ldepth = res->target == PIPE_TEXTURE_3D ? u_minify(res->depth0, level) :
144                                                       res->array_size;
145 
146    unsigned wb = box->x;
147    unsigned we = box->x + box->width;
148 
149    unsigned hb = box->y;
150    unsigned he = box->y + box->height;
151 
152    unsigned db = box->z;
153    unsigned de = box->z + box->depth;
154 
155    return (wb <= lwidth && we <= lwidth &&
156            hb <= lheight && he <= lheight &&
157            db <= ldepth && de <= ldepth);
158 }
159 
160 static bool
direct_copy_supported(struct d3d12_screen * screen,const struct pipe_blit_info * info,bool have_predication)161 direct_copy_supported(struct d3d12_screen *screen,
162                       const struct pipe_blit_info *info,
163                       bool have_predication)
164 {
165    if (info->scissor_enable || info->alpha_blend ||
166        (have_predication && info->render_condition_enable) ||
167        MAX2(info->src.resource->nr_samples, 1) != MAX2(info->dst.resource->nr_samples, 1)) {
168       return false;
169    }
170 
171    if (!formats_are_copy_compatible(info->src.format, info->dst.format))
172       return false;
173 
174    if (info->src.format != info->src.resource->format ||
175        info->dst.format != info->dst.resource->format)
176       return false;
177 
178    if (util_format_is_depth_or_stencil(info->src.format) && !(info->mask & PIPE_MASK_ZS)) {
179       return false;
180    }
181 
182    if (!util_format_is_depth_or_stencil(info->src.format)) {
183       if (util_format_get_mask(info->dst.format) != info->mask ||
184           util_format_get_mask(info->src.format) != info->mask)
185          return false;
186    }
187 
188    if (abs(info->src.box.height) != info->dst.box.height) {
189       return false;
190    }
191 
192    if (info->src.box.height != info->dst.box.height &&
193        (!util_format_is_depth_or_stencil(info->src.format) ||
194         screen->opts2.ProgrammableSamplePositionsTier ==
195         D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED)) {
196       return false;
197    }
198 
199    if (!box_fits(&info->dst.box, info->dst.resource, info->dst.level)) {
200       return false;
201    }
202    if (!box_fits(&info->src.box, info->src.resource, info->src.level)) {
203       return false;
204    }
205 
206    if (info->src.box.width != info->dst.box.width) {
207       return false;
208    }
209 
210    if (info->src.box.depth != info->dst.box.depth) {
211       return false;
212    }
213 
214    if ((screen->opts2.ProgrammableSamplePositionsTier ==
215         D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED &&
216         (info->src.resource->bind & PIPE_BIND_DEPTH_STENCIL ||
217          info->dst.resource->bind & PIPE_BIND_DEPTH_STENCIL)) ||
218         info->src.resource->nr_samples != info->dst.resource->nr_samples) {
219 
220       if (info->dst.box.x != 0 ||
221           info->dst.box.y != 0 ||
222           info->dst.box.z != 0)
223          return false;
224 
225       if (info->src.box.x != 0 ||
226           info->src.box.y != 0 ||
227           info->src.box.z != 0 ||
228           info->src.box.width != (int)u_minify(info->src.resource->width0,
229                                                info->src.level) ||
230           info->src.box.height != (int)u_minify(info->src.resource->height0,
231                                                 info->src.level) ||
232           info->src.box.depth != (int)u_minify(info->src.resource->depth0,
233                                                info->src.level))
234          return false;
235    }
236 
237    return true;
238 }
239 
240 static bool
is_same_resource(const struct pipe_blit_info * info)241 is_same_resource(const struct pipe_blit_info *info)
242 {
243    return d3d12_resource_resource(d3d12_resource(info->src.resource)) ==
244              d3d12_resource_resource(d3d12_resource(info->dst.resource)) &&
245           info->src.level == info->dst.level;
246 }
247 
248 static void
blit_same_resource(struct d3d12_context * ctx,const struct pipe_blit_info * info)249 blit_same_resource(struct d3d12_context *ctx,
250                    const struct pipe_blit_info *info)
251 {
252    struct pipe_blit_info dst_info = *info;
253 
254    dst_info.src.level = 0;
255    dst_info.src.resource = create_staging_resource(ctx, d3d12_resource(info->src.resource),
256                                                    info->src.level,
257                                                    &info->src.box,
258                                                    &dst_info.src.box, PIPE_MASK_RGBAZS);
259    ctx->base.blit(&ctx->base, &dst_info);
260    pipe_resource_reference(&dst_info.src.resource, NULL);
261 }
262 
263 static void
util_blit_save_state(struct d3d12_context * ctx)264 util_blit_save_state(struct d3d12_context *ctx)
265 {
266    util_blitter_save_blend(ctx->blitter, ctx->gfx_pipeline_state.blend);
267    util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->gfx_pipeline_state.zsa);
268    util_blitter_save_vertex_elements(ctx->blitter, ctx->gfx_pipeline_state.ves);
269    util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
270    util_blitter_save_rasterizer(ctx->blitter, ctx->gfx_pipeline_state.rast);
271    util_blitter_save_fragment_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_FRAGMENT]);
272    util_blitter_save_vertex_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_VERTEX]);
273    util_blitter_save_geometry_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_GEOMETRY]);
274    util_blitter_save_tessctrl_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_TESS_CTRL]);
275    util_blitter_save_tesseval_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]);
276 
277    util_blitter_save_framebuffer(ctx->blitter, &ctx->fb);
278    util_blitter_save_viewport(ctx->blitter, ctx->viewport_states);
279    util_blitter_save_scissor(ctx->blitter, ctx->scissor_states);
280    util_blitter_save_fragment_sampler_states(ctx->blitter,
281                                              ctx->num_samplers[PIPE_SHADER_FRAGMENT],
282                                              (void **)ctx->samplers[PIPE_SHADER_FRAGMENT]);
283    util_blitter_save_fragment_sampler_views(ctx->blitter,
284                                             ctx->num_sampler_views[PIPE_SHADER_FRAGMENT],
285                                             ctx->sampler_views[PIPE_SHADER_FRAGMENT]);
286    util_blitter_save_fragment_constant_buffer_slot(ctx->blitter, ctx->cbufs[PIPE_SHADER_FRAGMENT]);
287    util_blitter_save_vertex_buffers(ctx->blitter, ctx->vbs, ctx->num_vbs);
288    util_blitter_save_sample_mask(ctx->blitter, ctx->gfx_pipeline_state.sample_mask, 0);
289    util_blitter_save_so_targets(ctx->blitter, ctx->gfx_pipeline_state.num_so_targets, ctx->so_targets);
290 }
291 
292 static void
util_blit(struct d3d12_context * ctx,const struct pipe_blit_info * info)293 util_blit(struct d3d12_context *ctx,
294           const struct pipe_blit_info *info)
295 {
296    util_blit_save_state(ctx);
297 
298    util_blitter_blit(ctx->blitter, info, NULL);
299 }
300 
301 static bool
resolve_stencil_supported(struct d3d12_context * ctx,const struct pipe_blit_info * info)302 resolve_stencil_supported(struct d3d12_context *ctx,
303                           const struct pipe_blit_info *info)
304 {
305    assert(is_resolve(info));
306 
307    if (!util_format_is_depth_or_stencil(info->src.format) ||
308        !(info->mask & PIPE_MASK_S))
309       return false;
310 
311    if (info->mask & PIPE_MASK_Z) {
312       struct pipe_blit_info new_info = *info;
313       new_info.mask = PIPE_MASK_Z;
314       if (!resolve_supported(&new_info) &&
315           !util_blitter_is_blit_supported(ctx->blitter, &new_info))
316          return false;
317    }
318 
319    struct pipe_blit_info new_info = *info;
320    new_info.dst.format = PIPE_FORMAT_R8_UINT;
321    return util_blitter_is_blit_supported(ctx->blitter, &new_info);
322 }
323 
324 static struct pipe_resource *
create_tmp_resource(struct pipe_screen * screen,const struct pipe_blit_info * info)325 create_tmp_resource(struct pipe_screen *screen,
326                     const struct pipe_blit_info *info)
327 {
328    struct pipe_resource tpl = {};
329    tpl.width0 = info->dst.box.width;
330    tpl.height0 = info->dst.box.height;
331    tpl.depth0 = info->dst.box.depth;
332    tpl.array_size = 1;
333    tpl.format = PIPE_FORMAT_R8_UINT;
334    tpl.target = info->dst.resource->target;
335    tpl.nr_samples = info->dst.resource->nr_samples;
336    tpl.nr_storage_samples = info->dst.resource->nr_storage_samples;
337    tpl.usage = PIPE_USAGE_STREAM;
338    tpl.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
339    return screen->resource_create(screen, &tpl);
340 }
341 
342 static void *
get_stencil_resolve_vs(struct d3d12_context * ctx)343 get_stencil_resolve_vs(struct d3d12_context *ctx)
344 {
345    if (ctx->stencil_resolve_vs)
346       return ctx->stencil_resolve_vs;
347 
348    nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_VERTEX,
349                                                   &d3d12_screen(ctx->base.screen)->nir_options,
350                                                   "linear_blit_vs");
351 
352    const struct glsl_type *vec4 = glsl_vec4_type();
353    nir_variable *pos_in = nir_variable_create(b.shader, nir_var_shader_in,
354                                               vec4, "pos");
355 
356    nir_variable *pos_out = nir_variable_create(b.shader, nir_var_shader_out,
357                                                vec4, "gl_Position");
358    pos_out->data.location = VARYING_SLOT_POS;
359 
360    nir_store_var(&b, pos_out, nir_load_var(&b, pos_in), 0xf);
361 
362    struct pipe_shader_state state = {};
363    state.type = PIPE_SHADER_IR_NIR;
364    state.ir.nir = b.shader;
365    ctx->stencil_resolve_vs = ctx->base.create_vs_state(&ctx->base, &state);
366 
367    return ctx->stencil_resolve_vs;
368 }
369 
370 static void *
get_stencil_resolve_fs(struct d3d12_context * ctx,bool no_flip)371 get_stencil_resolve_fs(struct d3d12_context *ctx, bool no_flip)
372 {
373    if (!no_flip && ctx->stencil_resolve_fs)
374       return ctx->stencil_resolve_fs;
375 
376    if (no_flip && ctx->stencil_resolve_fs_no_flip)
377       return ctx->stencil_resolve_fs_no_flip;
378 
379    nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT,
380                                                   &d3d12_screen(ctx->base.screen)->nir_options,
381                                                   no_flip ? "stencil_resolve_fs_no_flip" : "stencil_resolve_fs");
382 
383    nir_variable *stencil_out = nir_variable_create(b.shader,
384                                                    nir_var_shader_out,
385                                                    glsl_uint_type(),
386                                                    "stencil_out");
387    stencil_out->data.location = FRAG_RESULT_COLOR;
388 
389    const struct glsl_type *sampler_type =
390       glsl_sampler_type(GLSL_SAMPLER_DIM_MS, false, false, GLSL_TYPE_UINT);
391    nir_variable *sampler = nir_variable_create(b.shader, nir_var_uniform,
392                                                sampler_type, "stencil_tex");
393    sampler->data.binding = 0;
394    sampler->data.explicit_binding = true;
395 
396    nir_def *tex_deref = &nir_build_deref_var(&b, sampler)->def;
397 
398    nir_variable *pos_in = nir_variable_create(b.shader, nir_var_shader_in,
399                                               glsl_vec4_type(), "pos");
400    pos_in->data.location = VARYING_SLOT_POS; // VARYING_SLOT_VAR0?
401    nir_def *pos = nir_load_var(&b, pos_in);
402 
403    nir_def *pos_src;
404 
405    if (no_flip)
406       pos_src = pos;
407    else {
408       nir_tex_instr *txs = nir_tex_instr_create(b.shader, 1);
409       txs->op = nir_texop_txs;
410       txs->sampler_dim = GLSL_SAMPLER_DIM_MS;
411       txs->src[0] = nir_tex_src_for_ssa(nir_tex_src_texture_deref, tex_deref);
412       txs->is_array = false;
413       txs->dest_type = nir_type_int;
414 
415       nir_def_init(&txs->instr, &txs->def, 2, 32);
416       nir_builder_instr_insert(&b, &txs->instr);
417 
418       pos_src = nir_vec4(&b,
419                          nir_channel(&b, pos, 0),
420                          /*Height - pos_dest.y - 1*/
421                          nir_fsub(&b,
422                                   nir_fsub(&b,
423                                            nir_channel(&b, nir_i2f32(&b, &txs->def), 1),
424                                            nir_channel(&b, pos, 1)),
425                                   nir_imm_float(&b, 1.0)),
426                          nir_channel(&b, pos, 2),
427                          nir_channel(&b, pos, 3));
428    }
429 
430    nir_tex_instr *tex = nir_tex_instr_create(b.shader, 3);
431    tex->sampler_dim = GLSL_SAMPLER_DIM_MS;
432    tex->op = nir_texop_txf_ms;
433    tex->src[0] = nir_tex_src_for_ssa(nir_tex_src_coord,
434                                      nir_trim_vector(&b, nir_f2i32(&b, pos_src), 2));
435    tex->src[1] = nir_tex_src_for_ssa(nir_tex_src_ms_index, nir_imm_int(&b, 0)); /* just use first sample */
436    tex->src[2] = nir_tex_src_for_ssa(nir_tex_src_texture_deref, tex_deref);
437    tex->dest_type = nir_type_uint32;
438    tex->is_array = false;
439    tex->coord_components = 2;
440 
441    nir_def_init(&tex->instr, &tex->def, 4, 32);
442    nir_builder_instr_insert(&b, &tex->instr);
443 
444    nir_store_var(&b, stencil_out, nir_channel(&b, &tex->def, 1), 0x1);
445 
446    struct pipe_shader_state state = {};
447    state.type = PIPE_SHADER_IR_NIR;
448    state.ir.nir = b.shader;
449    void *result;
450    if (no_flip) {
451       result = ctx->base.create_fs_state(&ctx->base, &state);
452       ctx->stencil_resolve_fs_no_flip = result;
453    } else {
454       result = ctx->base.create_fs_state(&ctx->base, &state);
455       ctx->stencil_resolve_fs = result;
456    }
457 
458    return result;
459 }
460 
461 static void *
get_sampler_state(struct d3d12_context * ctx)462 get_sampler_state(struct d3d12_context *ctx)
463 {
464    if (ctx->sampler_state)
465       return ctx->sampler_state;
466 
467    struct pipe_sampler_state state;
468    memset(&state, 0, sizeof(state));
469    state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
470    state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
471    state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
472 
473    return ctx->sampler_state = ctx->base.create_sampler_state(&ctx->base, &state);
474 }
475 
476 static struct pipe_resource *
resolve_stencil_to_temp(struct d3d12_context * ctx,const struct pipe_blit_info * info)477 resolve_stencil_to_temp(struct d3d12_context *ctx,
478                         const struct pipe_blit_info *info)
479 {
480    struct pipe_context *pctx = &ctx->base;
481    struct pipe_resource *tmp = create_tmp_resource(pctx->screen, info);
482    if (!tmp) {
483       debug_printf("D3D12: failed to create stencil-resolve temp-resource\n");
484       return NULL;
485    }
486    assert(tmp->nr_samples < 2);
487 
488    /* resolve stencil into tmp */
489    struct pipe_surface dst_tmpl;
490    util_blitter_default_dst_texture(&dst_tmpl, tmp, 0, 0);
491    dst_tmpl.format = tmp->format;
492    struct pipe_surface *dst_surf = pctx->create_surface(pctx, tmp, &dst_tmpl);
493    if (!dst_surf) {
494       debug_printf("D3D12: failed to create stencil-resolve dst-surface\n");
495       return NULL;
496    }
497 
498    struct pipe_sampler_view src_templ, *src_view;
499    util_blitter_default_src_texture(ctx->blitter, &src_templ,
500                                     info->src.resource, info->src.level);
501    src_templ.format = util_format_stencil_only(info->src.format);
502    src_view = pctx->create_sampler_view(pctx, info->src.resource, &src_templ);
503 
504    void *sampler_state = get_sampler_state(ctx);
505 
506    util_blit_save_state(ctx);
507    pctx->set_sampler_views(pctx, PIPE_SHADER_FRAGMENT, 0, 1, 0, false, &src_view);
508    pctx->bind_sampler_states(pctx, PIPE_SHADER_FRAGMENT, 0, 1, &sampler_state);
509    util_blitter_custom_shader(ctx->blitter, dst_surf,
510                               get_stencil_resolve_vs(ctx),
511                               get_stencil_resolve_fs(ctx, info->src.box.height == info->dst.box.height));
512    util_blitter_restore_textures(ctx->blitter);
513    pipe_surface_reference(&dst_surf, NULL);
514    pipe_sampler_view_reference(&src_view, NULL);
515    return tmp;
516 }
517 
518 static void
blit_resolve_stencil(struct d3d12_context * ctx,const struct pipe_blit_info * info)519 blit_resolve_stencil(struct d3d12_context *ctx,
520                      const struct pipe_blit_info *info)
521 {
522    assert(info->mask & PIPE_MASK_S);
523 
524    if (D3D12_DEBUG_BLIT & d3d12_debug)
525       debug_printf("D3D12 BLIT: blit_resolve_stencil\n");
526 
527    if (info->mask & PIPE_MASK_Z) {
528       /* resolve depth into dst */
529       struct pipe_blit_info new_info = *info;
530       new_info.mask = PIPE_MASK_Z;
531 
532       if (resolve_supported(&new_info))
533          blit_resolve(ctx, &new_info);
534       else
535          util_blit(ctx, &new_info);
536    }
537 
538    struct pipe_resource *tmp = resolve_stencil_to_temp(ctx, info);
539 
540 
541    /* copy resolved stencil into dst */
542    struct d3d12_resource *dst = d3d12_resource(info->dst.resource);
543    d3d12_transition_subresources_state(ctx, d3d12_resource(tmp),
544                                        0, 1, 0, 1, 0, 1,
545                                        D3D12_RESOURCE_STATE_COPY_SOURCE,
546                                        D3D12_TRANSITION_FLAG_NONE);
547    d3d12_transition_subresources_state(ctx, dst,
548                                        0, 1, 0, 1, 1, 1,
549                                        D3D12_RESOURCE_STATE_COPY_DEST,
550                                        D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
551    d3d12_apply_resource_states(ctx, false);
552 
553    struct d3d12_batch *batch = d3d12_current_batch(ctx);
554    d3d12_batch_reference_resource(batch, d3d12_resource(tmp), false);
555    d3d12_batch_reference_resource(batch, dst, true);
556 
557    D3D12_BOX src_box;
558    src_box.left = src_box.top = src_box.front = 0;
559    src_box.right = tmp->width0;
560    src_box.bottom = tmp->height0;
561    src_box.back = tmp->depth0;
562 
563    D3D12_TEXTURE_COPY_LOCATION src_loc;
564    src_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
565    src_loc.SubresourceIndex = 0;
566    src_loc.pResource = d3d12_resource_resource(d3d12_resource(tmp));
567 
568    D3D12_TEXTURE_COPY_LOCATION dst_loc;
569    dst_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
570    dst_loc.SubresourceIndex = 1;
571    dst_loc.pResource = d3d12_resource_resource(dst);
572 
573    ctx->cmdlist->CopyTextureRegion(&dst_loc, info->dst.box.x,
574                                    info->dst.box.y, info->dst.box.z,
575                                    &src_loc, &src_box);
576 
577    pipe_resource_reference(&tmp, NULL);
578 }
579 
580 static bool
replicate_stencil_supported(struct d3d12_context * ctx,const struct pipe_blit_info * info)581 replicate_stencil_supported(struct d3d12_context *ctx,
582                             const struct pipe_blit_info *info)
583 {
584    if (!util_format_is_depth_or_stencil(info->src.format) ||
585        !(info->mask & PIPE_MASK_S))
586       return false;
587 
588    if (info->mask & PIPE_MASK_Z) {
589       struct pipe_blit_info new_info = *info;
590       new_info.mask = PIPE_MASK_Z;
591       if (!util_blitter_is_blit_supported(ctx->blitter, &new_info))
592          return false;
593    }
594 
595    return true;
596 }
597 
598 static void
blit_replicate_stencil(struct d3d12_context * ctx,const struct pipe_blit_info * info)599 blit_replicate_stencil(struct d3d12_context *ctx,
600                        const struct pipe_blit_info *info)
601 {
602    struct pipe_context *pctx = &ctx->base;
603    assert(info->mask & PIPE_MASK_S);
604 
605    if (D3D12_DEBUG_BLIT & d3d12_debug)
606       debug_printf("D3D12 BLIT: blit_replicate_stencil\n");
607 
608    if (info->mask & PIPE_MASK_Z) {
609       /* resolve depth into dst */
610       struct pipe_blit_info new_info = *info;
611       new_info.mask = PIPE_MASK_Z;
612       util_blit(ctx, &new_info);
613    }
614 
615    struct pipe_surface *dst_view, dst_templ;
616    util_blitter_default_dst_texture(&dst_templ, info->dst.resource,
617                            info->dst.level, info->dst.box.z);
618    dst_view = pctx->create_surface(pctx, info->dst.resource, &dst_templ);
619 
620    util_blit_save_state(ctx);
621    util_blitter_clear_depth_stencil(ctx->blitter, dst_view, PIPE_CLEAR_STENCIL,
622                                     0, 0, info->dst.box.x, info->dst.box.y,
623                                     info->dst.box.width, info->dst.box.height);
624    util_blit_save_state(ctx);
625    util_blitter_stencil_fallback(ctx->blitter, info->dst.resource,
626                                  info->dst.level,
627                                  &info->dst.box,
628                                  info->src.resource,
629                                  info->src.level,
630                                  &info->src.box,
631                                  info->scissor_enable ? &info->scissor : NULL);
632 
633    pipe_surface_release(pctx, &dst_view);
634 }
635 
636 void
d3d12_blit(struct pipe_context * pctx,const struct pipe_blit_info * info)637 d3d12_blit(struct pipe_context *pctx,
638            const struct pipe_blit_info *info)
639 {
640    struct d3d12_context *ctx = d3d12_context(pctx);
641 
642    if (!info->render_condition_enable && ctx->current_predication) {
643       if (D3D12_DEBUG_BLIT & d3d12_debug)
644          debug_printf("D3D12 BLIT: Disable predication\n");
645       ctx->cmdlist->SetPredication(nullptr, 0, D3D12_PREDICATION_OP_EQUAL_ZERO);
646    }
647 
648    if (D3D12_DEBUG_BLIT & d3d12_debug) {
649       debug_printf("D3D12 BLIT: from %s@%d msaa:%d %dx%dx%d + %dx%dx%d\n",
650                    util_format_name(info->src.format), info->src.level,
651                    info->src.resource->nr_samples,
652                    info->src.box.x, info->src.box.y, info->src.box.z,
653                    info->src.box.width, info->src.box.height, info->src.box.depth);
654       debug_printf("            to   %s@%d msaa:%d %dx%dx%d + %dx%dx%d ",
655                    util_format_name(info->dst.format), info->dst.level,
656                    info->dst.resource->nr_samples,
657                    info->dst.box.x, info->dst.box.y, info->dst.box.z,
658                    info->dst.box.width, info->dst.box.height, info->dst.box.depth);
659       debug_printf("| flags %s%s%s\n",
660                    info->render_condition_enable ? "cond " : "",
661                    info->scissor_enable ? "scissor " : "",
662                    info->alpha_blend ? "blend" : "");
663    }
664 
665    if (is_same_resource(info))
666       blit_same_resource(ctx, info);
667    else if (is_resolve(info)) {
668       if (resolve_supported(info))
669          blit_resolve(ctx, info);
670       else if (util_blitter_is_blit_supported(ctx->blitter, info))
671          util_blit(ctx, info);
672       else if (resolve_stencil_supported(ctx, info))
673          blit_resolve_stencil(ctx, info);
674       else
675          debug_printf("D3D12: resolve unsupported %s -> %s\n",
676                     util_format_short_name(info->src.resource->format),
677                     util_format_short_name(info->dst.resource->format));
678    } else if (direct_copy_supported(d3d12_screen(pctx->screen), info,
679                                     ctx->current_predication != nullptr))
680       d3d12_direct_copy(ctx, d3d12_resource(info->dst.resource),
681                         info->dst.level, &info->dst.box,
682                         d3d12_resource(info->src.resource),
683                         info->src.level, &info->src.box, info->mask);
684    else if (util_blitter_is_blit_supported(ctx->blitter, info))
685       util_blit(ctx, info);
686    else if (replicate_stencil_supported(ctx, info))
687       blit_replicate_stencil(ctx, info);
688    else
689       debug_printf("D3D12: blit unsupported %s -> %s\n",
690                  util_format_short_name(info->src.resource->format),
691                  util_format_short_name(info->dst.resource->format));
692 
693    if (d3d12_screen(pctx->screen)->max_feature_level >= D3D_FEATURE_LEVEL_11_0) {
694       if (!info->render_condition_enable && ctx->current_predication) {
695          d3d12_enable_predication(ctx);
696          if (D3D12_DEBUG_BLIT & d3d12_debug)
697             debug_printf("D3D12 BLIT: Re-enable predication\n");
698       }
699    }
700 }
701 
702 void
d3d12_context_blit_init(struct pipe_context * ctx)703 d3d12_context_blit_init(struct pipe_context *ctx)
704 {
705    ctx->blit = d3d12_blit;
706 }
707