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 ©_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, ©_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