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