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