Path: blob/21.2-virgl/src/gallium/drivers/zink/zink_blit.c
4570 views
#include "zink_context.h"1#include "zink_helpers.h"2#include "zink_query.h"3#include "zink_resource.h"4#include "zink_screen.h"56#include "util/u_blitter.h"7#include "util/u_rect.h"8#include "util/u_surface.h"9#include "util/format/u_format.h"1011static void12apply_dst_clears(struct zink_context *ctx, const struct pipe_blit_info *info, bool discard_only)13{14if (info->scissor_enable) {15struct u_rect rect = { info->scissor.minx, info->scissor.maxx,16info->scissor.miny, info->scissor.maxy };17zink_fb_clears_apply_or_discard(ctx, info->dst.resource, rect, discard_only);18} else19zink_fb_clears_apply_or_discard(ctx, info->dst.resource, zink_rect_from_box(&info->dst.box), discard_only);20}2122static bool23blit_resolve(struct zink_context *ctx, const struct pipe_blit_info *info)24{25if (util_format_get_mask(info->dst.format) != info->mask ||26util_format_get_mask(info->src.format) != info->mask ||27util_format_is_depth_or_stencil(info->dst.format) ||28info->scissor_enable ||29info->alpha_blend)30return false;3132if (info->src.box.width != info->dst.box.width ||33info->src.box.height != info->dst.box.height ||34info->src.box.depth != info->dst.box.depth)35return false;3637if (info->render_condition_enable &&38ctx->render_condition_active)39return false;4041struct zink_resource *src = zink_resource(info->src.resource);42struct zink_resource *dst = zink_resource(info->dst.resource);4344struct zink_screen *screen = zink_screen(ctx->base.screen);45if (src->format != zink_get_format(screen, info->src.format) ||46dst->format != zink_get_format(screen, info->dst.format))47return false;48if (info->dst.resource->target == PIPE_BUFFER)49util_range_add(info->dst.resource, &dst->valid_buffer_range,50info->dst.box.x, info->dst.box.x + info->dst.box.width);5152apply_dst_clears(ctx, info, false);53zink_fb_clears_apply_region(ctx, info->src.resource, zink_rect_from_box(&info->src.box));54struct zink_batch *batch = zink_batch_no_rp(ctx);5556zink_batch_reference_resource_rw(batch, src, false);57zink_batch_reference_resource_rw(batch, dst, true);5859zink_resource_setup_transfer_layouts(ctx, src, dst);6061VkImageResolve region = {0};6263region.srcSubresource.aspectMask = src->aspect;64region.srcSubresource.mipLevel = info->src.level;65region.srcOffset.x = info->src.box.x;66region.srcOffset.y = info->src.box.y;6768if (src->base.b.array_size > 1) {69region.srcOffset.z = 0;70region.srcSubresource.baseArrayLayer = info->src.box.z;71region.srcSubresource.layerCount = info->src.box.depth;72} else {73assert(info->src.box.depth == 1);74region.srcOffset.z = info->src.box.z;75region.srcSubresource.baseArrayLayer = 0;76region.srcSubresource.layerCount = 1;77}7879region.dstSubresource.aspectMask = dst->aspect;80region.dstSubresource.mipLevel = info->dst.level;81region.dstOffset.x = info->dst.box.x;82region.dstOffset.y = info->dst.box.y;8384if (dst->base.b.array_size > 1) {85region.dstOffset.z = 0;86region.dstSubresource.baseArrayLayer = info->dst.box.z;87region.dstSubresource.layerCount = info->dst.box.depth;88} else {89assert(info->dst.box.depth == 1);90region.dstOffset.z = info->dst.box.z;91region.dstSubresource.baseArrayLayer = 0;92region.dstSubresource.layerCount = 1;93}9495region.extent.width = info->dst.box.width;96region.extent.height = info->dst.box.height;97region.extent.depth = info->dst.box.depth;98vkCmdResolveImage(batch->state->cmdbuf, src->obj->image, src->layout,99dst->obj->image, dst->layout,1001, ®ion);101102return true;103}104105static VkFormatFeatureFlags106get_resource_features(struct zink_screen *screen, struct zink_resource *res)107{108VkFormatProperties props = screen->format_props[res->base.b.format];109return res->optimal_tiling ? props.optimalTilingFeatures :110props.linearTilingFeatures;111}112113static bool114blit_native(struct zink_context *ctx, const struct pipe_blit_info *info)115{116if (util_format_get_mask(info->dst.format) != info->mask ||117util_format_get_mask(info->src.format) != info->mask ||118info->scissor_enable ||119info->alpha_blend)120return false;121122if (info->render_condition_enable &&123ctx->render_condition_active)124return false;125126if (util_format_is_depth_or_stencil(info->dst.format) &&127info->dst.format != info->src.format)128return false;129130/* vkCmdBlitImage must not be used for multisampled source or destination images. */131if (info->src.resource->nr_samples > 1 || info->dst.resource->nr_samples > 1)132return false;133134struct zink_resource *src = zink_resource(info->src.resource);135struct zink_resource *dst = zink_resource(info->dst.resource);136137struct zink_screen *screen = zink_screen(ctx->base.screen);138if (src->format != zink_get_format(screen, info->src.format) ||139dst->format != zink_get_format(screen, info->dst.format))140return false;141142if (!(get_resource_features(screen, src) & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ||143!(get_resource_features(screen, dst) & VK_FORMAT_FEATURE_BLIT_DST_BIT))144return false;145146if ((util_format_is_pure_sint(info->src.format) !=147util_format_is_pure_sint(info->dst.format)) ||148(util_format_is_pure_uint(info->src.format) !=149util_format_is_pure_uint(info->dst.format)))150return false;151152if (info->filter == PIPE_TEX_FILTER_LINEAR &&153!(get_resource_features(screen, src) &154VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT))155return false;156157apply_dst_clears(ctx, info, false);158zink_fb_clears_apply_region(ctx, info->src.resource, zink_rect_from_box(&info->src.box));159struct zink_batch *batch = zink_batch_no_rp(ctx);160zink_batch_reference_resource_rw(batch, src, false);161zink_batch_reference_resource_rw(batch, dst, true);162163zink_resource_setup_transfer_layouts(ctx, src, dst);164if (info->dst.resource->target == PIPE_BUFFER)165util_range_add(info->dst.resource, &dst->valid_buffer_range,166info->dst.box.x, info->dst.box.x + info->dst.box.width);167VkImageBlit region = {0};168region.srcSubresource.aspectMask = src->aspect;169region.srcSubresource.mipLevel = info->src.level;170region.srcOffsets[0].x = info->src.box.x;171region.srcOffsets[0].y = info->src.box.y;172region.srcOffsets[1].x = info->src.box.x + info->src.box.width;173region.srcOffsets[1].y = info->src.box.y + info->src.box.height;174175switch (src->base.b.target) {176case PIPE_TEXTURE_CUBE:177case PIPE_TEXTURE_CUBE_ARRAY:178case PIPE_TEXTURE_2D_ARRAY:179case PIPE_TEXTURE_1D_ARRAY:180/* these use layer */181region.srcSubresource.baseArrayLayer = info->src.box.z;182region.srcSubresource.layerCount = info->src.box.depth;183region.srcOffsets[0].z = 0;184region.srcOffsets[1].z = 1;185break;186case PIPE_TEXTURE_3D:187/* this uses depth */188region.srcSubresource.baseArrayLayer = 0;189region.srcSubresource.layerCount = 1;190region.srcOffsets[0].z = info->src.box.z;191region.srcOffsets[1].z = info->src.box.z + info->src.box.depth;192break;193default:194/* these must only copy one layer */195region.srcSubresource.baseArrayLayer = 0;196region.srcSubresource.layerCount = 1;197region.srcOffsets[0].z = 0;198region.srcOffsets[1].z = 1;199}200201region.dstSubresource.aspectMask = dst->aspect;202region.dstSubresource.mipLevel = info->dst.level;203region.dstOffsets[0].x = info->dst.box.x;204region.dstOffsets[0].y = info->dst.box.y;205region.dstOffsets[1].x = info->dst.box.x + info->dst.box.width;206region.dstOffsets[1].y = info->dst.box.y + info->dst.box.height;207assert(region.dstOffsets[0].x != region.dstOffsets[1].x);208assert(region.dstOffsets[0].y != region.dstOffsets[1].y);209210switch (dst->base.b.target) {211case PIPE_TEXTURE_CUBE:212case PIPE_TEXTURE_CUBE_ARRAY:213case PIPE_TEXTURE_2D_ARRAY:214case PIPE_TEXTURE_1D_ARRAY:215/* these use layer */216region.dstSubresource.baseArrayLayer = info->dst.box.z;217region.dstSubresource.layerCount = info->dst.box.depth;218region.dstOffsets[0].z = 0;219region.dstOffsets[1].z = 1;220break;221case PIPE_TEXTURE_3D:222/* this uses depth */223region.dstSubresource.baseArrayLayer = 0;224region.dstSubresource.layerCount = 1;225region.dstOffsets[0].z = info->dst.box.z;226region.dstOffsets[1].z = info->dst.box.z + info->dst.box.depth;227break;228default:229/* these must only copy one layer */230region.dstSubresource.baseArrayLayer = 0;231region.dstSubresource.layerCount = 1;232region.dstOffsets[0].z = 0;233region.dstOffsets[1].z = 1;234}235assert(region.dstOffsets[0].z != region.dstOffsets[1].z);236237vkCmdBlitImage(batch->state->cmdbuf, src->obj->image, src->layout,238dst->obj->image, dst->layout,2391, ®ion,240zink_filter(info->filter));241242return true;243}244245void246zink_blit(struct pipe_context *pctx,247const struct pipe_blit_info *info)248{249struct zink_context *ctx = zink_context(pctx);250const struct util_format_description *src_desc = util_format_description(info->src.format);251const struct util_format_description *dst_desc = util_format_description(info->dst.format);252if (src_desc == dst_desc ||253src_desc->nr_channels != 4 || src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||254(src_desc->nr_channels == 4 && src_desc->channel[3].type != UTIL_FORMAT_TYPE_VOID)) {255/* we can't blit RGBX -> RGBA formats directly since they're emulated256* so we have to use sampler views257*/258if (info->src.resource->nr_samples > 1 &&259info->dst.resource->nr_samples <= 1) {260if (blit_resolve(ctx, info))261return;262} else {263if (blit_native(ctx, info))264return;265}266}267268struct zink_resource *src = zink_resource(info->src.resource);269struct zink_resource *dst = zink_resource(info->dst.resource);270/* if we're copying between resources with matching aspects then we can probably just copy_region */271if (src->aspect == dst->aspect) {272struct pipe_blit_info new_info = *info;273274if (src->aspect & VK_IMAGE_ASPECT_STENCIL_BIT &&275new_info.render_condition_enable &&276!ctx->render_condition_active)277new_info.render_condition_enable = false;278279if (util_try_blit_via_copy_region(pctx, &new_info))280return;281}282283if (!util_blitter_is_blit_supported(ctx->blitter, info)) {284debug_printf("blit unsupported %s -> %s\n",285util_format_short_name(info->src.resource->format),286util_format_short_name(info->dst.resource->format));287return;288}289290/* this is discard_only because we're about to start a renderpass that will291* flush all pending clears anyway292*/293apply_dst_clears(ctx, info, true);294295if (info->dst.resource->target == PIPE_BUFFER)296util_range_add(info->dst.resource, &dst->valid_buffer_range,297info->dst.box.x, info->dst.box.x + info->dst.box.width);298zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS | ZINK_BLIT_SAVE_TEXTURES);299300util_blitter_blit(ctx->blitter, info);301}302303/* similar to radeonsi */304void305zink_blit_begin(struct zink_context *ctx, enum zink_blit_flags flags)306{307util_blitter_save_vertex_elements(ctx->blitter, ctx->element_state);308util_blitter_save_viewport(ctx->blitter, ctx->vp_state.viewport_states);309310util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vertex_buffers);311util_blitter_save_vertex_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_VERTEX]);312util_blitter_save_tessctrl_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_TESS_CTRL]);313util_blitter_save_tesseval_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]);314util_blitter_save_geometry_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_GEOMETRY]);315util_blitter_save_rasterizer(ctx->blitter, ctx->rast_state);316util_blitter_save_so_targets(ctx->blitter, ctx->num_so_targets, ctx->so_targets);317318if (flags & ZINK_BLIT_SAVE_FS) {319util_blitter_save_fragment_constant_buffer_slot(ctx->blitter, ctx->ubos[PIPE_SHADER_FRAGMENT]);320util_blitter_save_blend(ctx->blitter, ctx->gfx_pipeline_state.blend_state);321util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->dsa_state);322util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);323util_blitter_save_sample_mask(ctx->blitter, ctx->gfx_pipeline_state.sample_mask);324util_blitter_save_scissor(ctx->blitter, ctx->vp_state.scissor_states);325/* also util_blitter_save_window_rectangles when we have that? */326327util_blitter_save_fragment_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_FRAGMENT]);328}329330if (flags & ZINK_BLIT_SAVE_FB)331util_blitter_save_framebuffer(ctx->blitter, &ctx->fb_state);332333334if (flags & ZINK_BLIT_SAVE_TEXTURES) {335util_blitter_save_fragment_sampler_states(ctx->blitter,336ctx->di.num_samplers[PIPE_SHADER_FRAGMENT],337(void**)ctx->sampler_states[PIPE_SHADER_FRAGMENT]);338util_blitter_save_fragment_sampler_views(ctx->blitter,339ctx->di.num_sampler_views[PIPE_SHADER_FRAGMENT],340ctx->sampler_views[PIPE_SHADER_FRAGMENT]);341}342343if (flags & ZINK_BLIT_NO_COND_RENDER && ctx->render_condition_active)344zink_stop_conditional_render(ctx);345}346347bool348zink_blit_region_fills(struct u_rect region, unsigned width, unsigned height)349{350struct u_rect intersect = {0, width, 0, height};351352if (!u_rect_test_intersection(®ion, &intersect))353/* is this even a thing? */354return false;355356u_rect_find_intersection(®ion, &intersect);357if (intersect.x0 != 0 || intersect.y0 != 0 ||358intersect.x1 != width || intersect.y1 != height)359return false;360361return true;362}363364bool365zink_blit_region_covers(struct u_rect region, struct u_rect covers)366{367struct u_rect intersect;368if (!u_rect_test_intersection(®ion, &covers))369return false;370371u_rect_union(&intersect, ®ion, &covers);372return intersect.x0 == covers.x0 && intersect.y0 == covers.y0 &&373intersect.x1 == covers.x1 && intersect.y1 == covers.y1;374}375376377