17ec681f3Smrg/*
27ec681f3Smrg * Copyright © Microsoft Corporation
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
97ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
217ec681f3Smrg * IN THE SOFTWARE.
227ec681f3Smrg */
237ec681f3Smrg
247ec681f3Smrg#include "d3d12_context.h"
257ec681f3Smrg#include "d3d12_compiler.h"
267ec681f3Smrg#include "d3d12_debug.h"
277ec681f3Smrg#include "d3d12_format.h"
287ec681f3Smrg#include "d3d12_resource.h"
297ec681f3Smrg#include "d3d12_screen.h"
307ec681f3Smrg
317ec681f3Smrg#include "util/u_blitter.h"
327ec681f3Smrg#include "util/format/u_format.h"
337ec681f3Smrg
347ec681f3Smrg#include "nir_to_dxil.h"
357ec681f3Smrg#include "nir_builder.h"
367ec681f3Smrg
377ec681f3Smrgstatic void
387ec681f3Smrgcopy_buffer_region_no_barriers(struct d3d12_context *ctx,
397ec681f3Smrg                               struct d3d12_resource *dst,
407ec681f3Smrg                               uint64_t dst_offset,
417ec681f3Smrg                               struct d3d12_resource *src,
427ec681f3Smrg                               uint64_t src_offset,
437ec681f3Smrg                               uint64_t size)
447ec681f3Smrg{
457ec681f3Smrg   uint64_t dst_off, src_off;
467ec681f3Smrg   ID3D12Resource *dst_buf = d3d12_resource_underlying(dst, &dst_off);
477ec681f3Smrg   ID3D12Resource *src_buf = d3d12_resource_underlying(src, &src_off);
487ec681f3Smrg
497ec681f3Smrg   ctx->cmdlist->CopyBufferRegion(dst_buf, dst_offset + dst_off,
507ec681f3Smrg                                  src_buf, src_offset + src_off,
517ec681f3Smrg                                  size);
527ec681f3Smrg}
537ec681f3Smrg
547ec681f3Smrgstatic bool
557ec681f3Smrgis_resolve(const struct pipe_blit_info *info)
567ec681f3Smrg{
577ec681f3Smrg   return info->src.resource->nr_samples > 1 &&
587ec681f3Smrg          info->dst.resource->nr_samples <= 1;
597ec681f3Smrg}
607ec681f3Smrg
617ec681f3Smrgstatic bool
627ec681f3Smrgresolve_supported(const struct pipe_blit_info *info)
637ec681f3Smrg{
647ec681f3Smrg   assert(is_resolve(info));
657ec681f3Smrg
667ec681f3Smrg   // check for unsupported operations
677ec681f3Smrg   if (util_format_is_depth_or_stencil(info->src.format) &&
687ec681f3Smrg       info->mask != PIPE_MASK_Z) {
697ec681f3Smrg      return false;
707ec681f3Smrg   } else {
717ec681f3Smrg      if (util_format_get_mask(info->dst.format) != info->mask ||
727ec681f3Smrg          util_format_get_mask(info->src.format) != info->mask)
737ec681f3Smrg         return false;
747ec681f3Smrg   }
757ec681f3Smrg
767ec681f3Smrg   if (info->filter != PIPE_TEX_FILTER_NEAREST ||
777ec681f3Smrg       info->scissor_enable ||
787ec681f3Smrg       info->num_window_rectangles > 0 ||
797ec681f3Smrg       info->alpha_blend)
807ec681f3Smrg      return false;
817ec681f3Smrg
827ec681f3Smrg   // formats need to match
837ec681f3Smrg   struct d3d12_resource *src = d3d12_resource(info->src.resource);
847ec681f3Smrg   struct d3d12_resource *dst = d3d12_resource(info->dst.resource);
857ec681f3Smrg   if (src->dxgi_format != dst->dxgi_format)
867ec681f3Smrg      return false;
877ec681f3Smrg
887ec681f3Smrg   if (util_format_is_pure_integer(src->base.format))
897ec681f3Smrg      return false;
907ec681f3Smrg
917ec681f3Smrg   // sizes needs to match
927ec681f3Smrg   if (info->src.box.width != info->dst.box.width ||
937ec681f3Smrg       info->src.box.height != info->dst.box.height)
947ec681f3Smrg      return false;
957ec681f3Smrg
967ec681f3Smrg   // can only resolve full subresource
977ec681f3Smrg   if (info->src.box.width != (int)u_minify(info->src.resource->width0,
987ec681f3Smrg                                            info->src.level) ||
997ec681f3Smrg       info->src.box.height != (int)u_minify(info->src.resource->height0,
1007ec681f3Smrg                                             info->src.level) ||
1017ec681f3Smrg       info->dst.box.width != (int)u_minify(info->dst.resource->width0,
1027ec681f3Smrg                                            info->dst.level) ||
1037ec681f3Smrg       info->dst.box.height != (int)u_minify(info->dst.resource->height0,
1047ec681f3Smrg                                             info->dst.level))
1057ec681f3Smrg      return false;
1067ec681f3Smrg
1077ec681f3Smrg   return true;
1087ec681f3Smrg}
1097ec681f3Smrg
1107ec681f3Smrgstatic void
1117ec681f3Smrgblit_resolve(struct d3d12_context *ctx, const struct pipe_blit_info *info)
1127ec681f3Smrg{
1137ec681f3Smrg   struct d3d12_batch *batch = d3d12_current_batch(ctx);
1147ec681f3Smrg   struct d3d12_resource *src = d3d12_resource(info->src.resource);
1157ec681f3Smrg   struct d3d12_resource *dst = d3d12_resource(info->dst.resource);
1167ec681f3Smrg
1177ec681f3Smrg   d3d12_transition_resource_state(ctx, src,
1187ec681f3Smrg                                   D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
1197ec681f3Smrg                                   D3D12_BIND_INVALIDATE_FULL);
1207ec681f3Smrg   d3d12_transition_resource_state(ctx, dst,
1217ec681f3Smrg                                   D3D12_RESOURCE_STATE_RESOLVE_DEST,
1227ec681f3Smrg                                   D3D12_BIND_INVALIDATE_FULL);
1237ec681f3Smrg
1247ec681f3Smrg   d3d12_apply_resource_states(ctx);
1257ec681f3Smrg
1267ec681f3Smrg   d3d12_batch_reference_resource(batch, src);
1277ec681f3Smrg   d3d12_batch_reference_resource(batch, dst);
1287ec681f3Smrg
1297ec681f3Smrg   DXGI_FORMAT dxgi_format = d3d12_get_resource_srv_format(src->base.format, src->base.target);
1307ec681f3Smrg
1317ec681f3Smrg   assert(src->dxgi_format == dst->dxgi_format);
1327ec681f3Smrg   ctx->cmdlist->ResolveSubresource(
1337ec681f3Smrg      d3d12_resource_resource(dst), info->dst.level,
1347ec681f3Smrg      d3d12_resource_resource(src), info->src.level,
1357ec681f3Smrg      dxgi_format);
1367ec681f3Smrg}
1377ec681f3Smrg
1387ec681f3Smrgstatic bool
1397ec681f3Smrgformats_are_copy_compatible(enum pipe_format src, enum pipe_format dst)
1407ec681f3Smrg{
1417ec681f3Smrg   if (src == dst)
1427ec681f3Smrg      return true;
1437ec681f3Smrg
1447ec681f3Smrg   /* We can skip the stencil copy */
1457ec681f3Smrg   if (util_format_get_depth_only(src) == dst ||
1467ec681f3Smrg       util_format_get_depth_only(dst) == src)
1477ec681f3Smrg      return true;
1487ec681f3Smrg
1497ec681f3Smrg   return false;
1507ec681f3Smrg}
1517ec681f3Smrg
1527ec681f3Smrgstatic bool
1537ec681f3Smrgbox_fits(const struct pipe_box *box, const struct pipe_resource *res, int level)
1547ec681f3Smrg{
1557ec681f3Smrg   unsigned lwidth = u_minify(res->width0, level);
1567ec681f3Smrg   unsigned lheight= u_minify(res->height0, level);
1577ec681f3Smrg   unsigned ldepth = res->target == PIPE_TEXTURE_3D ? u_minify(res->depth0, level) :
1587ec681f3Smrg                                                      res->array_size;
1597ec681f3Smrg
1607ec681f3Smrg   unsigned wb = box->x;
1617ec681f3Smrg   unsigned we = box->x + box->width;
1627ec681f3Smrg
1637ec681f3Smrg   unsigned hb = box->y;
1647ec681f3Smrg   unsigned he = box->y + box->height;
1657ec681f3Smrg
1667ec681f3Smrg   unsigned db = box->z;
1677ec681f3Smrg   unsigned de = box->z + box->depth;
1687ec681f3Smrg
1697ec681f3Smrg   return (wb <= lwidth && we <= lwidth &&
1707ec681f3Smrg           hb <= lheight && he <= lheight &&
1717ec681f3Smrg           db <= ldepth && de <= ldepth);
1727ec681f3Smrg}
1737ec681f3Smrg
1747ec681f3Smrgstatic bool
1757ec681f3Smrgdirect_copy_supported(struct d3d12_screen *screen,
1767ec681f3Smrg                      const struct pipe_blit_info *info,
1777ec681f3Smrg                      bool have_predication)
1787ec681f3Smrg{
1797ec681f3Smrg   if (info->scissor_enable || info->alpha_blend ||
1807ec681f3Smrg       (have_predication && info->render_condition_enable) ||
1817ec681f3Smrg       MAX2(info->src.resource->nr_samples, 1) != MAX2(info->dst.resource->nr_samples, 1)) {
1827ec681f3Smrg      return false;
1837ec681f3Smrg   }
1847ec681f3Smrg
1857ec681f3Smrg   if (!formats_are_copy_compatible(info->src.format, info->dst.format))
1867ec681f3Smrg      return false;
1877ec681f3Smrg
1887ec681f3Smrg   if (util_format_is_depth_or_stencil(info->src.format) && !(info->mask & PIPE_MASK_ZS)) {
1897ec681f3Smrg      return false;
1907ec681f3Smrg   }
1917ec681f3Smrg
1927ec681f3Smrg   if (!util_format_is_depth_or_stencil(info->src.format)) {
1937ec681f3Smrg      if (util_format_get_mask(info->dst.format) != info->mask ||
1947ec681f3Smrg          util_format_get_mask(info->src.format) != info->mask)
1957ec681f3Smrg         return false;
1967ec681f3Smrg   }
1977ec681f3Smrg
1987ec681f3Smrg   if (abs(info->src.box.height) != info->dst.box.height) {
1997ec681f3Smrg      return false;
2007ec681f3Smrg   }
2017ec681f3Smrg
2027ec681f3Smrg   if (info->src.box.height != info->dst.box.height &&
2037ec681f3Smrg       (!util_format_is_depth_or_stencil(info->src.format) ||
2047ec681f3Smrg        screen->opts2.ProgrammableSamplePositionsTier ==
2057ec681f3Smrg        D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED)) {
2067ec681f3Smrg      return false;
2077ec681f3Smrg   }
2087ec681f3Smrg
2097ec681f3Smrg   if (!box_fits(&info->dst.box, info->dst.resource, info->dst.level)) {
2107ec681f3Smrg      return false;
2117ec681f3Smrg   }
2127ec681f3Smrg   if (!box_fits(&info->src.box, info->src.resource, info->src.level)) {
2137ec681f3Smrg      return false;
2147ec681f3Smrg   }
2157ec681f3Smrg
2167ec681f3Smrg   if (info->src.box.width != info->dst.box.width) {
2177ec681f3Smrg      return false;
2187ec681f3Smrg   }
2197ec681f3Smrg
2207ec681f3Smrg   if (info->src.box.depth != info->dst.box.depth) {
2217ec681f3Smrg      return false;
2227ec681f3Smrg   }
2237ec681f3Smrg
2247ec681f3Smrg   if ((screen->opts2.ProgrammableSamplePositionsTier ==
2257ec681f3Smrg        D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED &&
2267ec681f3Smrg        (info->src.resource->bind & PIPE_BIND_DEPTH_STENCIL ||
2277ec681f3Smrg         info->dst.resource->bind & PIPE_BIND_DEPTH_STENCIL)) ||
2287ec681f3Smrg        info->src.resource->nr_samples > 1) {
2297ec681f3Smrg
2307ec681f3Smrg      if (info->dst.box.x != 0 ||
2317ec681f3Smrg          info->dst.box.y != 0 ||
2327ec681f3Smrg          info->dst.box.z != 0)
2337ec681f3Smrg         return false;
2347ec681f3Smrg
2357ec681f3Smrg      if (info->src.box.x != 0 ||
2367ec681f3Smrg          info->src.box.y != 0 ||
2377ec681f3Smrg          info->src.box.z != 0 ||
2387ec681f3Smrg          info->src.box.width != (int)u_minify(info->src.resource->width0,
2397ec681f3Smrg                                               info->src.level) ||
2407ec681f3Smrg          info->src.box.height != (int)u_minify(info->src.resource->height0,
2417ec681f3Smrg                                                info->src.level) ||
2427ec681f3Smrg          info->src.box.depth != (int)u_minify(info->src.resource->depth0,
2437ec681f3Smrg                                               info->src.level))
2447ec681f3Smrg         return false;
2457ec681f3Smrg   }
2467ec681f3Smrg
2477ec681f3Smrg   return true;
2487ec681f3Smrg}
2497ec681f3Smrg
2507ec681f3Smrginline static unsigned
2517ec681f3Smrgget_subresource_id(enum pipe_texture_target target, unsigned subres, unsigned stride,
2527ec681f3Smrg                   unsigned z, unsigned *updated_z)
2537ec681f3Smrg{
2547ec681f3Smrg   if (d3d12_subresource_id_uses_layer(target)) {
2557ec681f3Smrg      subres += stride * z;
2567ec681f3Smrg      if (updated_z)
2577ec681f3Smrg         *updated_z = 0;
2587ec681f3Smrg   }
2597ec681f3Smrg   return subres;
2607ec681f3Smrg}
2617ec681f3Smrg
2627ec681f3Smrgstatic void
2637ec681f3Smrgcopy_subregion_no_barriers(struct d3d12_context *ctx,
2647ec681f3Smrg                           struct d3d12_resource *dst,
2657ec681f3Smrg                           unsigned dst_level,
2667ec681f3Smrg                           unsigned dstx, unsigned dsty, unsigned dstz,
2677ec681f3Smrg                           struct d3d12_resource *src,
2687ec681f3Smrg                           unsigned src_level,
2697ec681f3Smrg                           const struct pipe_box *psrc_box,
2707ec681f3Smrg                           unsigned mask)
2717ec681f3Smrg{
2727ec681f3Smrg   UNUSED struct d3d12_screen *screen = d3d12_screen(ctx->base.screen);
2737ec681f3Smrg   D3D12_TEXTURE_COPY_LOCATION src_loc, dst_loc;
2747ec681f3Smrg   unsigned src_z = psrc_box->z;
2757ec681f3Smrg
2767ec681f3Smrg   int src_subres_stride = src->base.last_level + 1;
2777ec681f3Smrg   int dst_subres_stride = dst->base.last_level + 1;
2787ec681f3Smrg
2797ec681f3Smrg   int src_array_size = src->base.array_size;
2807ec681f3Smrg   int dst_array_size = dst->base.array_size;
2817ec681f3Smrg
2827ec681f3Smrg   if (dst->base.target == PIPE_TEXTURE_CUBE)
2837ec681f3Smrg      dst_array_size *= 6;
2847ec681f3Smrg
2857ec681f3Smrg   if (src->base.target == PIPE_TEXTURE_CUBE)
2867ec681f3Smrg      src_array_size *= 6;
2877ec681f3Smrg
2887ec681f3Smrg   int stencil_src_res_offset = 1;
2897ec681f3Smrg   int stencil_dst_res_offset = 1;
2907ec681f3Smrg
2917ec681f3Smrg   int src_nres = 1;
2927ec681f3Smrg   int dst_nres = 1;
2937ec681f3Smrg
2947ec681f3Smrg   if (dst->base.format == PIPE_FORMAT_Z24_UNORM_S8_UINT ||
2957ec681f3Smrg       dst->base.format == PIPE_FORMAT_S8_UINT_Z24_UNORM ||
2967ec681f3Smrg       dst->base.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) {
2977ec681f3Smrg      stencil_dst_res_offset = dst_subres_stride * dst_array_size;
2987ec681f3Smrg      src_nres = 2;
2997ec681f3Smrg   }
3007ec681f3Smrg
3017ec681f3Smrg   if (src->base.format == PIPE_FORMAT_Z24_UNORM_S8_UINT ||
3027ec681f3Smrg       src->base.format == PIPE_FORMAT_S8_UINT_Z24_UNORM ||
3037ec681f3Smrg       dst->base.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) {
3047ec681f3Smrg      stencil_src_res_offset = src_subres_stride * src_array_size;
3057ec681f3Smrg      dst_nres = 2;
3067ec681f3Smrg   }
3077ec681f3Smrg
3087ec681f3Smrg   static_assert(PIPE_MASK_S == 0x20 && PIPE_MASK_Z == 0x10, "unexpected ZS format mask");
3097ec681f3Smrg   int nsubres = MIN2(src_nres, dst_nres);
3107ec681f3Smrg   unsigned subresource_copy_mask = nsubres > 1 ? mask >> 4 : 1;
3117ec681f3Smrg
3127ec681f3Smrg   for (int subres = 0; subres < nsubres; ++subres) {
3137ec681f3Smrg
3147ec681f3Smrg      if (!(subresource_copy_mask & (1 << subres)))
3157ec681f3Smrg         continue;
3167ec681f3Smrg
3177ec681f3Smrg      src_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
3187ec681f3Smrg      src_loc.SubresourceIndex = get_subresource_id(src->base.target, src_level, src_subres_stride, src_z, &src_z) +
3197ec681f3Smrg                                 subres * stencil_src_res_offset;
3207ec681f3Smrg      src_loc.pResource = d3d12_resource_resource(src);
3217ec681f3Smrg
3227ec681f3Smrg      dst_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
3237ec681f3Smrg      dst_loc.SubresourceIndex = get_subresource_id(dst->base.target, dst_level, dst_subres_stride, dstz, &dstz) +
3247ec681f3Smrg                                 subres * stencil_dst_res_offset;
3257ec681f3Smrg      dst_loc.pResource = d3d12_resource_resource(dst);
3267ec681f3Smrg
3277ec681f3Smrg      if (psrc_box->x == 0 && psrc_box->y == 0 && psrc_box->z == 0 &&
3287ec681f3Smrg          psrc_box->width == (int)u_minify(src->base.width0, src_level) &&
3297ec681f3Smrg          psrc_box->height == (int)u_minify(src->base.height0, src_level) &&
3307ec681f3Smrg          psrc_box->depth == (int)u_minify(src->base.depth0, src_level)) {
3317ec681f3Smrg
3327ec681f3Smrg         assert((dstx == 0 && dsty == 0 && dstz == 0) ||
3337ec681f3Smrg                screen->opts2.ProgrammableSamplePositionsTier !=
3347ec681f3Smrg                D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED ||
3357ec681f3Smrg                (!util_format_is_depth_or_stencil(dst->base.format) &&
3367ec681f3Smrg                 !util_format_is_depth_or_stencil(src->base.format) &&
3377ec681f3Smrg                  dst->base.nr_samples <= 1 &&
3387ec681f3Smrg                  src->base.nr_samples <= 1));
3397ec681f3Smrg
3407ec681f3Smrg         ctx->cmdlist->CopyTextureRegion(&dst_loc, dstx, dsty, dstz,
3417ec681f3Smrg                                         &src_loc, NULL);
3427ec681f3Smrg
3437ec681f3Smrg      } else {
3447ec681f3Smrg         D3D12_BOX src_box;
3457ec681f3Smrg         src_box.left = psrc_box->x;
3467ec681f3Smrg         src_box.right = MIN2(psrc_box->x + psrc_box->width, (int)u_minify(src->base.width0, src_level));
3477ec681f3Smrg         src_box.top = psrc_box->y;
3487ec681f3Smrg         src_box.bottom = MIN2(psrc_box->y + psrc_box->height, (int)u_minify(src->base.height0, src_level));
3497ec681f3Smrg         src_box.front = src_z;
3507ec681f3Smrg         src_box.back = src_z + psrc_box->depth;
3517ec681f3Smrg
3527ec681f3Smrg         assert((screen->opts2.ProgrammableSamplePositionsTier !=
3537ec681f3Smrg                 D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED ||
3547ec681f3Smrg                 (!util_format_is_depth_or_stencil(dst->base.format) &&
3557ec681f3Smrg                  !util_format_is_depth_or_stencil(src->base.format))) &&
3567ec681f3Smrg                dst->base.nr_samples <= 1 &&
3577ec681f3Smrg                src->base.nr_samples <= 1);
3587ec681f3Smrg
3597ec681f3Smrg         ctx->cmdlist->CopyTextureRegion(&dst_loc, dstx, dsty, dstz,
3607ec681f3Smrg                                         &src_loc, &src_box);
3617ec681f3Smrg      }
3627ec681f3Smrg   }
3637ec681f3Smrg}
3647ec681f3Smrg
3657ec681f3Smrgstatic void
3667ec681f3Smrgcopy_resource_y_flipped_no_barriers(struct d3d12_context *ctx,
3677ec681f3Smrg                                    struct d3d12_resource *dst,
3687ec681f3Smrg                                    unsigned dst_level,
3697ec681f3Smrg                                    const struct pipe_box *pdst_box,
3707ec681f3Smrg                                    struct d3d12_resource *src,
3717ec681f3Smrg                                    unsigned src_level,
3727ec681f3Smrg                                    const struct pipe_box *psrc_box,
3737ec681f3Smrg                                    unsigned mask)
3747ec681f3Smrg{
3757ec681f3Smrg   if (D3D12_DEBUG_BLIT & d3d12_debug) {
3767ec681f3Smrg      debug_printf("D3D12 BLIT as COPY: from %s@%d %dx%dx%d + %dx%dx%d\n",
3777ec681f3Smrg                   util_format_name(src->base.format), src_level,
3787ec681f3Smrg                   psrc_box->x, psrc_box->y, psrc_box->z,
3797ec681f3Smrg                   psrc_box->width, psrc_box->height, psrc_box->depth);
3807ec681f3Smrg      debug_printf("      to   %s@%d %dx%dx%d\n",
3817ec681f3Smrg                   util_format_name(dst->base.format), dst_level,
3827ec681f3Smrg                   pdst_box->x, pdst_box->y, pdst_box->z);
3837ec681f3Smrg   }
3847ec681f3Smrg
3857ec681f3Smrg   struct pipe_box src_box = *psrc_box;
3867ec681f3Smrg   int src_inc = psrc_box->height > 0 ? 1 : -1;
3877ec681f3Smrg   int dst_inc = pdst_box->height > 0 ? 1 : -1;
3887ec681f3Smrg   src_box.height = 1;
3897ec681f3Smrg   int rows_to_copy = abs(psrc_box->height);
3907ec681f3Smrg
3917ec681f3Smrg   if (psrc_box->height < 0)
3927ec681f3Smrg      --src_box.y;
3937ec681f3Smrg
3947ec681f3Smrg   for (int y = 0, dest_y = pdst_box->y; y < rows_to_copy;
3957ec681f3Smrg        ++y, src_box.y += src_inc, dest_y += dst_inc) {
3967ec681f3Smrg      copy_subregion_no_barriers(ctx, dst, dst_level,
3977ec681f3Smrg                                 pdst_box->x, dest_y, pdst_box->z,
3987ec681f3Smrg                                 src, src_level, &src_box, mask);
3997ec681f3Smrg   }
4007ec681f3Smrg}
4017ec681f3Smrg
4027ec681f3Smrgvoid
4037ec681f3Smrgd3d12_direct_copy(struct d3d12_context *ctx,
4047ec681f3Smrg                  struct d3d12_resource *dst,
4057ec681f3Smrg                  unsigned dst_level,
4067ec681f3Smrg                  const struct pipe_box *pdst_box,
4077ec681f3Smrg                  struct d3d12_resource *src,
4087ec681f3Smrg                  unsigned src_level,
4097ec681f3Smrg                  const struct pipe_box *psrc_box,
4107ec681f3Smrg                  unsigned mask)
4117ec681f3Smrg{
4127ec681f3Smrg   struct d3d12_batch *batch = d3d12_current_batch(ctx);
4137ec681f3Smrg
4147ec681f3Smrg   unsigned src_subres = get_subresource_id(src->base.target, src_level, src->base.last_level + 1,
4157ec681f3Smrg                                            psrc_box->z, nullptr);
4167ec681f3Smrg   unsigned dst_subres = get_subresource_id(dst->base.target, dst_level, dst->base.last_level + 1,
4177ec681f3Smrg                                            pdst_box->z, nullptr);
4187ec681f3Smrg
4197ec681f3Smrg   if (D3D12_DEBUG_BLIT & d3d12_debug)
4207ec681f3Smrg      debug_printf("BLIT: Direct copy from subres %d to subres  %d\n",
4217ec681f3Smrg                   src_subres, dst_subres);
4227ec681f3Smrg
4237ec681f3Smrg   d3d12_transition_subresources_state(ctx, src, src_subres, 1, 0, 1,
4247ec681f3Smrg                                       d3d12_get_format_start_plane(src->base.format),
4257ec681f3Smrg                                       d3d12_get_format_num_planes(src->base.format),
4267ec681f3Smrg                                       D3D12_RESOURCE_STATE_COPY_SOURCE,
4277ec681f3Smrg                                       D3D12_BIND_INVALIDATE_FULL);
4287ec681f3Smrg
4297ec681f3Smrg   d3d12_transition_subresources_state(ctx, dst, dst_subres, 1, 0, 1,
4307ec681f3Smrg                                       d3d12_get_format_start_plane(dst->base.format),
4317ec681f3Smrg                                       d3d12_get_format_num_planes(dst->base.format),
4327ec681f3Smrg                                       D3D12_RESOURCE_STATE_COPY_DEST,
4337ec681f3Smrg                                       D3D12_BIND_INVALIDATE_FULL);
4347ec681f3Smrg
4357ec681f3Smrg   d3d12_apply_resource_states(ctx);
4367ec681f3Smrg
4377ec681f3Smrg   d3d12_batch_reference_resource(batch, src);
4387ec681f3Smrg   d3d12_batch_reference_resource(batch, dst);
4397ec681f3Smrg
4407ec681f3Smrg   if (src->base.target == PIPE_BUFFER) {
4417ec681f3Smrg      copy_buffer_region_no_barriers(ctx, dst, pdst_box->x,
4427ec681f3Smrg                                     src, psrc_box->x, psrc_box->width);
4437ec681f3Smrg   } else if (psrc_box->height == pdst_box->height) {
4447ec681f3Smrg      /* No flipping, we can forward this directly to resource_copy_region */
4457ec681f3Smrg      copy_subregion_no_barriers(ctx, dst, dst_level,
4467ec681f3Smrg                                 pdst_box->x, pdst_box->y, pdst_box->z,
4477ec681f3Smrg                                 src, src_level, psrc_box, mask);
4487ec681f3Smrg   } else {
4497ec681f3Smrg      assert(psrc_box->height == -pdst_box->height);
4507ec681f3Smrg      copy_resource_y_flipped_no_barriers(ctx, dst, dst_level, pdst_box,
4517ec681f3Smrg                                          src, src_level, psrc_box, mask);
4527ec681f3Smrg   }
4537ec681f3Smrg}
4547ec681f3Smrg
4557ec681f3Smrgstatic bool
4567ec681f3Smrgis_same_resource(const struct pipe_blit_info *info)
4577ec681f3Smrg{
4587ec681f3Smrg   return d3d12_resource_resource(d3d12_resource(info->src.resource)) ==
4597ec681f3Smrg             d3d12_resource_resource(d3d12_resource(info->dst.resource)) &&
4607ec681f3Smrg          info->src.level == info->dst.level;
4617ec681f3Smrg}
4627ec681f3Smrg
4637ec681f3Smrgstatic struct pipe_resource *
4647ec681f3Smrgcreate_staging_resource(struct d3d12_context *ctx,
4657ec681f3Smrg                        struct d3d12_resource *src,
4667ec681f3Smrg                        unsigned src_level,
4677ec681f3Smrg                        const struct pipe_box *src_box,
4687ec681f3Smrg                        struct pipe_box *dst_box,
4697ec681f3Smrg                        unsigned mask)
4707ec681f3Smrg
4717ec681f3Smrg{
4727ec681f3Smrg   struct pipe_resource templ = {};
4737ec681f3Smrg   struct pipe_resource *staging_res;
4747ec681f3Smrg   struct pipe_box copy_src;
4757ec681f3Smrg
4767ec681f3Smrg   u_box_3d(MIN2(src_box->x, src_box->x + src_box->width),
4777ec681f3Smrg            MIN2(src_box->y, src_box->y + src_box->height),
4787ec681f3Smrg            MIN2(src_box->z, src_box->z + src_box->depth),
4797ec681f3Smrg            abs(src_box->width), abs(src_box->height), abs(src_box->depth),
4807ec681f3Smrg            &copy_src);
4817ec681f3Smrg
4827ec681f3Smrg   templ.format = src->base.format;
4837ec681f3Smrg   templ.width0 = copy_src.width;
4847ec681f3Smrg   templ.height0 = copy_src.height;
4857ec681f3Smrg   templ.depth0 = copy_src.depth;
4867ec681f3Smrg   templ.array_size = 1;
4877ec681f3Smrg   templ.nr_samples = 1;
4887ec681f3Smrg   templ.nr_storage_samples = 1;
4897ec681f3Smrg   templ.usage = PIPE_USAGE_STAGING;
4907ec681f3Smrg   templ.bind = util_format_is_depth_or_stencil(templ.format) ? PIPE_BIND_DEPTH_STENCIL : PIPE_BIND_RENDER_TARGET;
4917ec681f3Smrg   templ.target = src->base.target;
4927ec681f3Smrg
4937ec681f3Smrg   staging_res = ctx->base.screen->resource_create(ctx->base.screen, &templ);
4947ec681f3Smrg
4957ec681f3Smrg   dst_box->x = 0;
4967ec681f3Smrg   dst_box->y = 0;
4977ec681f3Smrg   dst_box->z = 0;
4987ec681f3Smrg   dst_box->width = copy_src.width;
4997ec681f3Smrg   dst_box->height = copy_src.height;
5007ec681f3Smrg   dst_box->depth = copy_src.depth;
5017ec681f3Smrg
5027ec681f3Smrg   d3d12_direct_copy(ctx, d3d12_resource(staging_res), 0, dst_box,
5037ec681f3Smrg                     src, src_level, &copy_src, mask);
5047ec681f3Smrg
5057ec681f3Smrg   if (src_box->width < 0) {
5067ec681f3Smrg      dst_box->x = dst_box->width;
5077ec681f3Smrg      dst_box->width = src_box->width;
5087ec681f3Smrg   }
5097ec681f3Smrg
5107ec681f3Smrg   if (src_box->height < 0) {
5117ec681f3Smrg      dst_box->y = dst_box->height;
5127ec681f3Smrg      dst_box->height = src_box->height;
5137ec681f3Smrg   }
5147ec681f3Smrg
5157ec681f3Smrg   if (src_box->depth < 0) {
5167ec681f3Smrg      dst_box->z = dst_box->depth;
5177ec681f3Smrg      dst_box->depth = src_box->depth;
5187ec681f3Smrg   }
5197ec681f3Smrg   return staging_res;
5207ec681f3Smrg}
5217ec681f3Smrg
5227ec681f3Smrgstatic void
5237ec681f3Smrgblit_same_resource(struct d3d12_context *ctx,
5247ec681f3Smrg                   const struct pipe_blit_info *info)
5257ec681f3Smrg{
5267ec681f3Smrg   struct pipe_blit_info dst_info = *info;
5277ec681f3Smrg
5287ec681f3Smrg   dst_info.src.level = 0;
5297ec681f3Smrg   dst_info.src.resource = create_staging_resource(ctx, d3d12_resource(info->src.resource),
5307ec681f3Smrg                                                   info->src.level,
5317ec681f3Smrg                                                   &info->src.box,
5327ec681f3Smrg                                                   &dst_info.src.box, PIPE_MASK_RGBAZS);
5337ec681f3Smrg   ctx->base.blit(&ctx->base, &dst_info);
5347ec681f3Smrg   pipe_resource_reference(&dst_info.src.resource, NULL);
5357ec681f3Smrg}
5367ec681f3Smrg
5377ec681f3Smrgstatic void
5387ec681f3Smrgutil_blit_save_state(struct d3d12_context *ctx)
5397ec681f3Smrg{
5407ec681f3Smrg   util_blitter_save_blend(ctx->blitter, ctx->gfx_pipeline_state.blend);
5417ec681f3Smrg   util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->gfx_pipeline_state.zsa);
5427ec681f3Smrg   util_blitter_save_vertex_elements(ctx->blitter, ctx->gfx_pipeline_state.ves);
5437ec681f3Smrg   util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
5447ec681f3Smrg   util_blitter_save_rasterizer(ctx->blitter, ctx->gfx_pipeline_state.rast);
5457ec681f3Smrg   util_blitter_save_fragment_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_FRAGMENT]);
5467ec681f3Smrg   util_blitter_save_vertex_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_VERTEX]);
5477ec681f3Smrg   util_blitter_save_geometry_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_GEOMETRY]);
5487ec681f3Smrg
5497ec681f3Smrg   util_blitter_save_framebuffer(ctx->blitter, &ctx->fb);
5507ec681f3Smrg   util_blitter_save_viewport(ctx->blitter, ctx->viewport_states);
5517ec681f3Smrg   util_blitter_save_scissor(ctx->blitter, ctx->scissor_states);
5527ec681f3Smrg   util_blitter_save_fragment_sampler_states(ctx->blitter,
5537ec681f3Smrg                                             ctx->num_samplers[PIPE_SHADER_FRAGMENT],
5547ec681f3Smrg                                             (void **)ctx->samplers[PIPE_SHADER_FRAGMENT]);
5557ec681f3Smrg   util_blitter_save_fragment_sampler_views(ctx->blitter,
5567ec681f3Smrg                                            ctx->num_sampler_views[PIPE_SHADER_FRAGMENT],
5577ec681f3Smrg                                            ctx->sampler_views[PIPE_SHADER_FRAGMENT]);
5587ec681f3Smrg   util_blitter_save_fragment_constant_buffer_slot(ctx->blitter, ctx->cbufs[PIPE_SHADER_FRAGMENT]);
5597ec681f3Smrg   util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vbs);
5607ec681f3Smrg   util_blitter_save_sample_mask(ctx->blitter, ctx->gfx_pipeline_state.sample_mask);
5617ec681f3Smrg   util_blitter_save_so_targets(ctx->blitter, ctx->gfx_pipeline_state.num_so_targets, ctx->so_targets);
5627ec681f3Smrg}
5637ec681f3Smrg
5647ec681f3Smrgstatic void
5657ec681f3Smrgutil_blit(struct d3d12_context *ctx,
5667ec681f3Smrg          const struct pipe_blit_info *info)
5677ec681f3Smrg{
5687ec681f3Smrg   util_blit_save_state(ctx);
5697ec681f3Smrg
5707ec681f3Smrg   util_blitter_blit(ctx->blitter, info);
5717ec681f3Smrg}
5727ec681f3Smrg
5737ec681f3Smrgstatic bool
5747ec681f3Smrgresolve_stencil_supported(struct d3d12_context *ctx,
5757ec681f3Smrg                          const struct pipe_blit_info *info)
5767ec681f3Smrg{
5777ec681f3Smrg   assert(is_resolve(info));
5787ec681f3Smrg
5797ec681f3Smrg   if (!util_format_is_depth_or_stencil(info->src.format) ||
5807ec681f3Smrg       !(info->mask & PIPE_MASK_S))
5817ec681f3Smrg      return false;
5827ec681f3Smrg
5837ec681f3Smrg   if (info->mask & PIPE_MASK_Z) {
5847ec681f3Smrg      struct pipe_blit_info new_info = *info;
5857ec681f3Smrg      new_info.mask = PIPE_MASK_Z;
5867ec681f3Smrg      if (!resolve_supported(&new_info) &&
5877ec681f3Smrg          !util_blitter_is_blit_supported(ctx->blitter, &new_info))
5887ec681f3Smrg         return false;
5897ec681f3Smrg   }
5907ec681f3Smrg
5917ec681f3Smrg   struct pipe_blit_info new_info = *info;
5927ec681f3Smrg   new_info.dst.format = PIPE_FORMAT_R8_UINT;
5937ec681f3Smrg   return util_blitter_is_blit_supported(ctx->blitter, &new_info);
5947ec681f3Smrg}
5957ec681f3Smrg
5967ec681f3Smrgstatic struct pipe_resource *
5977ec681f3Smrgcreate_tmp_resource(struct pipe_screen *screen,
5987ec681f3Smrg                    const struct pipe_blit_info *info)
5997ec681f3Smrg{
6007ec681f3Smrg   struct pipe_resource tpl = {};
6017ec681f3Smrg   tpl.width0 = info->dst.box.width;
6027ec681f3Smrg   tpl.height0 = info->dst.box.height;
6037ec681f3Smrg   tpl.depth0 = info->dst.box.depth;
6047ec681f3Smrg   tpl.array_size = 1;
6057ec681f3Smrg   tpl.format = PIPE_FORMAT_R8_UINT;
6067ec681f3Smrg   tpl.target = info->dst.resource->target;
6077ec681f3Smrg   tpl.nr_samples = info->dst.resource->nr_samples;
6087ec681f3Smrg   tpl.nr_storage_samples = info->dst.resource->nr_storage_samples;
6097ec681f3Smrg   tpl.usage = PIPE_USAGE_STREAM;
6107ec681f3Smrg   tpl.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
6117ec681f3Smrg   return screen->resource_create(screen, &tpl);
6127ec681f3Smrg}
6137ec681f3Smrg
6147ec681f3Smrgstatic void *
6157ec681f3Smrgget_stencil_resolve_vs(struct d3d12_context *ctx)
6167ec681f3Smrg{
6177ec681f3Smrg   if (ctx->stencil_resolve_vs)
6187ec681f3Smrg      return ctx->stencil_resolve_vs;
6197ec681f3Smrg
6207ec681f3Smrg   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_VERTEX,
6217ec681f3Smrg                                                  dxil_get_nir_compiler_options(),
6227ec681f3Smrg                                                  "linear_blit_vs");
6237ec681f3Smrg
6247ec681f3Smrg   const struct glsl_type *vec4 = glsl_vec4_type();
6257ec681f3Smrg   nir_variable *pos_in = nir_variable_create(b.shader, nir_var_shader_in,
6267ec681f3Smrg                                              vec4, "pos");
6277ec681f3Smrg
6287ec681f3Smrg   nir_variable *pos_out = nir_variable_create(b.shader, nir_var_shader_out,
6297ec681f3Smrg                                               vec4, "gl_Position");
6307ec681f3Smrg   pos_out->data.location = VARYING_SLOT_POS;
6317ec681f3Smrg
6327ec681f3Smrg   nir_store_var(&b, pos_out, nir_load_var(&b, pos_in), 0xf);
6337ec681f3Smrg
6347ec681f3Smrg   struct pipe_shader_state state = {};
6357ec681f3Smrg   state.type = PIPE_SHADER_IR_NIR;
6367ec681f3Smrg   state.ir.nir = b.shader;
6377ec681f3Smrg   ctx->stencil_resolve_vs = ctx->base.create_vs_state(&ctx->base, &state);
6387ec681f3Smrg
6397ec681f3Smrg   return ctx->stencil_resolve_vs;
6407ec681f3Smrg}
6417ec681f3Smrg
6427ec681f3Smrgstatic void *
6437ec681f3Smrgget_stencil_resolve_fs(struct d3d12_context *ctx, bool no_flip)
6447ec681f3Smrg{
6457ec681f3Smrg   if (!no_flip && ctx->stencil_resolve_fs)
6467ec681f3Smrg      return ctx->stencil_resolve_fs;
6477ec681f3Smrg
6487ec681f3Smrg   if (no_flip && ctx->stencil_resolve_fs_no_flip)
6497ec681f3Smrg      return ctx->stencil_resolve_fs_no_flip;
6507ec681f3Smrg
6517ec681f3Smrg   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT,
6527ec681f3Smrg                                                  dxil_get_nir_compiler_options(),
6537ec681f3Smrg                                                  no_flip ? "stencil_resolve_fs_no_flip" : "stencil_resolve_fs");
6547ec681f3Smrg
6557ec681f3Smrg   nir_variable *stencil_out = nir_variable_create(b.shader,
6567ec681f3Smrg                                                   nir_var_shader_out,
6577ec681f3Smrg                                                   glsl_uint_type(),
6587ec681f3Smrg                                                   "stencil_out");
6597ec681f3Smrg   stencil_out->data.location = FRAG_RESULT_COLOR;
6607ec681f3Smrg
6617ec681f3Smrg   const struct glsl_type *sampler_type =
6627ec681f3Smrg      glsl_sampler_type(GLSL_SAMPLER_DIM_MS, false, false, GLSL_TYPE_UINT);
6637ec681f3Smrg   nir_variable *sampler = nir_variable_create(b.shader, nir_var_uniform,
6647ec681f3Smrg                                               sampler_type, "stencil_tex");
6657ec681f3Smrg   sampler->data.binding = 0;
6667ec681f3Smrg   sampler->data.explicit_binding = true;
6677ec681f3Smrg
6687ec681f3Smrg   nir_ssa_def *tex_deref = &nir_build_deref_var(&b, sampler)->dest.ssa;
6697ec681f3Smrg
6707ec681f3Smrg   nir_variable *pos_in = nir_variable_create(b.shader, nir_var_shader_in,
6717ec681f3Smrg                                              glsl_vec4_type(), "pos");
6727ec681f3Smrg   pos_in->data.location = VARYING_SLOT_POS; // VARYING_SLOT_VAR0?
6737ec681f3Smrg   nir_ssa_def *pos = nir_load_var(&b, pos_in);
6747ec681f3Smrg
6757ec681f3Smrg   nir_ssa_def *pos_src;
6767ec681f3Smrg
6777ec681f3Smrg   if (no_flip)
6787ec681f3Smrg      pos_src = pos;
6797ec681f3Smrg   else {
6807ec681f3Smrg      nir_tex_instr *txs = nir_tex_instr_create(b.shader, 1);
6817ec681f3Smrg      txs->op = nir_texop_txs;
6827ec681f3Smrg      txs->sampler_dim = GLSL_SAMPLER_DIM_MS;
6837ec681f3Smrg      txs->src[0].src_type = nir_tex_src_texture_deref;
6847ec681f3Smrg      txs->src[0].src = nir_src_for_ssa(tex_deref);
6857ec681f3Smrg      txs->is_array = false;
6867ec681f3Smrg      txs->dest_type = nir_type_int;
6877ec681f3Smrg
6887ec681f3Smrg      nir_ssa_dest_init(&txs->instr, &txs->dest, 2, 32, "tex");
6897ec681f3Smrg      nir_builder_instr_insert(&b, &txs->instr);
6907ec681f3Smrg
6917ec681f3Smrg      pos_src = nir_vec4(&b,
6927ec681f3Smrg                         nir_channel(&b, pos, 0),
6937ec681f3Smrg                         /*Height - pos_dest.y - 1*/
6947ec681f3Smrg                         nir_fsub(&b,
6957ec681f3Smrg                                  nir_fsub(&b,
6967ec681f3Smrg                                           nir_channel(&b, nir_i2f32(&b, &txs->dest.ssa), 1),
6977ec681f3Smrg                                           nir_channel(&b, pos, 1)),
6987ec681f3Smrg                                  nir_imm_float(&b, 1.0)),
6997ec681f3Smrg                         nir_channel(&b, pos, 2),
7007ec681f3Smrg                         nir_channel(&b, pos, 3));
7017ec681f3Smrg   }
7027ec681f3Smrg
7037ec681f3Smrg   nir_tex_instr *tex = nir_tex_instr_create(b.shader, 3);
7047ec681f3Smrg   tex->sampler_dim = GLSL_SAMPLER_DIM_MS;
7057ec681f3Smrg   tex->op = nir_texop_txf_ms;
7067ec681f3Smrg   tex->src[0].src_type = nir_tex_src_coord;
7077ec681f3Smrg   tex->src[0].src = nir_src_for_ssa(nir_channels(&b, nir_f2i32(&b, pos_src), 0x3));
7087ec681f3Smrg   tex->src[1].src_type = nir_tex_src_ms_index;
7097ec681f3Smrg   tex->src[1].src = nir_src_for_ssa(nir_imm_int(&b, 0)); /* just use first sample */
7107ec681f3Smrg   tex->src[2].src_type = nir_tex_src_texture_deref;
7117ec681f3Smrg   tex->src[2].src = nir_src_for_ssa(tex_deref);
7127ec681f3Smrg   tex->dest_type = nir_type_uint32;
7137ec681f3Smrg   tex->is_array = false;
7147ec681f3Smrg   tex->coord_components = 2;
7157ec681f3Smrg
7167ec681f3Smrg   nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, "tex");
7177ec681f3Smrg   nir_builder_instr_insert(&b, &tex->instr);
7187ec681f3Smrg
7197ec681f3Smrg   nir_store_var(&b, stencil_out, nir_channel(&b, &tex->dest.ssa, 1), 0x1);
7207ec681f3Smrg
7217ec681f3Smrg   struct pipe_shader_state state = {};
7227ec681f3Smrg   state.type = PIPE_SHADER_IR_NIR;
7237ec681f3Smrg   state.ir.nir = b.shader;
7247ec681f3Smrg   void *result;
7257ec681f3Smrg   if (no_flip) {
7267ec681f3Smrg      result = ctx->base.create_fs_state(&ctx->base, &state);
7277ec681f3Smrg      ctx->stencil_resolve_fs_no_flip = result;
7287ec681f3Smrg   } else {
7297ec681f3Smrg      result = ctx->base.create_fs_state(&ctx->base, &state);
7307ec681f3Smrg      ctx->stencil_resolve_fs = result;
7317ec681f3Smrg   }
7327ec681f3Smrg
7337ec681f3Smrg   return result;
7347ec681f3Smrg}
7357ec681f3Smrg
7367ec681f3Smrgstatic void *
7377ec681f3Smrgget_sampler_state(struct d3d12_context *ctx)
7387ec681f3Smrg{
7397ec681f3Smrg   if (ctx->sampler_state)
7407ec681f3Smrg      return ctx->sampler_state;
7417ec681f3Smrg
7427ec681f3Smrg   struct pipe_sampler_state state;
7437ec681f3Smrg   memset(&state, 0, sizeof(state));
7447ec681f3Smrg   state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
7457ec681f3Smrg   state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
7467ec681f3Smrg   state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
7477ec681f3Smrg   state.normalized_coords = 1;
7487ec681f3Smrg
7497ec681f3Smrg   return ctx->sampler_state = ctx->base.create_sampler_state(&ctx->base, &state);
7507ec681f3Smrg}
7517ec681f3Smrg
7527ec681f3Smrgstatic struct pipe_resource *
7537ec681f3Smrgresolve_stencil_to_temp(struct d3d12_context *ctx,
7547ec681f3Smrg                        const struct pipe_blit_info *info)
7557ec681f3Smrg{
7567ec681f3Smrg   struct pipe_context *pctx = &ctx->base;
7577ec681f3Smrg   struct pipe_resource *tmp = create_tmp_resource(pctx->screen, info);
7587ec681f3Smrg   if (!tmp) {
7597ec681f3Smrg      debug_printf("D3D12: failed to create stencil-resolve temp-resource\n");
7607ec681f3Smrg      return NULL;
7617ec681f3Smrg   }
7627ec681f3Smrg   assert(tmp->nr_samples < 2);
7637ec681f3Smrg
7647ec681f3Smrg   /* resolve stencil into tmp */
7657ec681f3Smrg   struct pipe_surface dst_tmpl;
7667ec681f3Smrg   util_blitter_default_dst_texture(&dst_tmpl, tmp, 0, 0);
7677ec681f3Smrg   dst_tmpl.format = tmp->format;
7687ec681f3Smrg   struct pipe_surface *dst_surf = pctx->create_surface(pctx, tmp, &dst_tmpl);
7697ec681f3Smrg   if (!dst_surf) {
7707ec681f3Smrg      debug_printf("D3D12: failed to create stencil-resolve dst-surface\n");
7717ec681f3Smrg      return NULL;
7727ec681f3Smrg   }
7737ec681f3Smrg
7747ec681f3Smrg   struct pipe_sampler_view src_templ, *src_view;
7757ec681f3Smrg   util_blitter_default_src_texture(ctx->blitter, &src_templ,
7767ec681f3Smrg                                    info->src.resource, info->src.level);
7777ec681f3Smrg   src_templ.format = util_format_stencil_only(info->src.format);
7787ec681f3Smrg   src_view = pctx->create_sampler_view(pctx, info->src.resource, &src_templ);
7797ec681f3Smrg
7807ec681f3Smrg   void *sampler_state = get_sampler_state(ctx);
7817ec681f3Smrg
7827ec681f3Smrg   util_blit_save_state(ctx);
7837ec681f3Smrg   pctx->set_sampler_views(pctx, PIPE_SHADER_FRAGMENT, 0, 1, 0, false, &src_view);
7847ec681f3Smrg   pctx->bind_sampler_states(pctx, PIPE_SHADER_FRAGMENT, 0, 1, &sampler_state);
7857ec681f3Smrg   util_blitter_custom_shader(ctx->blitter, dst_surf,
7867ec681f3Smrg                              get_stencil_resolve_vs(ctx),
7877ec681f3Smrg                              get_stencil_resolve_fs(ctx, info->src.box.height == info->dst.box.height));
7887ec681f3Smrg   util_blitter_restore_textures(ctx->blitter);
7897ec681f3Smrg   pipe_surface_reference(&dst_surf, NULL);
7907ec681f3Smrg   pipe_sampler_view_reference(&src_view, NULL);
7917ec681f3Smrg   return tmp;
7927ec681f3Smrg}
7937ec681f3Smrg
7947ec681f3Smrgstatic void
7957ec681f3Smrgblit_resolve_stencil(struct d3d12_context *ctx,
7967ec681f3Smrg                     const struct pipe_blit_info *info)
7977ec681f3Smrg{
7987ec681f3Smrg   assert(info->mask & PIPE_MASK_S);
7997ec681f3Smrg
8007ec681f3Smrg   if (D3D12_DEBUG_BLIT & d3d12_debug)
8017ec681f3Smrg      debug_printf("D3D12 BLIT: blit_resolve_stencil\n");
8027ec681f3Smrg
8037ec681f3Smrg   if (info->mask & PIPE_MASK_Z) {
8047ec681f3Smrg      /* resolve depth into dst */
8057ec681f3Smrg      struct pipe_blit_info new_info = *info;
8067ec681f3Smrg      new_info.mask = PIPE_MASK_Z;
8077ec681f3Smrg
8087ec681f3Smrg      if (resolve_supported(&new_info))
8097ec681f3Smrg         blit_resolve(ctx, &new_info);
8107ec681f3Smrg      else
8117ec681f3Smrg         util_blit(ctx, &new_info);
8127ec681f3Smrg   }
8137ec681f3Smrg
8147ec681f3Smrg   struct pipe_resource *tmp = resolve_stencil_to_temp(ctx, info);
8157ec681f3Smrg
8167ec681f3Smrg
8177ec681f3Smrg   /* copy resolved stencil into dst */
8187ec681f3Smrg   struct d3d12_resource *dst = d3d12_resource(info->dst.resource);
8197ec681f3Smrg   d3d12_transition_subresources_state(ctx, d3d12_resource(tmp),
8207ec681f3Smrg                                       0, 1, 0, 1, 0, 1,
8217ec681f3Smrg                                       D3D12_RESOURCE_STATE_COPY_SOURCE,
8227ec681f3Smrg                                       D3D12_BIND_INVALIDATE_NONE);
8237ec681f3Smrg   d3d12_transition_subresources_state(ctx, dst,
8247ec681f3Smrg                                       0, 1, 0, 1, 1, 1,
8257ec681f3Smrg                                       D3D12_RESOURCE_STATE_COPY_DEST,
8267ec681f3Smrg                                       D3D12_BIND_INVALIDATE_FULL);
8277ec681f3Smrg   d3d12_apply_resource_states(ctx);
8287ec681f3Smrg
8297ec681f3Smrg   struct d3d12_batch *batch = d3d12_current_batch(ctx);
8307ec681f3Smrg   d3d12_batch_reference_resource(batch, d3d12_resource(tmp));
8317ec681f3Smrg   d3d12_batch_reference_resource(batch, dst);
8327ec681f3Smrg
8337ec681f3Smrg   D3D12_BOX src_box;
8347ec681f3Smrg   src_box.left = src_box.top = src_box.front = 0;
8357ec681f3Smrg   src_box.right = tmp->width0;
8367ec681f3Smrg   src_box.bottom = tmp->height0;
8377ec681f3Smrg   src_box.back = tmp->depth0;
8387ec681f3Smrg
8397ec681f3Smrg   D3D12_TEXTURE_COPY_LOCATION src_loc;
8407ec681f3Smrg   src_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
8417ec681f3Smrg   src_loc.SubresourceIndex = 0;
8427ec681f3Smrg   src_loc.pResource = d3d12_resource_resource(d3d12_resource(tmp));
8437ec681f3Smrg
8447ec681f3Smrg   D3D12_TEXTURE_COPY_LOCATION dst_loc;
8457ec681f3Smrg   dst_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
8467ec681f3Smrg   dst_loc.SubresourceIndex = 1;
8477ec681f3Smrg   dst_loc.pResource = d3d12_resource_resource(dst);
8487ec681f3Smrg
8497ec681f3Smrg   ctx->cmdlist->CopyTextureRegion(&dst_loc, info->dst.box.x,
8507ec681f3Smrg                                   info->dst.box.y, info->dst.box.z,
8517ec681f3Smrg                                   &src_loc, &src_box);
8527ec681f3Smrg
8537ec681f3Smrg   pipe_resource_reference(&tmp, NULL);
8547ec681f3Smrg}
8557ec681f3Smrg
8567ec681f3Smrgstatic bool
8577ec681f3Smrgreplicate_stencil_supported(struct d3d12_context *ctx,
8587ec681f3Smrg                            const struct pipe_blit_info *info)
8597ec681f3Smrg{
8607ec681f3Smrg   if (!util_format_is_depth_or_stencil(info->src.format) ||
8617ec681f3Smrg       !(info->mask & PIPE_MASK_S))
8627ec681f3Smrg      return false;
8637ec681f3Smrg
8647ec681f3Smrg   if (info->mask & PIPE_MASK_Z) {
8657ec681f3Smrg      struct pipe_blit_info new_info = *info;
8667ec681f3Smrg      new_info.mask = PIPE_MASK_Z;
8677ec681f3Smrg      if (!util_blitter_is_blit_supported(ctx->blitter, &new_info))
8687ec681f3Smrg         return false;
8697ec681f3Smrg   }
8707ec681f3Smrg
8717ec681f3Smrg   return true;
8727ec681f3Smrg}
8737ec681f3Smrg
8747ec681f3Smrgstatic void
8757ec681f3Smrgblit_replicate_stencil(struct d3d12_context *ctx,
8767ec681f3Smrg                       const struct pipe_blit_info *info)
8777ec681f3Smrg{
8787ec681f3Smrg   assert(info->mask & PIPE_MASK_S);
8797ec681f3Smrg
8807ec681f3Smrg   if (D3D12_DEBUG_BLIT & d3d12_debug)
8817ec681f3Smrg      debug_printf("D3D12 BLIT: blit_replicate_stencil\n");
8827ec681f3Smrg
8837ec681f3Smrg   if (info->mask & PIPE_MASK_Z) {
8847ec681f3Smrg      /* resolve depth into dst */
8857ec681f3Smrg      struct pipe_blit_info new_info = *info;
8867ec681f3Smrg      new_info.mask = PIPE_MASK_Z;
8877ec681f3Smrg      util_blit(ctx, &new_info);
8887ec681f3Smrg   }
8897ec681f3Smrg
8907ec681f3Smrg   util_blit_save_state(ctx);
8917ec681f3Smrg   util_blitter_stencil_fallback(ctx->blitter, info->dst.resource,
8927ec681f3Smrg                                 info->dst.level,
8937ec681f3Smrg                                 &info->dst.box,
8947ec681f3Smrg                                 info->src.resource,
8957ec681f3Smrg                                 info->src.level,
8967ec681f3Smrg                                 &info->src.box,
8977ec681f3Smrg                                 info->scissor_enable ? &info->scissor : NULL);
8987ec681f3Smrg}
8997ec681f3Smrg
9007ec681f3Smrgvoid
9017ec681f3Smrgd3d12_blit(struct pipe_context *pctx,
9027ec681f3Smrg           const struct pipe_blit_info *info)
9037ec681f3Smrg{
9047ec681f3Smrg   struct d3d12_context *ctx = d3d12_context(pctx);
9057ec681f3Smrg
9067ec681f3Smrg   if (!info->render_condition_enable && ctx->current_predication) {
9077ec681f3Smrg      if (D3D12_DEBUG_BLIT & d3d12_debug)
9087ec681f3Smrg         debug_printf("D3D12 BLIT: Disable predication\n");
9097ec681f3Smrg      ctx->cmdlist->SetPredication(nullptr, 0, D3D12_PREDICATION_OP_EQUAL_ZERO);
9107ec681f3Smrg   }
9117ec681f3Smrg
9127ec681f3Smrg   if (D3D12_DEBUG_BLIT & d3d12_debug) {
9137ec681f3Smrg      debug_printf("D3D12 BLIT: from %s@%d msaa:%d %dx%dx%d + %dx%dx%d\n",
9147ec681f3Smrg                   util_format_name(info->src.format), info->src.level,
9157ec681f3Smrg                   info->src.resource->nr_samples,
9167ec681f3Smrg                   info->src.box.x, info->src.box.y, info->src.box.z,
9177ec681f3Smrg                   info->src.box.width, info->src.box.height, info->src.box.depth);
9187ec681f3Smrg      debug_printf("            to   %s@%d msaa:%d %dx%dx%d + %dx%dx%d ",
9197ec681f3Smrg                   util_format_name(info->dst.format), info->dst.level,
9207ec681f3Smrg                   info->dst.resource->nr_samples,
9217ec681f3Smrg                   info->dst.box.x, info->dst.box.y, info->dst.box.z,
9227ec681f3Smrg                   info->dst.box.width, info->dst.box.height, info->dst.box.depth);
9237ec681f3Smrg      debug_printf("| flags %s%s%s\n",
9247ec681f3Smrg                   info->render_condition_enable ? "cond " : "",
9257ec681f3Smrg                   info->scissor_enable ? "scissor " : "",
9267ec681f3Smrg                   info->alpha_blend ? "blend" : "");
9277ec681f3Smrg   }
9287ec681f3Smrg
9297ec681f3Smrg   if (is_same_resource(info))
9307ec681f3Smrg      blit_same_resource(ctx, info);
9317ec681f3Smrg   else if (is_resolve(info)) {
9327ec681f3Smrg      if (resolve_supported(info))
9337ec681f3Smrg         blit_resolve(ctx, info);
9347ec681f3Smrg      else if (util_blitter_is_blit_supported(ctx->blitter, info))
9357ec681f3Smrg         util_blit(ctx, info);
9367ec681f3Smrg      else if (resolve_stencil_supported(ctx, info))
9377ec681f3Smrg         blit_resolve_stencil(ctx, info);
9387ec681f3Smrg      else
9397ec681f3Smrg         debug_printf("D3D12: resolve unsupported %s -> %s\n",
9407ec681f3Smrg                    util_format_short_name(info->src.resource->format),
9417ec681f3Smrg                    util_format_short_name(info->dst.resource->format));
9427ec681f3Smrg   } else if (direct_copy_supported(d3d12_screen(pctx->screen), info,
9437ec681f3Smrg                                    ctx->current_predication != nullptr))
9447ec681f3Smrg      d3d12_direct_copy(ctx, d3d12_resource(info->dst.resource),
9457ec681f3Smrg                        info->dst.level, &info->dst.box,
9467ec681f3Smrg                        d3d12_resource(info->src.resource),
9477ec681f3Smrg                        info->src.level, &info->src.box, info->mask);
9487ec681f3Smrg   else if (util_blitter_is_blit_supported(ctx->blitter, info))
9497ec681f3Smrg      util_blit(ctx, info);
9507ec681f3Smrg   else if (replicate_stencil_supported(ctx, info))
9517ec681f3Smrg      blit_replicate_stencil(ctx, info);
9527ec681f3Smrg   else
9537ec681f3Smrg      debug_printf("D3D12: blit unsupported %s -> %s\n",
9547ec681f3Smrg                 util_format_short_name(info->src.resource->format),
9557ec681f3Smrg                 util_format_short_name(info->dst.resource->format));
9567ec681f3Smrg
9577ec681f3Smrg   if (!info->render_condition_enable && ctx->current_predication) {
9587ec681f3Smrg      ctx->cmdlist->SetPredication(
9597ec681f3Smrg               d3d12_resource_resource(ctx->current_predication), 0, D3D12_PREDICATION_OP_EQUAL_ZERO);
9607ec681f3Smrg      if (D3D12_DEBUG_BLIT & d3d12_debug)
9617ec681f3Smrg         debug_printf("D3D12 BLIT: Re-enable predication\n");
9627ec681f3Smrg   }
9637ec681f3Smrg
9647ec681f3Smrg}
9657ec681f3Smrg
9667ec681f3Smrgstatic void
9677ec681f3Smrgd3d12_resource_copy_region(struct pipe_context *pctx,
9687ec681f3Smrg                           struct pipe_resource *pdst,
9697ec681f3Smrg                           unsigned dst_level,
9707ec681f3Smrg                           unsigned dstx, unsigned dsty, unsigned dstz,
9717ec681f3Smrg                           struct pipe_resource *psrc,
9727ec681f3Smrg                           unsigned src_level,
9737ec681f3Smrg                           const struct pipe_box *psrc_box)
9747ec681f3Smrg{
9757ec681f3Smrg   struct d3d12_context *ctx = d3d12_context(pctx);
9767ec681f3Smrg   struct d3d12_resource *dst = d3d12_resource(pdst);
9777ec681f3Smrg   struct d3d12_resource *src = d3d12_resource(psrc);
9787ec681f3Smrg   struct pipe_resource *staging_res = NULL;
9797ec681f3Smrg   const struct pipe_box *src_box = psrc_box;
9807ec681f3Smrg   struct pipe_box staging_box, dst_box;
9817ec681f3Smrg
9827ec681f3Smrg   if (D3D12_DEBUG_BLIT & d3d12_debug) {
9837ec681f3Smrg      debug_printf("D3D12 COPY: from %s@%d msaa:%d mips:%d %dx%dx%d + %dx%dx%d\n",
9847ec681f3Smrg                   util_format_name(psrc->format), src_level, psrc->nr_samples,
9857ec681f3Smrg                   psrc->last_level,
9867ec681f3Smrg                   psrc_box->x, psrc_box->y, psrc_box->z,
9877ec681f3Smrg                   psrc_box->width, psrc_box->height, psrc_box->depth);
9887ec681f3Smrg      debug_printf("            to   %s@%d msaa:%d mips:%d %dx%dx%d\n",
9897ec681f3Smrg                   util_format_name(pdst->format), dst_level, psrc->nr_samples,
9907ec681f3Smrg                   psrc->last_level, dstx, dsty, dstz);
9917ec681f3Smrg   }
9927ec681f3Smrg
9937ec681f3Smrg   /* Use an intermediate resource if copying from/to the same subresource */
9947ec681f3Smrg   if (d3d12_resource_resource(dst) == d3d12_resource_resource(src) && dst_level == src_level) {
9957ec681f3Smrg      staging_res = create_staging_resource(ctx, src, src_level, psrc_box, &staging_box, PIPE_MASK_RGBAZS);
9967ec681f3Smrg      src = d3d12_resource(staging_res);
9977ec681f3Smrg      src_level = 0;
9987ec681f3Smrg      src_box = &staging_box;
9997ec681f3Smrg   }
10007ec681f3Smrg
10017ec681f3Smrg   dst_box.x = dstx;
10027ec681f3Smrg   dst_box.y = dsty;
10037ec681f3Smrg   dst_box.z = dstz;
10047ec681f3Smrg   dst_box.width = psrc_box->width;
10057ec681f3Smrg   dst_box.height = psrc_box->height;
10067ec681f3Smrg
10077ec681f3Smrg   d3d12_direct_copy(ctx, dst, dst_level, &dst_box,
10087ec681f3Smrg                     src, src_level, src_box, PIPE_MASK_RGBAZS);
10097ec681f3Smrg
10107ec681f3Smrg   if (staging_res)
10117ec681f3Smrg      pipe_resource_reference(&staging_res, NULL);
10127ec681f3Smrg}
10137ec681f3Smrg
10147ec681f3Smrgvoid
10157ec681f3Smrgd3d12_context_blit_init(struct pipe_context *ctx)
10167ec681f3Smrg{
10177ec681f3Smrg   ctx->resource_copy_region = d3d12_resource_copy_region;
10187ec681f3Smrg   ctx->blit = d3d12_blit;
10197ec681f3Smrg}
1020