1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © Microsoft Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "d3d12_context.h"
25bf215546Sopenharmony_ci#include "d3d12_compiler.h"
26bf215546Sopenharmony_ci#include "d3d12_debug.h"
27bf215546Sopenharmony_ci#include "d3d12_format.h"
28bf215546Sopenharmony_ci#include "d3d12_query.h"
29bf215546Sopenharmony_ci#include "d3d12_resource.h"
30bf215546Sopenharmony_ci#include "d3d12_screen.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "util/u_blitter.h"
33bf215546Sopenharmony_ci#include "util/format/u_format.h"
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#include "nir_to_dxil.h"
36bf215546Sopenharmony_ci#include "nir_builder.h"
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_cistatic void
39bf215546Sopenharmony_cicopy_buffer_region_no_barriers(struct d3d12_context *ctx,
40bf215546Sopenharmony_ci                               struct d3d12_resource *dst,
41bf215546Sopenharmony_ci                               uint64_t dst_offset,
42bf215546Sopenharmony_ci                               struct d3d12_resource *src,
43bf215546Sopenharmony_ci                               uint64_t src_offset,
44bf215546Sopenharmony_ci                               uint64_t size)
45bf215546Sopenharmony_ci{
46bf215546Sopenharmony_ci   uint64_t dst_off, src_off;
47bf215546Sopenharmony_ci   ID3D12Resource *dst_buf = d3d12_resource_underlying(dst, &dst_off);
48bf215546Sopenharmony_ci   ID3D12Resource *src_buf = d3d12_resource_underlying(src, &src_off);
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci   ctx->cmdlist->CopyBufferRegion(dst_buf, dst_offset + dst_off,
51bf215546Sopenharmony_ci                                  src_buf, src_offset + src_off,
52bf215546Sopenharmony_ci                                  size);
53bf215546Sopenharmony_ci}
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_cistatic bool
56bf215546Sopenharmony_ciis_resolve(const struct pipe_blit_info *info)
57bf215546Sopenharmony_ci{
58bf215546Sopenharmony_ci   return info->src.resource->nr_samples > 1 &&
59bf215546Sopenharmony_ci          info->dst.resource->nr_samples <= 1;
60bf215546Sopenharmony_ci}
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_cistatic bool
63bf215546Sopenharmony_ciresolve_supported(const struct pipe_blit_info *info)
64bf215546Sopenharmony_ci{
65bf215546Sopenharmony_ci   assert(is_resolve(info));
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci   // check for unsupported operations
68bf215546Sopenharmony_ci   if (util_format_is_depth_or_stencil(info->src.format) &&
69bf215546Sopenharmony_ci       info->mask != PIPE_MASK_Z) {
70bf215546Sopenharmony_ci      return false;
71bf215546Sopenharmony_ci   } else {
72bf215546Sopenharmony_ci      if (util_format_get_mask(info->dst.format) != info->mask ||
73bf215546Sopenharmony_ci          util_format_get_mask(info->src.format) != info->mask ||
74bf215546Sopenharmony_ci          util_format_has_alpha1(info->src.format))
75bf215546Sopenharmony_ci         return false;
76bf215546Sopenharmony_ci   }
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci   if (info->filter != PIPE_TEX_FILTER_NEAREST ||
79bf215546Sopenharmony_ci       info->scissor_enable ||
80bf215546Sopenharmony_ci       info->num_window_rectangles > 0 ||
81bf215546Sopenharmony_ci       info->alpha_blend)
82bf215546Sopenharmony_ci      return false;
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci   // formats need to match
85bf215546Sopenharmony_ci   struct d3d12_resource *src = d3d12_resource(info->src.resource);
86bf215546Sopenharmony_ci   struct d3d12_resource *dst = d3d12_resource(info->dst.resource);
87bf215546Sopenharmony_ci   if (src->dxgi_format != dst->dxgi_format)
88bf215546Sopenharmony_ci      return false;
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ci   if (util_format_is_pure_integer(src->base.b.format))
91bf215546Sopenharmony_ci      return false;
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci   // sizes needs to match
94bf215546Sopenharmony_ci   if (info->src.box.width != info->dst.box.width ||
95bf215546Sopenharmony_ci       info->src.box.height != info->dst.box.height)
96bf215546Sopenharmony_ci      return false;
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci   // can only resolve full subresource
99bf215546Sopenharmony_ci   if (info->src.box.width != (int)u_minify(info->src.resource->width0,
100bf215546Sopenharmony_ci                                            info->src.level) ||
101bf215546Sopenharmony_ci       info->src.box.height != (int)u_minify(info->src.resource->height0,
102bf215546Sopenharmony_ci                                             info->src.level) ||
103bf215546Sopenharmony_ci       info->dst.box.width != (int)u_minify(info->dst.resource->width0,
104bf215546Sopenharmony_ci                                            info->dst.level) ||
105bf215546Sopenharmony_ci       info->dst.box.height != (int)u_minify(info->dst.resource->height0,
106bf215546Sopenharmony_ci                                             info->dst.level))
107bf215546Sopenharmony_ci      return false;
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci   return true;
110bf215546Sopenharmony_ci}
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_cistatic void
113bf215546Sopenharmony_ciblit_resolve(struct d3d12_context *ctx, const struct pipe_blit_info *info)
114bf215546Sopenharmony_ci{
115bf215546Sopenharmony_ci   struct d3d12_batch *batch = d3d12_current_batch(ctx);
116bf215546Sopenharmony_ci   struct d3d12_resource *src = d3d12_resource(info->src.resource);
117bf215546Sopenharmony_ci   struct d3d12_resource *dst = d3d12_resource(info->dst.resource);
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ci   d3d12_transition_resource_state(ctx, src,
120bf215546Sopenharmony_ci                                   D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
121bf215546Sopenharmony_ci                                   D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
122bf215546Sopenharmony_ci   d3d12_transition_resource_state(ctx, dst,
123bf215546Sopenharmony_ci                                   D3D12_RESOURCE_STATE_RESOLVE_DEST,
124bf215546Sopenharmony_ci                                   D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci   d3d12_apply_resource_states(ctx, false);
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   d3d12_batch_reference_resource(batch, src, false);
129bf215546Sopenharmony_ci   d3d12_batch_reference_resource(batch, dst, true);
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci   DXGI_FORMAT dxgi_format = d3d12_get_resource_srv_format(src->base.b.format, src->base.b.target);
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci   assert(src->dxgi_format == dst->dxgi_format);
134bf215546Sopenharmony_ci   ctx->cmdlist->ResolveSubresource(
135bf215546Sopenharmony_ci      d3d12_resource_resource(dst), info->dst.level,
136bf215546Sopenharmony_ci      d3d12_resource_resource(src), info->src.level,
137bf215546Sopenharmony_ci      dxgi_format);
138bf215546Sopenharmony_ci}
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_cistatic bool
141bf215546Sopenharmony_ciformats_are_copy_compatible(enum pipe_format src, enum pipe_format dst)
142bf215546Sopenharmony_ci{
143bf215546Sopenharmony_ci   if (src == dst)
144bf215546Sopenharmony_ci      return true;
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci   /* We can skip the stencil copy */
147bf215546Sopenharmony_ci   if (util_format_get_depth_only(src) == dst ||
148bf215546Sopenharmony_ci       util_format_get_depth_only(dst) == src)
149bf215546Sopenharmony_ci      return true;
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci   return false;
152bf215546Sopenharmony_ci}
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_cistatic bool
155bf215546Sopenharmony_cibox_fits(const struct pipe_box *box, const struct pipe_resource *res, int level)
156bf215546Sopenharmony_ci{
157bf215546Sopenharmony_ci   unsigned lwidth = u_minify(res->width0, level);
158bf215546Sopenharmony_ci   unsigned lheight= u_minify(res->height0, level);
159bf215546Sopenharmony_ci   unsigned ldepth = res->target == PIPE_TEXTURE_3D ? u_minify(res->depth0, level) :
160bf215546Sopenharmony_ci                                                      res->array_size;
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci   unsigned wb = box->x;
163bf215546Sopenharmony_ci   unsigned we = box->x + box->width;
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci   unsigned hb = box->y;
166bf215546Sopenharmony_ci   unsigned he = box->y + box->height;
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci   unsigned db = box->z;
169bf215546Sopenharmony_ci   unsigned de = box->z + box->depth;
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   return (wb <= lwidth && we <= lwidth &&
172bf215546Sopenharmony_ci           hb <= lheight && he <= lheight &&
173bf215546Sopenharmony_ci           db <= ldepth && de <= ldepth);
174bf215546Sopenharmony_ci}
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_cistatic bool
177bf215546Sopenharmony_cidirect_copy_supported(struct d3d12_screen *screen,
178bf215546Sopenharmony_ci                      const struct pipe_blit_info *info,
179bf215546Sopenharmony_ci                      bool have_predication)
180bf215546Sopenharmony_ci{
181bf215546Sopenharmony_ci   if (info->scissor_enable || info->alpha_blend ||
182bf215546Sopenharmony_ci       (have_predication && info->render_condition_enable) ||
183bf215546Sopenharmony_ci       MAX2(info->src.resource->nr_samples, 1) != MAX2(info->dst.resource->nr_samples, 1)) {
184bf215546Sopenharmony_ci      return false;
185bf215546Sopenharmony_ci   }
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci   if (!formats_are_copy_compatible(info->src.format, info->dst.format))
188bf215546Sopenharmony_ci      return false;
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci   if (util_format_is_depth_or_stencil(info->src.format) && !(info->mask & PIPE_MASK_ZS)) {
191bf215546Sopenharmony_ci      return false;
192bf215546Sopenharmony_ci   }
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci   if (!util_format_is_depth_or_stencil(info->src.format)) {
195bf215546Sopenharmony_ci      if (util_format_get_mask(info->dst.format) != info->mask ||
196bf215546Sopenharmony_ci          util_format_get_mask(info->src.format) != info->mask)
197bf215546Sopenharmony_ci         return false;
198bf215546Sopenharmony_ci   }
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci   if (abs(info->src.box.height) != info->dst.box.height) {
201bf215546Sopenharmony_ci      return false;
202bf215546Sopenharmony_ci   }
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci   if (info->src.box.height != info->dst.box.height &&
205bf215546Sopenharmony_ci       (!util_format_is_depth_or_stencil(info->src.format) ||
206bf215546Sopenharmony_ci        screen->opts2.ProgrammableSamplePositionsTier ==
207bf215546Sopenharmony_ci        D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED)) {
208bf215546Sopenharmony_ci      return false;
209bf215546Sopenharmony_ci   }
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci   if (!box_fits(&info->dst.box, info->dst.resource, info->dst.level)) {
212bf215546Sopenharmony_ci      return false;
213bf215546Sopenharmony_ci   }
214bf215546Sopenharmony_ci   if (!box_fits(&info->src.box, info->src.resource, info->src.level)) {
215bf215546Sopenharmony_ci      return false;
216bf215546Sopenharmony_ci   }
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci   if (info->src.box.width != info->dst.box.width) {
219bf215546Sopenharmony_ci      return false;
220bf215546Sopenharmony_ci   }
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_ci   if (info->src.box.depth != info->dst.box.depth) {
223bf215546Sopenharmony_ci      return false;
224bf215546Sopenharmony_ci   }
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci   if ((screen->opts2.ProgrammableSamplePositionsTier ==
227bf215546Sopenharmony_ci        D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED &&
228bf215546Sopenharmony_ci        (info->src.resource->bind & PIPE_BIND_DEPTH_STENCIL ||
229bf215546Sopenharmony_ci         info->dst.resource->bind & PIPE_BIND_DEPTH_STENCIL)) ||
230bf215546Sopenharmony_ci        info->src.resource->nr_samples != info->dst.resource->nr_samples) {
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci      if (info->dst.box.x != 0 ||
233bf215546Sopenharmony_ci          info->dst.box.y != 0 ||
234bf215546Sopenharmony_ci          info->dst.box.z != 0)
235bf215546Sopenharmony_ci         return false;
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_ci      if (info->src.box.x != 0 ||
238bf215546Sopenharmony_ci          info->src.box.y != 0 ||
239bf215546Sopenharmony_ci          info->src.box.z != 0 ||
240bf215546Sopenharmony_ci          info->src.box.width != (int)u_minify(info->src.resource->width0,
241bf215546Sopenharmony_ci                                               info->src.level) ||
242bf215546Sopenharmony_ci          info->src.box.height != (int)u_minify(info->src.resource->height0,
243bf215546Sopenharmony_ci                                                info->src.level) ||
244bf215546Sopenharmony_ci          info->src.box.depth != (int)u_minify(info->src.resource->depth0,
245bf215546Sopenharmony_ci                                               info->src.level))
246bf215546Sopenharmony_ci         return false;
247bf215546Sopenharmony_ci   }
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_ci   return true;
250bf215546Sopenharmony_ci}
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_ciinline static unsigned
253bf215546Sopenharmony_ciget_subresource_id(enum pipe_texture_target target, unsigned subres, unsigned stride,
254bf215546Sopenharmony_ci                   unsigned z, unsigned *updated_z, unsigned array_size, unsigned plane_slice)
255bf215546Sopenharmony_ci{
256bf215546Sopenharmony_ci   if (d3d12_subresource_id_uses_layer(target)) {
257bf215546Sopenharmony_ci      subres += stride * z;
258bf215546Sopenharmony_ci      if (updated_z)
259bf215546Sopenharmony_ci         *updated_z = 0;
260bf215546Sopenharmony_ci   }
261bf215546Sopenharmony_ci   return subres + plane_slice * array_size * stride;
262bf215546Sopenharmony_ci}
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_cistatic void
265bf215546Sopenharmony_cicopy_subregion_no_barriers(struct d3d12_context *ctx,
266bf215546Sopenharmony_ci                           struct d3d12_resource *dst,
267bf215546Sopenharmony_ci                           unsigned dst_level,
268bf215546Sopenharmony_ci                           unsigned dstx, unsigned dsty, unsigned dstz,
269bf215546Sopenharmony_ci                           struct d3d12_resource *src,
270bf215546Sopenharmony_ci                           unsigned src_level,
271bf215546Sopenharmony_ci                           const struct pipe_box *psrc_box,
272bf215546Sopenharmony_ci                           unsigned mask)
273bf215546Sopenharmony_ci{
274bf215546Sopenharmony_ci   UNUSED struct d3d12_screen *screen = d3d12_screen(ctx->base.screen);
275bf215546Sopenharmony_ci   D3D12_TEXTURE_COPY_LOCATION src_loc, dst_loc;
276bf215546Sopenharmony_ci   unsigned src_z = psrc_box->z;
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci   int src_subres_stride = src->base.b.last_level + 1;
279bf215546Sopenharmony_ci   int dst_subres_stride = dst->base.b.last_level + 1;
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci   int src_array_size = src->base.b.array_size;
282bf215546Sopenharmony_ci   int dst_array_size = dst->base.b.array_size;
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci   if (dst->base.b.target == PIPE_TEXTURE_CUBE)
285bf215546Sopenharmony_ci      dst_array_size *= 6;
286bf215546Sopenharmony_ci
287bf215546Sopenharmony_ci   if (src->base.b.target == PIPE_TEXTURE_CUBE)
288bf215546Sopenharmony_ci      src_array_size *= 6;
289bf215546Sopenharmony_ci
290bf215546Sopenharmony_ci   int stencil_src_res_offset = 1;
291bf215546Sopenharmony_ci   int stencil_dst_res_offset = 1;
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci   int src_nres = 1;
294bf215546Sopenharmony_ci   int dst_nres = 1;
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci   if (dst->base.b.format == PIPE_FORMAT_Z24_UNORM_S8_UINT ||
297bf215546Sopenharmony_ci       dst->base.b.format == PIPE_FORMAT_S8_UINT_Z24_UNORM ||
298bf215546Sopenharmony_ci       dst->base.b.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) {
299bf215546Sopenharmony_ci      stencil_dst_res_offset = dst_subres_stride * dst_array_size;
300bf215546Sopenharmony_ci      src_nres = 2;
301bf215546Sopenharmony_ci   }
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci   if (src->base.b.format == PIPE_FORMAT_Z24_UNORM_S8_UINT ||
304bf215546Sopenharmony_ci       src->base.b.format == PIPE_FORMAT_S8_UINT_Z24_UNORM ||
305bf215546Sopenharmony_ci       dst->base.b.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) {
306bf215546Sopenharmony_ci      stencil_src_res_offset = src_subres_stride * src_array_size;
307bf215546Sopenharmony_ci      dst_nres = 2;
308bf215546Sopenharmony_ci   }
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_ci   static_assert(PIPE_MASK_S == 0x20 && PIPE_MASK_Z == 0x10, "unexpected ZS format mask");
311bf215546Sopenharmony_ci   int nsubres = MIN2(src_nres, dst_nres);
312bf215546Sopenharmony_ci   unsigned subresource_copy_mask = nsubres > 1 ? mask >> 4 : 1;
313bf215546Sopenharmony_ci
314bf215546Sopenharmony_ci   for (int subres = 0; subres < nsubres; ++subres) {
315bf215546Sopenharmony_ci
316bf215546Sopenharmony_ci      if (!(subresource_copy_mask & (1 << subres)))
317bf215546Sopenharmony_ci         continue;
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci      src_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
320bf215546Sopenharmony_ci      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) +
321bf215546Sopenharmony_ci                                 subres * stencil_src_res_offset;
322bf215546Sopenharmony_ci      src_loc.pResource = d3d12_resource_resource(src);
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ci      dst_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
325bf215546Sopenharmony_ci      dst_loc.SubresourceIndex = get_subresource_id(dst->base.b.target, dst_level, dst_subres_stride, dstz, &dstz, dst_array_size, dst->plane_slice) +
326bf215546Sopenharmony_ci                                 subres * stencil_dst_res_offset;
327bf215546Sopenharmony_ci      dst_loc.pResource = d3d12_resource_resource(dst);
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci      if (psrc_box->x == 0 && psrc_box->y == 0 && psrc_box->z == 0 &&
330bf215546Sopenharmony_ci          psrc_box->width == (int)u_minify(src->base.b.width0, src_level) &&
331bf215546Sopenharmony_ci          psrc_box->height == (int)u_minify(src->base.b.height0, src_level) &&
332bf215546Sopenharmony_ci          psrc_box->depth == (int)u_minify(src->base.b.depth0, src_level)) {
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci         assert((dstx == 0 && dsty == 0 && dstz == 0) ||
335bf215546Sopenharmony_ci                screen->opts2.ProgrammableSamplePositionsTier !=
336bf215546Sopenharmony_ci                D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED ||
337bf215546Sopenharmony_ci                (!util_format_is_depth_or_stencil(dst->base.b.format) &&
338bf215546Sopenharmony_ci                 !util_format_is_depth_or_stencil(src->base.b.format) &&
339bf215546Sopenharmony_ci                  dst->base.b.nr_samples == src->base.b.nr_samples));
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ci         ctx->cmdlist->CopyTextureRegion(&dst_loc, dstx, dsty, dstz,
342bf215546Sopenharmony_ci                                         &src_loc, NULL);
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci      } else {
345bf215546Sopenharmony_ci         D3D12_BOX src_box;
346bf215546Sopenharmony_ci         src_box.left = psrc_box->x;
347bf215546Sopenharmony_ci         src_box.right = MIN2(psrc_box->x + psrc_box->width, (int)u_minify(src->base.b.width0, src_level));
348bf215546Sopenharmony_ci         src_box.top = psrc_box->y;
349bf215546Sopenharmony_ci         src_box.bottom = MIN2(psrc_box->y + psrc_box->height, (int)u_minify(src->base.b.height0, src_level));
350bf215546Sopenharmony_ci         src_box.front = src_z;
351bf215546Sopenharmony_ci         src_box.back = src_z + psrc_box->depth;
352bf215546Sopenharmony_ci
353bf215546Sopenharmony_ci         assert((screen->opts2.ProgrammableSamplePositionsTier !=
354bf215546Sopenharmony_ci                 D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED ||
355bf215546Sopenharmony_ci                 (!util_format_is_depth_or_stencil(dst->base.b.format) &&
356bf215546Sopenharmony_ci                  !util_format_is_depth_or_stencil(src->base.b.format))) &&
357bf215546Sopenharmony_ci                dst->base.b.nr_samples == src->base.b.nr_samples);
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_ci         ctx->cmdlist->CopyTextureRegion(&dst_loc, dstx, dsty, dstz,
360bf215546Sopenharmony_ci                                         &src_loc, &src_box);
361bf215546Sopenharmony_ci      }
362bf215546Sopenharmony_ci   }
363bf215546Sopenharmony_ci}
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_cistatic void
366bf215546Sopenharmony_cicopy_resource_y_flipped_no_barriers(struct d3d12_context *ctx,
367bf215546Sopenharmony_ci                                    struct d3d12_resource *dst,
368bf215546Sopenharmony_ci                                    unsigned dst_level,
369bf215546Sopenharmony_ci                                    const struct pipe_box *pdst_box,
370bf215546Sopenharmony_ci                                    struct d3d12_resource *src,
371bf215546Sopenharmony_ci                                    unsigned src_level,
372bf215546Sopenharmony_ci                                    const struct pipe_box *psrc_box,
373bf215546Sopenharmony_ci                                    unsigned mask)
374bf215546Sopenharmony_ci{
375bf215546Sopenharmony_ci   if (D3D12_DEBUG_BLIT & d3d12_debug) {
376bf215546Sopenharmony_ci      debug_printf("D3D12 BLIT as COPY: from %s@%d %dx%dx%d + %dx%dx%d\n",
377bf215546Sopenharmony_ci                   util_format_name(src->base.b.format), src_level,
378bf215546Sopenharmony_ci                   psrc_box->x, psrc_box->y, psrc_box->z,
379bf215546Sopenharmony_ci                   psrc_box->width, psrc_box->height, psrc_box->depth);
380bf215546Sopenharmony_ci      debug_printf("      to   %s@%d %dx%dx%d\n",
381bf215546Sopenharmony_ci                   util_format_name(dst->base.b.format), dst_level,
382bf215546Sopenharmony_ci                   pdst_box->x, pdst_box->y, pdst_box->z);
383bf215546Sopenharmony_ci   }
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci   struct pipe_box src_box = *psrc_box;
386bf215546Sopenharmony_ci   int src_inc = psrc_box->height > 0 ? 1 : -1;
387bf215546Sopenharmony_ci   int dst_inc = pdst_box->height > 0 ? 1 : -1;
388bf215546Sopenharmony_ci   src_box.height = 1;
389bf215546Sopenharmony_ci   int rows_to_copy = abs(psrc_box->height);
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci   if (psrc_box->height < 0)
392bf215546Sopenharmony_ci      --src_box.y;
393bf215546Sopenharmony_ci
394bf215546Sopenharmony_ci   for (int y = 0, dest_y = pdst_box->y; y < rows_to_copy;
395bf215546Sopenharmony_ci        ++y, src_box.y += src_inc, dest_y += dst_inc) {
396bf215546Sopenharmony_ci      copy_subregion_no_barriers(ctx, dst, dst_level,
397bf215546Sopenharmony_ci                                 pdst_box->x, dest_y, pdst_box->z,
398bf215546Sopenharmony_ci                                 src, src_level, &src_box, mask);
399bf215546Sopenharmony_ci   }
400bf215546Sopenharmony_ci}
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_civoid
403bf215546Sopenharmony_cid3d12_direct_copy(struct d3d12_context *ctx,
404bf215546Sopenharmony_ci                  struct d3d12_resource *dst,
405bf215546Sopenharmony_ci                  unsigned dst_level,
406bf215546Sopenharmony_ci                  const struct pipe_box *pdst_box,
407bf215546Sopenharmony_ci                  struct d3d12_resource *src,
408bf215546Sopenharmony_ci                  unsigned src_level,
409bf215546Sopenharmony_ci                  const struct pipe_box *psrc_box,
410bf215546Sopenharmony_ci                  unsigned mask)
411bf215546Sopenharmony_ci{
412bf215546Sopenharmony_ci   struct d3d12_batch *batch = d3d12_current_batch(ctx);
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_ci   unsigned src_subres = get_subresource_id(src->base.b.target, src_level, src->base.b.last_level + 1,
415bf215546Sopenharmony_ci                                            psrc_box->z, nullptr, src->base.b.array_size, src->plane_slice);
416bf215546Sopenharmony_ci   unsigned dst_subres = get_subresource_id(dst->base.b.target, dst_level, dst->base.b.last_level + 1,
417bf215546Sopenharmony_ci                                            pdst_box->z, nullptr, dst->base.b.array_size, dst->plane_slice);
418bf215546Sopenharmony_ci
419bf215546Sopenharmony_ci   if (D3D12_DEBUG_BLIT & d3d12_debug)
420bf215546Sopenharmony_ci      debug_printf("BLIT: Direct copy from subres %d to subres  %d\n",
421bf215546Sopenharmony_ci                   src_subres, dst_subres);
422bf215546Sopenharmony_ci
423bf215546Sopenharmony_ci   d3d12_transition_subresources_state(ctx, src, src_subres, 1, 0, 1,
424bf215546Sopenharmony_ci                                       d3d12_get_format_start_plane(src->base.b.format),
425bf215546Sopenharmony_ci                                       d3d12_get_format_num_planes(src->base.b.format),
426bf215546Sopenharmony_ci                                       D3D12_RESOURCE_STATE_COPY_SOURCE,
427bf215546Sopenharmony_ci                                       D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci   d3d12_transition_subresources_state(ctx, dst, dst_subres, 1, 0, 1,
430bf215546Sopenharmony_ci                                       d3d12_get_format_start_plane(dst->base.b.format),
431bf215546Sopenharmony_ci                                       d3d12_get_format_num_planes(dst->base.b.format),
432bf215546Sopenharmony_ci                                       D3D12_RESOURCE_STATE_COPY_DEST,
433bf215546Sopenharmony_ci                                       D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
434bf215546Sopenharmony_ci
435bf215546Sopenharmony_ci   d3d12_apply_resource_states(ctx, false);
436bf215546Sopenharmony_ci
437bf215546Sopenharmony_ci   d3d12_batch_reference_resource(batch, src, false);
438bf215546Sopenharmony_ci   d3d12_batch_reference_resource(batch, dst, true);
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci   if (src->base.b.target == PIPE_BUFFER) {
441bf215546Sopenharmony_ci      copy_buffer_region_no_barriers(ctx, dst, pdst_box->x,
442bf215546Sopenharmony_ci                                     src, psrc_box->x, psrc_box->width);
443bf215546Sopenharmony_ci   } else if (psrc_box->height == pdst_box->height) {
444bf215546Sopenharmony_ci      /* No flipping, we can forward this directly to resource_copy_region */
445bf215546Sopenharmony_ci      copy_subregion_no_barriers(ctx, dst, dst_level,
446bf215546Sopenharmony_ci                                 pdst_box->x, pdst_box->y, pdst_box->z,
447bf215546Sopenharmony_ci                                 src, src_level, psrc_box, mask);
448bf215546Sopenharmony_ci   } else {
449bf215546Sopenharmony_ci      assert(psrc_box->height == -pdst_box->height);
450bf215546Sopenharmony_ci      copy_resource_y_flipped_no_barriers(ctx, dst, dst_level, pdst_box,
451bf215546Sopenharmony_ci                                          src, src_level, psrc_box, mask);
452bf215546Sopenharmony_ci   }
453bf215546Sopenharmony_ci}
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_cistatic bool
456bf215546Sopenharmony_ciis_same_resource(const struct pipe_blit_info *info)
457bf215546Sopenharmony_ci{
458bf215546Sopenharmony_ci   return d3d12_resource_resource(d3d12_resource(info->src.resource)) ==
459bf215546Sopenharmony_ci             d3d12_resource_resource(d3d12_resource(info->dst.resource)) &&
460bf215546Sopenharmony_ci          info->src.level == info->dst.level;
461bf215546Sopenharmony_ci}
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_cistatic struct pipe_resource *
464bf215546Sopenharmony_cicreate_staging_resource(struct d3d12_context *ctx,
465bf215546Sopenharmony_ci                        struct d3d12_resource *src,
466bf215546Sopenharmony_ci                        unsigned src_level,
467bf215546Sopenharmony_ci                        const struct pipe_box *src_box,
468bf215546Sopenharmony_ci                        struct pipe_box *dst_box,
469bf215546Sopenharmony_ci                        unsigned mask)
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_ci{
472bf215546Sopenharmony_ci   struct pipe_resource templ = {};
473bf215546Sopenharmony_ci   struct pipe_resource *staging_res;
474bf215546Sopenharmony_ci   struct pipe_box copy_src;
475bf215546Sopenharmony_ci
476bf215546Sopenharmony_ci   u_box_3d(MIN2(src_box->x, src_box->x + src_box->width),
477bf215546Sopenharmony_ci            MIN2(src_box->y, src_box->y + src_box->height),
478bf215546Sopenharmony_ci            MIN2(src_box->z, src_box->z + src_box->depth),
479bf215546Sopenharmony_ci            abs(src_box->width), abs(src_box->height), abs(src_box->depth),
480bf215546Sopenharmony_ci            &copy_src);
481bf215546Sopenharmony_ci
482bf215546Sopenharmony_ci   templ.format = src->base.b.format;
483bf215546Sopenharmony_ci   templ.width0 = copy_src.width;
484bf215546Sopenharmony_ci   templ.height0 = copy_src.height;
485bf215546Sopenharmony_ci   templ.depth0 = copy_src.depth;
486bf215546Sopenharmony_ci   templ.array_size = 1;
487bf215546Sopenharmony_ci   templ.nr_samples = src->base.b.nr_samples;
488bf215546Sopenharmony_ci   templ.nr_storage_samples = src->base.b.nr_storage_samples;
489bf215546Sopenharmony_ci   templ.usage = PIPE_USAGE_STAGING;
490bf215546Sopenharmony_ci   templ.bind = util_format_is_depth_or_stencil(templ.format) ? PIPE_BIND_DEPTH_STENCIL : PIPE_BIND_RENDER_TARGET;
491bf215546Sopenharmony_ci   templ.target = src->base.b.target;
492bf215546Sopenharmony_ci
493bf215546Sopenharmony_ci   staging_res = ctx->base.screen->resource_create(ctx->base.screen, &templ);
494bf215546Sopenharmony_ci
495bf215546Sopenharmony_ci   dst_box->x = 0;
496bf215546Sopenharmony_ci   dst_box->y = 0;
497bf215546Sopenharmony_ci   dst_box->z = 0;
498bf215546Sopenharmony_ci   dst_box->width = copy_src.width;
499bf215546Sopenharmony_ci   dst_box->height = copy_src.height;
500bf215546Sopenharmony_ci   dst_box->depth = copy_src.depth;
501bf215546Sopenharmony_ci
502bf215546Sopenharmony_ci   d3d12_direct_copy(ctx, d3d12_resource(staging_res), 0, dst_box,
503bf215546Sopenharmony_ci                     src, src_level, &copy_src, mask);
504bf215546Sopenharmony_ci
505bf215546Sopenharmony_ci   if (src_box->width < 0) {
506bf215546Sopenharmony_ci      dst_box->x = dst_box->width;
507bf215546Sopenharmony_ci      dst_box->width = src_box->width;
508bf215546Sopenharmony_ci   }
509bf215546Sopenharmony_ci
510bf215546Sopenharmony_ci   if (src_box->height < 0) {
511bf215546Sopenharmony_ci      dst_box->y = dst_box->height;
512bf215546Sopenharmony_ci      dst_box->height = src_box->height;
513bf215546Sopenharmony_ci   }
514bf215546Sopenharmony_ci
515bf215546Sopenharmony_ci   if (src_box->depth < 0) {
516bf215546Sopenharmony_ci      dst_box->z = dst_box->depth;
517bf215546Sopenharmony_ci      dst_box->depth = src_box->depth;
518bf215546Sopenharmony_ci   }
519bf215546Sopenharmony_ci   return staging_res;
520bf215546Sopenharmony_ci}
521bf215546Sopenharmony_ci
522bf215546Sopenharmony_cistatic void
523bf215546Sopenharmony_ciblit_same_resource(struct d3d12_context *ctx,
524bf215546Sopenharmony_ci                   const struct pipe_blit_info *info)
525bf215546Sopenharmony_ci{
526bf215546Sopenharmony_ci   struct pipe_blit_info dst_info = *info;
527bf215546Sopenharmony_ci
528bf215546Sopenharmony_ci   dst_info.src.level = 0;
529bf215546Sopenharmony_ci   dst_info.src.resource = create_staging_resource(ctx, d3d12_resource(info->src.resource),
530bf215546Sopenharmony_ci                                                   info->src.level,
531bf215546Sopenharmony_ci                                                   &info->src.box,
532bf215546Sopenharmony_ci                                                   &dst_info.src.box, PIPE_MASK_RGBAZS);
533bf215546Sopenharmony_ci   ctx->base.blit(&ctx->base, &dst_info);
534bf215546Sopenharmony_ci   pipe_resource_reference(&dst_info.src.resource, NULL);
535bf215546Sopenharmony_ci}
536bf215546Sopenharmony_ci
537bf215546Sopenharmony_cistatic void
538bf215546Sopenharmony_ciutil_blit_save_state(struct d3d12_context *ctx)
539bf215546Sopenharmony_ci{
540bf215546Sopenharmony_ci   util_blitter_save_blend(ctx->blitter, ctx->gfx_pipeline_state.blend);
541bf215546Sopenharmony_ci   util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->gfx_pipeline_state.zsa);
542bf215546Sopenharmony_ci   util_blitter_save_vertex_elements(ctx->blitter, ctx->gfx_pipeline_state.ves);
543bf215546Sopenharmony_ci   util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
544bf215546Sopenharmony_ci   util_blitter_save_rasterizer(ctx->blitter, ctx->gfx_pipeline_state.rast);
545bf215546Sopenharmony_ci   util_blitter_save_fragment_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_FRAGMENT]);
546bf215546Sopenharmony_ci   util_blitter_save_vertex_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_VERTEX]);
547bf215546Sopenharmony_ci   util_blitter_save_geometry_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_GEOMETRY]);
548bf215546Sopenharmony_ci   util_blitter_save_tessctrl_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_TESS_CTRL]);
549bf215546Sopenharmony_ci   util_blitter_save_tesseval_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]);
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_ci   util_blitter_save_framebuffer(ctx->blitter, &ctx->fb);
552bf215546Sopenharmony_ci   util_blitter_save_viewport(ctx->blitter, ctx->viewport_states);
553bf215546Sopenharmony_ci   util_blitter_save_scissor(ctx->blitter, ctx->scissor_states);
554bf215546Sopenharmony_ci   util_blitter_save_fragment_sampler_states(ctx->blitter,
555bf215546Sopenharmony_ci                                             ctx->num_samplers[PIPE_SHADER_FRAGMENT],
556bf215546Sopenharmony_ci                                             (void **)ctx->samplers[PIPE_SHADER_FRAGMENT]);
557bf215546Sopenharmony_ci   util_blitter_save_fragment_sampler_views(ctx->blitter,
558bf215546Sopenharmony_ci                                            ctx->num_sampler_views[PIPE_SHADER_FRAGMENT],
559bf215546Sopenharmony_ci                                            ctx->sampler_views[PIPE_SHADER_FRAGMENT]);
560bf215546Sopenharmony_ci   util_blitter_save_fragment_constant_buffer_slot(ctx->blitter, ctx->cbufs[PIPE_SHADER_FRAGMENT]);
561bf215546Sopenharmony_ci   util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vbs);
562bf215546Sopenharmony_ci   util_blitter_save_sample_mask(ctx->blitter, ctx->gfx_pipeline_state.sample_mask, 0);
563bf215546Sopenharmony_ci   util_blitter_save_so_targets(ctx->blitter, ctx->gfx_pipeline_state.num_so_targets, ctx->so_targets);
564bf215546Sopenharmony_ci}
565bf215546Sopenharmony_ci
566bf215546Sopenharmony_cistatic void
567bf215546Sopenharmony_ciutil_blit(struct d3d12_context *ctx,
568bf215546Sopenharmony_ci          const struct pipe_blit_info *info)
569bf215546Sopenharmony_ci{
570bf215546Sopenharmony_ci   util_blit_save_state(ctx);
571bf215546Sopenharmony_ci
572bf215546Sopenharmony_ci   util_blitter_blit(ctx->blitter, info);
573bf215546Sopenharmony_ci}
574bf215546Sopenharmony_ci
575bf215546Sopenharmony_cistatic bool
576bf215546Sopenharmony_ciresolve_stencil_supported(struct d3d12_context *ctx,
577bf215546Sopenharmony_ci                          const struct pipe_blit_info *info)
578bf215546Sopenharmony_ci{
579bf215546Sopenharmony_ci   assert(is_resolve(info));
580bf215546Sopenharmony_ci
581bf215546Sopenharmony_ci   if (!util_format_is_depth_or_stencil(info->src.format) ||
582bf215546Sopenharmony_ci       !(info->mask & PIPE_MASK_S))
583bf215546Sopenharmony_ci      return false;
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ci   if (info->mask & PIPE_MASK_Z) {
586bf215546Sopenharmony_ci      struct pipe_blit_info new_info = *info;
587bf215546Sopenharmony_ci      new_info.mask = PIPE_MASK_Z;
588bf215546Sopenharmony_ci      if (!resolve_supported(&new_info) &&
589bf215546Sopenharmony_ci          !util_blitter_is_blit_supported(ctx->blitter, &new_info))
590bf215546Sopenharmony_ci         return false;
591bf215546Sopenharmony_ci   }
592bf215546Sopenharmony_ci
593bf215546Sopenharmony_ci   struct pipe_blit_info new_info = *info;
594bf215546Sopenharmony_ci   new_info.dst.format = PIPE_FORMAT_R8_UINT;
595bf215546Sopenharmony_ci   return util_blitter_is_blit_supported(ctx->blitter, &new_info);
596bf215546Sopenharmony_ci}
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_cistatic struct pipe_resource *
599bf215546Sopenharmony_cicreate_tmp_resource(struct pipe_screen *screen,
600bf215546Sopenharmony_ci                    const struct pipe_blit_info *info)
601bf215546Sopenharmony_ci{
602bf215546Sopenharmony_ci   struct pipe_resource tpl = {};
603bf215546Sopenharmony_ci   tpl.width0 = info->dst.box.width;
604bf215546Sopenharmony_ci   tpl.height0 = info->dst.box.height;
605bf215546Sopenharmony_ci   tpl.depth0 = info->dst.box.depth;
606bf215546Sopenharmony_ci   tpl.array_size = 1;
607bf215546Sopenharmony_ci   tpl.format = PIPE_FORMAT_R8_UINT;
608bf215546Sopenharmony_ci   tpl.target = info->dst.resource->target;
609bf215546Sopenharmony_ci   tpl.nr_samples = info->dst.resource->nr_samples;
610bf215546Sopenharmony_ci   tpl.nr_storage_samples = info->dst.resource->nr_storage_samples;
611bf215546Sopenharmony_ci   tpl.usage = PIPE_USAGE_STREAM;
612bf215546Sopenharmony_ci   tpl.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
613bf215546Sopenharmony_ci   return screen->resource_create(screen, &tpl);
614bf215546Sopenharmony_ci}
615bf215546Sopenharmony_ci
616bf215546Sopenharmony_cistatic void *
617bf215546Sopenharmony_ciget_stencil_resolve_vs(struct d3d12_context *ctx)
618bf215546Sopenharmony_ci{
619bf215546Sopenharmony_ci   if (ctx->stencil_resolve_vs)
620bf215546Sopenharmony_ci      return ctx->stencil_resolve_vs;
621bf215546Sopenharmony_ci
622bf215546Sopenharmony_ci   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_VERTEX,
623bf215546Sopenharmony_ci                                                  &d3d12_screen(ctx->base.screen)->nir_options,
624bf215546Sopenharmony_ci                                                  "linear_blit_vs");
625bf215546Sopenharmony_ci
626bf215546Sopenharmony_ci   const struct glsl_type *vec4 = glsl_vec4_type();
627bf215546Sopenharmony_ci   nir_variable *pos_in = nir_variable_create(b.shader, nir_var_shader_in,
628bf215546Sopenharmony_ci                                              vec4, "pos");
629bf215546Sopenharmony_ci
630bf215546Sopenharmony_ci   nir_variable *pos_out = nir_variable_create(b.shader, nir_var_shader_out,
631bf215546Sopenharmony_ci                                               vec4, "gl_Position");
632bf215546Sopenharmony_ci   pos_out->data.location = VARYING_SLOT_POS;
633bf215546Sopenharmony_ci
634bf215546Sopenharmony_ci   nir_store_var(&b, pos_out, nir_load_var(&b, pos_in), 0xf);
635bf215546Sopenharmony_ci
636bf215546Sopenharmony_ci   struct pipe_shader_state state = {};
637bf215546Sopenharmony_ci   state.type = PIPE_SHADER_IR_NIR;
638bf215546Sopenharmony_ci   state.ir.nir = b.shader;
639bf215546Sopenharmony_ci   ctx->stencil_resolve_vs = ctx->base.create_vs_state(&ctx->base, &state);
640bf215546Sopenharmony_ci
641bf215546Sopenharmony_ci   return ctx->stencil_resolve_vs;
642bf215546Sopenharmony_ci}
643bf215546Sopenharmony_ci
644bf215546Sopenharmony_cistatic void *
645bf215546Sopenharmony_ciget_stencil_resolve_fs(struct d3d12_context *ctx, bool no_flip)
646bf215546Sopenharmony_ci{
647bf215546Sopenharmony_ci   if (!no_flip && ctx->stencil_resolve_fs)
648bf215546Sopenharmony_ci      return ctx->stencil_resolve_fs;
649bf215546Sopenharmony_ci
650bf215546Sopenharmony_ci   if (no_flip && ctx->stencil_resolve_fs_no_flip)
651bf215546Sopenharmony_ci      return ctx->stencil_resolve_fs_no_flip;
652bf215546Sopenharmony_ci
653bf215546Sopenharmony_ci   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT,
654bf215546Sopenharmony_ci                                                  &d3d12_screen(ctx->base.screen)->nir_options,
655bf215546Sopenharmony_ci                                                  no_flip ? "stencil_resolve_fs_no_flip" : "stencil_resolve_fs");
656bf215546Sopenharmony_ci
657bf215546Sopenharmony_ci   nir_variable *stencil_out = nir_variable_create(b.shader,
658bf215546Sopenharmony_ci                                                   nir_var_shader_out,
659bf215546Sopenharmony_ci                                                   glsl_uint_type(),
660bf215546Sopenharmony_ci                                                   "stencil_out");
661bf215546Sopenharmony_ci   stencil_out->data.location = FRAG_RESULT_COLOR;
662bf215546Sopenharmony_ci
663bf215546Sopenharmony_ci   const struct glsl_type *sampler_type =
664bf215546Sopenharmony_ci      glsl_sampler_type(GLSL_SAMPLER_DIM_MS, false, false, GLSL_TYPE_UINT);
665bf215546Sopenharmony_ci   nir_variable *sampler = nir_variable_create(b.shader, nir_var_uniform,
666bf215546Sopenharmony_ci                                               sampler_type, "stencil_tex");
667bf215546Sopenharmony_ci   sampler->data.binding = 0;
668bf215546Sopenharmony_ci   sampler->data.explicit_binding = true;
669bf215546Sopenharmony_ci
670bf215546Sopenharmony_ci   nir_ssa_def *tex_deref = &nir_build_deref_var(&b, sampler)->dest.ssa;
671bf215546Sopenharmony_ci
672bf215546Sopenharmony_ci   nir_variable *pos_in = nir_variable_create(b.shader, nir_var_shader_in,
673bf215546Sopenharmony_ci                                              glsl_vec4_type(), "pos");
674bf215546Sopenharmony_ci   pos_in->data.location = VARYING_SLOT_POS; // VARYING_SLOT_VAR0?
675bf215546Sopenharmony_ci   nir_ssa_def *pos = nir_load_var(&b, pos_in);
676bf215546Sopenharmony_ci
677bf215546Sopenharmony_ci   nir_ssa_def *pos_src;
678bf215546Sopenharmony_ci
679bf215546Sopenharmony_ci   if (no_flip)
680bf215546Sopenharmony_ci      pos_src = pos;
681bf215546Sopenharmony_ci   else {
682bf215546Sopenharmony_ci      nir_tex_instr *txs = nir_tex_instr_create(b.shader, 1);
683bf215546Sopenharmony_ci      txs->op = nir_texop_txs;
684bf215546Sopenharmony_ci      txs->sampler_dim = GLSL_SAMPLER_DIM_MS;
685bf215546Sopenharmony_ci      txs->src[0].src_type = nir_tex_src_texture_deref;
686bf215546Sopenharmony_ci      txs->src[0].src = nir_src_for_ssa(tex_deref);
687bf215546Sopenharmony_ci      txs->is_array = false;
688bf215546Sopenharmony_ci      txs->dest_type = nir_type_int;
689bf215546Sopenharmony_ci
690bf215546Sopenharmony_ci      nir_ssa_dest_init(&txs->instr, &txs->dest, 2, 32, "tex");
691bf215546Sopenharmony_ci      nir_builder_instr_insert(&b, &txs->instr);
692bf215546Sopenharmony_ci
693bf215546Sopenharmony_ci      pos_src = nir_vec4(&b,
694bf215546Sopenharmony_ci                         nir_channel(&b, pos, 0),
695bf215546Sopenharmony_ci                         /*Height - pos_dest.y - 1*/
696bf215546Sopenharmony_ci                         nir_fsub(&b,
697bf215546Sopenharmony_ci                                  nir_fsub(&b,
698bf215546Sopenharmony_ci                                           nir_channel(&b, nir_i2f32(&b, &txs->dest.ssa), 1),
699bf215546Sopenharmony_ci                                           nir_channel(&b, pos, 1)),
700bf215546Sopenharmony_ci                                  nir_imm_float(&b, 1.0)),
701bf215546Sopenharmony_ci                         nir_channel(&b, pos, 2),
702bf215546Sopenharmony_ci                         nir_channel(&b, pos, 3));
703bf215546Sopenharmony_ci   }
704bf215546Sopenharmony_ci
705bf215546Sopenharmony_ci   nir_tex_instr *tex = nir_tex_instr_create(b.shader, 3);
706bf215546Sopenharmony_ci   tex->sampler_dim = GLSL_SAMPLER_DIM_MS;
707bf215546Sopenharmony_ci   tex->op = nir_texop_txf_ms;
708bf215546Sopenharmony_ci   tex->src[0].src_type = nir_tex_src_coord;
709bf215546Sopenharmony_ci   tex->src[0].src = nir_src_for_ssa(nir_channels(&b, nir_f2i32(&b, pos_src), 0x3));
710bf215546Sopenharmony_ci   tex->src[1].src_type = nir_tex_src_ms_index;
711bf215546Sopenharmony_ci   tex->src[1].src = nir_src_for_ssa(nir_imm_int(&b, 0)); /* just use first sample */
712bf215546Sopenharmony_ci   tex->src[2].src_type = nir_tex_src_texture_deref;
713bf215546Sopenharmony_ci   tex->src[2].src = nir_src_for_ssa(tex_deref);
714bf215546Sopenharmony_ci   tex->dest_type = nir_type_uint32;
715bf215546Sopenharmony_ci   tex->is_array = false;
716bf215546Sopenharmony_ci   tex->coord_components = 2;
717bf215546Sopenharmony_ci
718bf215546Sopenharmony_ci   nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, "tex");
719bf215546Sopenharmony_ci   nir_builder_instr_insert(&b, &tex->instr);
720bf215546Sopenharmony_ci
721bf215546Sopenharmony_ci   nir_store_var(&b, stencil_out, nir_channel(&b, &tex->dest.ssa, 1), 0x1);
722bf215546Sopenharmony_ci
723bf215546Sopenharmony_ci   struct pipe_shader_state state = {};
724bf215546Sopenharmony_ci   state.type = PIPE_SHADER_IR_NIR;
725bf215546Sopenharmony_ci   state.ir.nir = b.shader;
726bf215546Sopenharmony_ci   void *result;
727bf215546Sopenharmony_ci   if (no_flip) {
728bf215546Sopenharmony_ci      result = ctx->base.create_fs_state(&ctx->base, &state);
729bf215546Sopenharmony_ci      ctx->stencil_resolve_fs_no_flip = result;
730bf215546Sopenharmony_ci   } else {
731bf215546Sopenharmony_ci      result = ctx->base.create_fs_state(&ctx->base, &state);
732bf215546Sopenharmony_ci      ctx->stencil_resolve_fs = result;
733bf215546Sopenharmony_ci   }
734bf215546Sopenharmony_ci
735bf215546Sopenharmony_ci   return result;
736bf215546Sopenharmony_ci}
737bf215546Sopenharmony_ci
738bf215546Sopenharmony_cistatic void *
739bf215546Sopenharmony_ciget_sampler_state(struct d3d12_context *ctx)
740bf215546Sopenharmony_ci{
741bf215546Sopenharmony_ci   if (ctx->sampler_state)
742bf215546Sopenharmony_ci      return ctx->sampler_state;
743bf215546Sopenharmony_ci
744bf215546Sopenharmony_ci   struct pipe_sampler_state state;
745bf215546Sopenharmony_ci   memset(&state, 0, sizeof(state));
746bf215546Sopenharmony_ci   state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
747bf215546Sopenharmony_ci   state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
748bf215546Sopenharmony_ci   state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
749bf215546Sopenharmony_ci   state.normalized_coords = 1;
750bf215546Sopenharmony_ci
751bf215546Sopenharmony_ci   return ctx->sampler_state = ctx->base.create_sampler_state(&ctx->base, &state);
752bf215546Sopenharmony_ci}
753bf215546Sopenharmony_ci
754bf215546Sopenharmony_cistatic struct pipe_resource *
755bf215546Sopenharmony_ciresolve_stencil_to_temp(struct d3d12_context *ctx,
756bf215546Sopenharmony_ci                        const struct pipe_blit_info *info)
757bf215546Sopenharmony_ci{
758bf215546Sopenharmony_ci   struct pipe_context *pctx = &ctx->base;
759bf215546Sopenharmony_ci   struct pipe_resource *tmp = create_tmp_resource(pctx->screen, info);
760bf215546Sopenharmony_ci   if (!tmp) {
761bf215546Sopenharmony_ci      debug_printf("D3D12: failed to create stencil-resolve temp-resource\n");
762bf215546Sopenharmony_ci      return NULL;
763bf215546Sopenharmony_ci   }
764bf215546Sopenharmony_ci   assert(tmp->nr_samples < 2);
765bf215546Sopenharmony_ci
766bf215546Sopenharmony_ci   /* resolve stencil into tmp */
767bf215546Sopenharmony_ci   struct pipe_surface dst_tmpl;
768bf215546Sopenharmony_ci   util_blitter_default_dst_texture(&dst_tmpl, tmp, 0, 0);
769bf215546Sopenharmony_ci   dst_tmpl.format = tmp->format;
770bf215546Sopenharmony_ci   struct pipe_surface *dst_surf = pctx->create_surface(pctx, tmp, &dst_tmpl);
771bf215546Sopenharmony_ci   if (!dst_surf) {
772bf215546Sopenharmony_ci      debug_printf("D3D12: failed to create stencil-resolve dst-surface\n");
773bf215546Sopenharmony_ci      return NULL;
774bf215546Sopenharmony_ci   }
775bf215546Sopenharmony_ci
776bf215546Sopenharmony_ci   struct pipe_sampler_view src_templ, *src_view;
777bf215546Sopenharmony_ci   util_blitter_default_src_texture(ctx->blitter, &src_templ,
778bf215546Sopenharmony_ci                                    info->src.resource, info->src.level);
779bf215546Sopenharmony_ci   src_templ.format = util_format_stencil_only(info->src.format);
780bf215546Sopenharmony_ci   src_view = pctx->create_sampler_view(pctx, info->src.resource, &src_templ);
781bf215546Sopenharmony_ci
782bf215546Sopenharmony_ci   void *sampler_state = get_sampler_state(ctx);
783bf215546Sopenharmony_ci
784bf215546Sopenharmony_ci   util_blit_save_state(ctx);
785bf215546Sopenharmony_ci   pctx->set_sampler_views(pctx, PIPE_SHADER_FRAGMENT, 0, 1, 0, false, &src_view);
786bf215546Sopenharmony_ci   pctx->bind_sampler_states(pctx, PIPE_SHADER_FRAGMENT, 0, 1, &sampler_state);
787bf215546Sopenharmony_ci   util_blitter_custom_shader(ctx->blitter, dst_surf,
788bf215546Sopenharmony_ci                              get_stencil_resolve_vs(ctx),
789bf215546Sopenharmony_ci                              get_stencil_resolve_fs(ctx, info->src.box.height == info->dst.box.height));
790bf215546Sopenharmony_ci   util_blitter_restore_textures(ctx->blitter);
791bf215546Sopenharmony_ci   pipe_surface_reference(&dst_surf, NULL);
792bf215546Sopenharmony_ci   pipe_sampler_view_reference(&src_view, NULL);
793bf215546Sopenharmony_ci   return tmp;
794bf215546Sopenharmony_ci}
795bf215546Sopenharmony_ci
796bf215546Sopenharmony_cistatic void
797bf215546Sopenharmony_ciblit_resolve_stencil(struct d3d12_context *ctx,
798bf215546Sopenharmony_ci                     const struct pipe_blit_info *info)
799bf215546Sopenharmony_ci{
800bf215546Sopenharmony_ci   assert(info->mask & PIPE_MASK_S);
801bf215546Sopenharmony_ci
802bf215546Sopenharmony_ci   if (D3D12_DEBUG_BLIT & d3d12_debug)
803bf215546Sopenharmony_ci      debug_printf("D3D12 BLIT: blit_resolve_stencil\n");
804bf215546Sopenharmony_ci
805bf215546Sopenharmony_ci   if (info->mask & PIPE_MASK_Z) {
806bf215546Sopenharmony_ci      /* resolve depth into dst */
807bf215546Sopenharmony_ci      struct pipe_blit_info new_info = *info;
808bf215546Sopenharmony_ci      new_info.mask = PIPE_MASK_Z;
809bf215546Sopenharmony_ci
810bf215546Sopenharmony_ci      if (resolve_supported(&new_info))
811bf215546Sopenharmony_ci         blit_resolve(ctx, &new_info);
812bf215546Sopenharmony_ci      else
813bf215546Sopenharmony_ci         util_blit(ctx, &new_info);
814bf215546Sopenharmony_ci   }
815bf215546Sopenharmony_ci
816bf215546Sopenharmony_ci   struct pipe_resource *tmp = resolve_stencil_to_temp(ctx, info);
817bf215546Sopenharmony_ci
818bf215546Sopenharmony_ci
819bf215546Sopenharmony_ci   /* copy resolved stencil into dst */
820bf215546Sopenharmony_ci   struct d3d12_resource *dst = d3d12_resource(info->dst.resource);
821bf215546Sopenharmony_ci   d3d12_transition_subresources_state(ctx, d3d12_resource(tmp),
822bf215546Sopenharmony_ci                                       0, 1, 0, 1, 0, 1,
823bf215546Sopenharmony_ci                                       D3D12_RESOURCE_STATE_COPY_SOURCE,
824bf215546Sopenharmony_ci                                       D3D12_TRANSITION_FLAG_NONE);
825bf215546Sopenharmony_ci   d3d12_transition_subresources_state(ctx, dst,
826bf215546Sopenharmony_ci                                       0, 1, 0, 1, 1, 1,
827bf215546Sopenharmony_ci                                       D3D12_RESOURCE_STATE_COPY_DEST,
828bf215546Sopenharmony_ci                                       D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
829bf215546Sopenharmony_ci   d3d12_apply_resource_states(ctx, false);
830bf215546Sopenharmony_ci
831bf215546Sopenharmony_ci   struct d3d12_batch *batch = d3d12_current_batch(ctx);
832bf215546Sopenharmony_ci   d3d12_batch_reference_resource(batch, d3d12_resource(tmp), false);
833bf215546Sopenharmony_ci   d3d12_batch_reference_resource(batch, dst, true);
834bf215546Sopenharmony_ci
835bf215546Sopenharmony_ci   D3D12_BOX src_box;
836bf215546Sopenharmony_ci   src_box.left = src_box.top = src_box.front = 0;
837bf215546Sopenharmony_ci   src_box.right = tmp->width0;
838bf215546Sopenharmony_ci   src_box.bottom = tmp->height0;
839bf215546Sopenharmony_ci   src_box.back = tmp->depth0;
840bf215546Sopenharmony_ci
841bf215546Sopenharmony_ci   D3D12_TEXTURE_COPY_LOCATION src_loc;
842bf215546Sopenharmony_ci   src_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
843bf215546Sopenharmony_ci   src_loc.SubresourceIndex = 0;
844bf215546Sopenharmony_ci   src_loc.pResource = d3d12_resource_resource(d3d12_resource(tmp));
845bf215546Sopenharmony_ci
846bf215546Sopenharmony_ci   D3D12_TEXTURE_COPY_LOCATION dst_loc;
847bf215546Sopenharmony_ci   dst_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
848bf215546Sopenharmony_ci   dst_loc.SubresourceIndex = 1;
849bf215546Sopenharmony_ci   dst_loc.pResource = d3d12_resource_resource(dst);
850bf215546Sopenharmony_ci
851bf215546Sopenharmony_ci   ctx->cmdlist->CopyTextureRegion(&dst_loc, info->dst.box.x,
852bf215546Sopenharmony_ci                                   info->dst.box.y, info->dst.box.z,
853bf215546Sopenharmony_ci                                   &src_loc, &src_box);
854bf215546Sopenharmony_ci
855bf215546Sopenharmony_ci   pipe_resource_reference(&tmp, NULL);
856bf215546Sopenharmony_ci}
857bf215546Sopenharmony_ci
858bf215546Sopenharmony_cistatic bool
859bf215546Sopenharmony_cireplicate_stencil_supported(struct d3d12_context *ctx,
860bf215546Sopenharmony_ci                            const struct pipe_blit_info *info)
861bf215546Sopenharmony_ci{
862bf215546Sopenharmony_ci   if (!util_format_is_depth_or_stencil(info->src.format) ||
863bf215546Sopenharmony_ci       !(info->mask & PIPE_MASK_S))
864bf215546Sopenharmony_ci      return false;
865bf215546Sopenharmony_ci
866bf215546Sopenharmony_ci   if (info->mask & PIPE_MASK_Z) {
867bf215546Sopenharmony_ci      struct pipe_blit_info new_info = *info;
868bf215546Sopenharmony_ci      new_info.mask = PIPE_MASK_Z;
869bf215546Sopenharmony_ci      if (!util_blitter_is_blit_supported(ctx->blitter, &new_info))
870bf215546Sopenharmony_ci         return false;
871bf215546Sopenharmony_ci   }
872bf215546Sopenharmony_ci
873bf215546Sopenharmony_ci   return true;
874bf215546Sopenharmony_ci}
875bf215546Sopenharmony_ci
876bf215546Sopenharmony_cistatic void
877bf215546Sopenharmony_ciblit_replicate_stencil(struct d3d12_context *ctx,
878bf215546Sopenharmony_ci                       const struct pipe_blit_info *info)
879bf215546Sopenharmony_ci{
880bf215546Sopenharmony_ci   assert(info->mask & PIPE_MASK_S);
881bf215546Sopenharmony_ci
882bf215546Sopenharmony_ci   if (D3D12_DEBUG_BLIT & d3d12_debug)
883bf215546Sopenharmony_ci      debug_printf("D3D12 BLIT: blit_replicate_stencil\n");
884bf215546Sopenharmony_ci
885bf215546Sopenharmony_ci   if (info->mask & PIPE_MASK_Z) {
886bf215546Sopenharmony_ci      /* resolve depth into dst */
887bf215546Sopenharmony_ci      struct pipe_blit_info new_info = *info;
888bf215546Sopenharmony_ci      new_info.mask = PIPE_MASK_Z;
889bf215546Sopenharmony_ci      util_blit(ctx, &new_info);
890bf215546Sopenharmony_ci   }
891bf215546Sopenharmony_ci
892bf215546Sopenharmony_ci   util_blit_save_state(ctx);
893bf215546Sopenharmony_ci   util_blitter_stencil_fallback(ctx->blitter, info->dst.resource,
894bf215546Sopenharmony_ci                                 info->dst.level,
895bf215546Sopenharmony_ci                                 &info->dst.box,
896bf215546Sopenharmony_ci                                 info->src.resource,
897bf215546Sopenharmony_ci                                 info->src.level,
898bf215546Sopenharmony_ci                                 &info->src.box,
899bf215546Sopenharmony_ci                                 info->scissor_enable ? &info->scissor : NULL);
900bf215546Sopenharmony_ci}
901bf215546Sopenharmony_ci
902bf215546Sopenharmony_civoid
903bf215546Sopenharmony_cid3d12_blit(struct pipe_context *pctx,
904bf215546Sopenharmony_ci           const struct pipe_blit_info *info)
905bf215546Sopenharmony_ci{
906bf215546Sopenharmony_ci   struct d3d12_context *ctx = d3d12_context(pctx);
907bf215546Sopenharmony_ci
908bf215546Sopenharmony_ci   if (!info->render_condition_enable && ctx->current_predication) {
909bf215546Sopenharmony_ci      if (D3D12_DEBUG_BLIT & d3d12_debug)
910bf215546Sopenharmony_ci         debug_printf("D3D12 BLIT: Disable predication\n");
911bf215546Sopenharmony_ci      ctx->cmdlist->SetPredication(nullptr, 0, D3D12_PREDICATION_OP_EQUAL_ZERO);
912bf215546Sopenharmony_ci   }
913bf215546Sopenharmony_ci
914bf215546Sopenharmony_ci   if (D3D12_DEBUG_BLIT & d3d12_debug) {
915bf215546Sopenharmony_ci      debug_printf("D3D12 BLIT: from %s@%d msaa:%d %dx%dx%d + %dx%dx%d\n",
916bf215546Sopenharmony_ci                   util_format_name(info->src.format), info->src.level,
917bf215546Sopenharmony_ci                   info->src.resource->nr_samples,
918bf215546Sopenharmony_ci                   info->src.box.x, info->src.box.y, info->src.box.z,
919bf215546Sopenharmony_ci                   info->src.box.width, info->src.box.height, info->src.box.depth);
920bf215546Sopenharmony_ci      debug_printf("            to   %s@%d msaa:%d %dx%dx%d + %dx%dx%d ",
921bf215546Sopenharmony_ci                   util_format_name(info->dst.format), info->dst.level,
922bf215546Sopenharmony_ci                   info->dst.resource->nr_samples,
923bf215546Sopenharmony_ci                   info->dst.box.x, info->dst.box.y, info->dst.box.z,
924bf215546Sopenharmony_ci                   info->dst.box.width, info->dst.box.height, info->dst.box.depth);
925bf215546Sopenharmony_ci      debug_printf("| flags %s%s%s\n",
926bf215546Sopenharmony_ci                   info->render_condition_enable ? "cond " : "",
927bf215546Sopenharmony_ci                   info->scissor_enable ? "scissor " : "",
928bf215546Sopenharmony_ci                   info->alpha_blend ? "blend" : "");
929bf215546Sopenharmony_ci   }
930bf215546Sopenharmony_ci
931bf215546Sopenharmony_ci   if (is_same_resource(info))
932bf215546Sopenharmony_ci      blit_same_resource(ctx, info);
933bf215546Sopenharmony_ci   else if (is_resolve(info)) {
934bf215546Sopenharmony_ci      if (resolve_supported(info))
935bf215546Sopenharmony_ci         blit_resolve(ctx, info);
936bf215546Sopenharmony_ci      else if (util_blitter_is_blit_supported(ctx->blitter, info))
937bf215546Sopenharmony_ci         util_blit(ctx, info);
938bf215546Sopenharmony_ci      else if (resolve_stencil_supported(ctx, info))
939bf215546Sopenharmony_ci         blit_resolve_stencil(ctx, info);
940bf215546Sopenharmony_ci      else
941bf215546Sopenharmony_ci         debug_printf("D3D12: resolve unsupported %s -> %s\n",
942bf215546Sopenharmony_ci                    util_format_short_name(info->src.resource->format),
943bf215546Sopenharmony_ci                    util_format_short_name(info->dst.resource->format));
944bf215546Sopenharmony_ci   } else if (direct_copy_supported(d3d12_screen(pctx->screen), info,
945bf215546Sopenharmony_ci                                    ctx->current_predication != nullptr))
946bf215546Sopenharmony_ci      d3d12_direct_copy(ctx, d3d12_resource(info->dst.resource),
947bf215546Sopenharmony_ci                        info->dst.level, &info->dst.box,
948bf215546Sopenharmony_ci                        d3d12_resource(info->src.resource),
949bf215546Sopenharmony_ci                        info->src.level, &info->src.box, info->mask);
950bf215546Sopenharmony_ci   else if (util_blitter_is_blit_supported(ctx->blitter, info))
951bf215546Sopenharmony_ci      util_blit(ctx, info);
952bf215546Sopenharmony_ci   else if (replicate_stencil_supported(ctx, info))
953bf215546Sopenharmony_ci      blit_replicate_stencil(ctx, info);
954bf215546Sopenharmony_ci   else
955bf215546Sopenharmony_ci      debug_printf("D3D12: blit unsupported %s -> %s\n",
956bf215546Sopenharmony_ci                 util_format_short_name(info->src.resource->format),
957bf215546Sopenharmony_ci                 util_format_short_name(info->dst.resource->format));
958bf215546Sopenharmony_ci
959bf215546Sopenharmony_ci   if (!info->render_condition_enable && ctx->current_predication) {
960bf215546Sopenharmony_ci      d3d12_enable_predication(ctx);
961bf215546Sopenharmony_ci      if (D3D12_DEBUG_BLIT & d3d12_debug)
962bf215546Sopenharmony_ci         debug_printf("D3D12 BLIT: Re-enable predication\n");
963bf215546Sopenharmony_ci   }
964bf215546Sopenharmony_ci
965bf215546Sopenharmony_ci}
966bf215546Sopenharmony_ci
967bf215546Sopenharmony_cistatic void
968bf215546Sopenharmony_cid3d12_resource_copy_region(struct pipe_context *pctx,
969bf215546Sopenharmony_ci                           struct pipe_resource *pdst,
970bf215546Sopenharmony_ci                           unsigned dst_level,
971bf215546Sopenharmony_ci                           unsigned dstx, unsigned dsty, unsigned dstz,
972bf215546Sopenharmony_ci                           struct pipe_resource *psrc,
973bf215546Sopenharmony_ci                           unsigned src_level,
974bf215546Sopenharmony_ci                           const struct pipe_box *psrc_box)
975bf215546Sopenharmony_ci{
976bf215546Sopenharmony_ci   struct d3d12_context *ctx = d3d12_context(pctx);
977bf215546Sopenharmony_ci   struct d3d12_resource *dst = d3d12_resource(pdst);
978bf215546Sopenharmony_ci   struct d3d12_resource *src = d3d12_resource(psrc);
979bf215546Sopenharmony_ci   struct pipe_resource *staging_res = NULL;
980bf215546Sopenharmony_ci   const struct pipe_box *src_box = psrc_box;
981bf215546Sopenharmony_ci   struct pipe_box staging_box, dst_box;
982bf215546Sopenharmony_ci
983bf215546Sopenharmony_ci   if (D3D12_DEBUG_BLIT & d3d12_debug) {
984bf215546Sopenharmony_ci      debug_printf("D3D12 COPY: from %s@%d msaa:%d mips:%d %dx%dx%d + %dx%dx%d\n",
985bf215546Sopenharmony_ci                   util_format_name(psrc->format), src_level, psrc->nr_samples,
986bf215546Sopenharmony_ci                   psrc->last_level,
987bf215546Sopenharmony_ci                   psrc_box->x, psrc_box->y, psrc_box->z,
988bf215546Sopenharmony_ci                   psrc_box->width, psrc_box->height, psrc_box->depth);
989bf215546Sopenharmony_ci      debug_printf("            to   %s@%d msaa:%d mips:%d %dx%dx%d\n",
990bf215546Sopenharmony_ci                   util_format_name(pdst->format), dst_level, psrc->nr_samples,
991bf215546Sopenharmony_ci                   psrc->last_level, dstx, dsty, dstz);
992bf215546Sopenharmony_ci   }
993bf215546Sopenharmony_ci
994bf215546Sopenharmony_ci   /* Use an intermediate resource if copying from/to the same subresource */
995bf215546Sopenharmony_ci   if (d3d12_resource_resource(dst) == d3d12_resource_resource(src) && dst_level == src_level) {
996bf215546Sopenharmony_ci      staging_res = create_staging_resource(ctx, src, src_level, psrc_box, &staging_box, PIPE_MASK_RGBAZS);
997bf215546Sopenharmony_ci      src = d3d12_resource(staging_res);
998bf215546Sopenharmony_ci      src_level = 0;
999bf215546Sopenharmony_ci      src_box = &staging_box;
1000bf215546Sopenharmony_ci   }
1001bf215546Sopenharmony_ci
1002bf215546Sopenharmony_ci   dst_box.x = dstx;
1003bf215546Sopenharmony_ci   dst_box.y = dsty;
1004bf215546Sopenharmony_ci   dst_box.z = dstz;
1005bf215546Sopenharmony_ci   dst_box.width = psrc_box->width;
1006bf215546Sopenharmony_ci   dst_box.height = psrc_box->height;
1007bf215546Sopenharmony_ci
1008bf215546Sopenharmony_ci   d3d12_direct_copy(ctx, dst, dst_level, &dst_box,
1009bf215546Sopenharmony_ci                     src, src_level, src_box, PIPE_MASK_RGBAZS);
1010bf215546Sopenharmony_ci
1011bf215546Sopenharmony_ci   if (staging_res)
1012bf215546Sopenharmony_ci      pipe_resource_reference(&staging_res, NULL);
1013bf215546Sopenharmony_ci}
1014bf215546Sopenharmony_ci
1015bf215546Sopenharmony_civoid
1016bf215546Sopenharmony_cid3d12_context_blit_init(struct pipe_context *ctx)
1017bf215546Sopenharmony_ci{
1018bf215546Sopenharmony_ci   ctx->resource_copy_region = d3d12_resource_copy_region;
1019bf215546Sopenharmony_ci   ctx->blit = d3d12_blit;
1020bf215546Sopenharmony_ci}
1021