1 #include "zink_context.h"
2 #include "zink_helpers.h"
3 #include "zink_query.h"
4 #include "zink_resource.h"
5 #include "zink_screen.h"
6 
7 #include "util/u_blitter.h"
8 #include "util/u_rect.h"
9 #include "util/u_surface.h"
10 #include "util/format/u_format.h"
11 
12 static void
apply_dst_clears(struct zink_context * ctx,const struct pipe_blit_info * info,bool discard_only)13 apply_dst_clears(struct zink_context *ctx, const struct pipe_blit_info *info, bool discard_only)
14 {
15    if (info->scissor_enable) {
16       struct u_rect rect = { info->scissor.minx, info->scissor.maxx,
17                              info->scissor.miny, info->scissor.maxy };
18       zink_fb_clears_apply_or_discard(ctx, info->dst.resource, rect, discard_only);
19    } else
20       zink_fb_clears_apply_or_discard(ctx, info->dst.resource, zink_rect_from_box(&info->dst.box), discard_only);
21 }
22 
23 static bool
blit_resolve(struct zink_context * ctx,const struct pipe_blit_info * info)24 blit_resolve(struct zink_context *ctx, const struct pipe_blit_info *info)
25 {
26    if (util_format_get_mask(info->dst.format) != info->mask ||
27        util_format_get_mask(info->src.format) != info->mask ||
28        util_format_is_depth_or_stencil(info->dst.format) ||
29        info->scissor_enable ||
30        info->alpha_blend)
31       return false;
32 
33    if (info->src.box.width != info->dst.box.width ||
34        info->src.box.height != info->dst.box.height ||
35        info->src.box.depth != info->dst.box.depth)
36       return false;
37 
38    if (info->render_condition_enable &&
39        ctx->render_condition_active)
40       return false;
41 
42    struct zink_resource *src = zink_resource(info->src.resource);
43    struct zink_resource *dst = zink_resource(info->dst.resource);
44 
45    struct zink_screen *screen = zink_screen(ctx->base.screen);
46    if (src->format != zink_get_format(screen, info->src.format) ||
47        dst->format != zink_get_format(screen, info->dst.format))
48       return false;
49    if (info->dst.resource->target == PIPE_BUFFER)
50       util_range_add(info->dst.resource, &dst->valid_buffer_range,
51                      info->dst.box.x, info->dst.box.x + info->dst.box.width);
52 
53    apply_dst_clears(ctx, info, false);
54    zink_fb_clears_apply_region(ctx, info->src.resource, zink_rect_from_box(&info->src.box));
55 
56    struct zink_batch *batch = &ctx->batch;
57    zink_batch_no_rp(ctx);
58    zink_batch_reference_resource_rw(batch, src, false);
59    zink_batch_reference_resource_rw(batch, dst, true);
60 
61    zink_resource_setup_transfer_layouts(ctx, src, dst);
62 
63    VkImageResolve region = {0};
64 
65    region.srcSubresource.aspectMask = src->aspect;
66    region.srcSubresource.mipLevel = info->src.level;
67    region.srcOffset.x = info->src.box.x;
68    region.srcOffset.y = info->src.box.y;
69 
70    if (src->base.b.array_size > 1) {
71       region.srcOffset.z = 0;
72       region.srcSubresource.baseArrayLayer = info->src.box.z;
73       region.srcSubresource.layerCount = info->src.box.depth;
74    } else {
75       assert(info->src.box.depth == 1);
76       region.srcOffset.z = info->src.box.z;
77       region.srcSubresource.baseArrayLayer = 0;
78       region.srcSubresource.layerCount = 1;
79    }
80 
81    region.dstSubresource.aspectMask = dst->aspect;
82    region.dstSubresource.mipLevel = info->dst.level;
83    region.dstOffset.x = info->dst.box.x;
84    region.dstOffset.y = info->dst.box.y;
85 
86    if (dst->base.b.array_size > 1) {
87       region.dstOffset.z = 0;
88       region.dstSubresource.baseArrayLayer = info->dst.box.z;
89       region.dstSubresource.layerCount = info->dst.box.depth;
90    } else {
91       assert(info->dst.box.depth == 1);
92       region.dstOffset.z = info->dst.box.z;
93       region.dstSubresource.baseArrayLayer = 0;
94       region.dstSubresource.layerCount = 1;
95    }
96 
97    region.extent.width = info->dst.box.width;
98    region.extent.height = info->dst.box.height;
99    region.extent.depth = info->dst.box.depth;
100    VKCTX(CmdResolveImage)(batch->state->cmdbuf, src->obj->image, src->layout,
101                      dst->obj->image, dst->layout,
102                      1, &region);
103 
104    return true;
105 }
106 
107 static VkFormatFeatureFlags
get_resource_features(struct zink_screen * screen,struct zink_resource * res)108 get_resource_features(struct zink_screen *screen, struct zink_resource *res)
109 {
110    VkFormatProperties props = screen->format_props[res->base.b.format];
111    return res->optimal_tiling ? props.optimalTilingFeatures :
112                                 props.linearTilingFeatures;
113 }
114 
115 static bool
blit_native(struct zink_context * ctx,const struct pipe_blit_info * info)116 blit_native(struct zink_context *ctx, const struct pipe_blit_info *info)
117 {
118    if (util_format_get_mask(info->dst.format) != info->mask ||
119        util_format_get_mask(info->src.format) != info->mask ||
120        info->scissor_enable ||
121        info->alpha_blend)
122       return false;
123 
124    if (info->render_condition_enable &&
125        ctx->render_condition_active)
126       return false;
127 
128    if (util_format_is_depth_or_stencil(info->dst.format) &&
129        info->dst.format != info->src.format)
130       return false;
131 
132    /* vkCmdBlitImage must not be used for multisampled source or destination images. */
133    if (info->src.resource->nr_samples > 1 || info->dst.resource->nr_samples > 1)
134       return false;
135 
136    struct zink_resource *src = zink_resource(info->src.resource);
137    struct zink_resource *dst = zink_resource(info->dst.resource);
138 
139    struct zink_screen *screen = zink_screen(ctx->base.screen);
140    if (src->format != zink_get_format(screen, info->src.format) ||
141        dst->format != zink_get_format(screen, info->dst.format))
142       return false;
143 
144    if (!(get_resource_features(screen, src) & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ||
145        !(get_resource_features(screen, dst) & VK_FORMAT_FEATURE_BLIT_DST_BIT))
146       return false;
147 
148    if ((util_format_is_pure_sint(info->src.format) !=
149         util_format_is_pure_sint(info->dst.format)) ||
150        (util_format_is_pure_uint(info->src.format) !=
151         util_format_is_pure_uint(info->dst.format)))
152       return false;
153 
154    if (info->filter == PIPE_TEX_FILTER_LINEAR &&
155        !(get_resource_features(screen, src) &
156           VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT))
157       return false;
158 
159    apply_dst_clears(ctx, info, false);
160    zink_fb_clears_apply_region(ctx, info->src.resource, zink_rect_from_box(&info->src.box));
161 
162    struct zink_batch *batch = &ctx->batch;
163    zink_batch_no_rp(ctx);
164    zink_batch_reference_resource_rw(batch, src, false);
165    zink_batch_reference_resource_rw(batch, dst, true);
166 
167    zink_resource_setup_transfer_layouts(ctx, src, dst);
168    if (info->dst.resource->target == PIPE_BUFFER)
169       util_range_add(info->dst.resource, &dst->valid_buffer_range,
170                      info->dst.box.x, info->dst.box.x + info->dst.box.width);
171    VkImageBlit region = {0};
172    region.srcSubresource.aspectMask = src->aspect;
173    region.srcSubresource.mipLevel = info->src.level;
174    region.srcOffsets[0].x = info->src.box.x;
175    region.srcOffsets[0].y = info->src.box.y;
176    region.srcOffsets[1].x = info->src.box.x + info->src.box.width;
177    region.srcOffsets[1].y = info->src.box.y + info->src.box.height;
178 
179    switch (src->base.b.target) {
180    case PIPE_TEXTURE_CUBE:
181    case PIPE_TEXTURE_CUBE_ARRAY:
182    case PIPE_TEXTURE_2D_ARRAY:
183    case PIPE_TEXTURE_1D_ARRAY:
184       /* these use layer */
185       region.srcSubresource.baseArrayLayer = info->src.box.z;
186       region.srcSubresource.layerCount = info->src.box.depth;
187       region.srcOffsets[0].z = 0;
188       region.srcOffsets[1].z = 1;
189       break;
190    case PIPE_TEXTURE_3D:
191       /* this uses depth */
192       region.srcSubresource.baseArrayLayer = 0;
193       region.srcSubresource.layerCount = 1;
194       region.srcOffsets[0].z = info->src.box.z;
195       region.srcOffsets[1].z = info->src.box.z + info->src.box.depth;
196       break;
197    default:
198       /* these must only copy one layer */
199       region.srcSubresource.baseArrayLayer = 0;
200       region.srcSubresource.layerCount = 1;
201       region.srcOffsets[0].z = 0;
202       region.srcOffsets[1].z = 1;
203    }
204 
205    region.dstSubresource.aspectMask = dst->aspect;
206    region.dstSubresource.mipLevel = info->dst.level;
207    region.dstOffsets[0].x = info->dst.box.x;
208    region.dstOffsets[0].y = info->dst.box.y;
209    region.dstOffsets[1].x = info->dst.box.x + info->dst.box.width;
210    region.dstOffsets[1].y = info->dst.box.y + info->dst.box.height;
211    assert(region.dstOffsets[0].x != region.dstOffsets[1].x);
212    assert(region.dstOffsets[0].y != region.dstOffsets[1].y);
213 
214    switch (dst->base.b.target) {
215    case PIPE_TEXTURE_CUBE:
216    case PIPE_TEXTURE_CUBE_ARRAY:
217    case PIPE_TEXTURE_2D_ARRAY:
218    case PIPE_TEXTURE_1D_ARRAY:
219       /* these use layer */
220       region.dstSubresource.baseArrayLayer = info->dst.box.z;
221       region.dstSubresource.layerCount = info->dst.box.depth;
222       region.dstOffsets[0].z = 0;
223       region.dstOffsets[1].z = 1;
224       break;
225    case PIPE_TEXTURE_3D:
226       /* this uses depth */
227       region.dstSubresource.baseArrayLayer = 0;
228       region.dstSubresource.layerCount = 1;
229       region.dstOffsets[0].z = info->dst.box.z;
230       region.dstOffsets[1].z = info->dst.box.z + info->dst.box.depth;
231       break;
232    default:
233       /* these must only copy one layer */
234       region.dstSubresource.baseArrayLayer = 0;
235       region.dstSubresource.layerCount = 1;
236       region.dstOffsets[0].z = 0;
237       region.dstOffsets[1].z = 1;
238    }
239    assert(region.dstOffsets[0].z != region.dstOffsets[1].z);
240 
241    VKCTX(CmdBlitImage)(batch->state->cmdbuf, src->obj->image, src->layout,
242                   dst->obj->image, dst->layout,
243                   1, &region,
244                   zink_filter(info->filter));
245 
246    return true;
247 }
248 
249 void
zink_blit(struct pipe_context * pctx,const struct pipe_blit_info * info)250 zink_blit(struct pipe_context *pctx,
251           const struct pipe_blit_info *info)
252 {
253    struct zink_context *ctx = zink_context(pctx);
254    const struct util_format_description *src_desc = util_format_description(info->src.format);
255    const struct util_format_description *dst_desc = util_format_description(info->dst.format);
256 
257    if (info->render_condition_enable &&
258        unlikely(!zink_screen(pctx->screen)->info.have_EXT_conditional_rendering && !zink_check_conditional_render(ctx)))
259       return;
260 
261    if (src_desc == dst_desc ||
262        src_desc->nr_channels != 4 || src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
263        (src_desc->nr_channels == 4 && src_desc->channel[3].type != UTIL_FORMAT_TYPE_VOID)) {
264       /* we can't blit RGBX -> RGBA formats directly since they're emulated
265        * so we have to use sampler views
266        */
267       if (info->src.resource->nr_samples > 1 &&
268           info->dst.resource->nr_samples <= 1) {
269          if (blit_resolve(ctx, info))
270             return;
271       } else {
272          if (blit_native(ctx, info))
273             return;
274       }
275    }
276 
277    struct zink_resource *src = zink_resource(info->src.resource);
278    struct zink_resource *dst = zink_resource(info->dst.resource);
279    /* if we're copying between resources with matching aspects then we can probably just copy_region */
280    if (src->aspect == dst->aspect) {
281       struct pipe_blit_info new_info = *info;
282 
283       if (src->aspect & VK_IMAGE_ASPECT_STENCIL_BIT &&
284           new_info.render_condition_enable &&
285           !ctx->render_condition_active)
286          new_info.render_condition_enable = false;
287 
288       if (util_try_blit_via_copy_region(pctx, &new_info))
289          return;
290    }
291 
292    if (!util_blitter_is_blit_supported(ctx->blitter, info)) {
293       debug_printf("blit unsupported %s -> %s\n",
294               util_format_short_name(info->src.resource->format),
295               util_format_short_name(info->dst.resource->format));
296       return;
297    }
298 
299    /* this is discard_only because we're about to start a renderpass that will
300     * flush all pending clears anyway
301     */
302    apply_dst_clears(ctx, info, true);
303 
304    if (info->dst.resource->target == PIPE_BUFFER)
305       util_range_add(info->dst.resource, &dst->valid_buffer_range,
306                      info->dst.box.x, info->dst.box.x + info->dst.box.width);
307    zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS | ZINK_BLIT_SAVE_TEXTURES);
308 
309    util_blitter_blit(ctx->blitter, info);
310 }
311 
312 /* similar to radeonsi */
313 void
zink_blit_begin(struct zink_context * ctx,enum zink_blit_flags flags)314 zink_blit_begin(struct zink_context *ctx, enum zink_blit_flags flags)
315 {
316    util_blitter_save_vertex_elements(ctx->blitter, ctx->element_state);
317    util_blitter_save_viewport(ctx->blitter, ctx->vp_state.viewport_states);
318 
319    util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vertex_buffers);
320    util_blitter_save_vertex_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_VERTEX]);
321    util_blitter_save_tessctrl_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_TESS_CTRL]);
322    util_blitter_save_tesseval_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]);
323    util_blitter_save_geometry_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_GEOMETRY]);
324    util_blitter_save_rasterizer(ctx->blitter, ctx->rast_state);
325    util_blitter_save_so_targets(ctx->blitter, ctx->num_so_targets, ctx->so_targets);
326 
327    if (flags & ZINK_BLIT_SAVE_FS) {
328       util_blitter_save_fragment_constant_buffer_slot(ctx->blitter, ctx->ubos[PIPE_SHADER_FRAGMENT]);
329       util_blitter_save_blend(ctx->blitter, ctx->gfx_pipeline_state.blend_state);
330       util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->dsa_state);
331       util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
332       util_blitter_save_sample_mask(ctx->blitter, ctx->gfx_pipeline_state.sample_mask);
333       util_blitter_save_scissor(ctx->blitter, ctx->vp_state.scissor_states);
334       /* also util_blitter_save_window_rectangles when we have that? */
335 
336       util_blitter_save_fragment_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_FRAGMENT]);
337    }
338 
339    if (flags & ZINK_BLIT_SAVE_FB)
340       util_blitter_save_framebuffer(ctx->blitter, &ctx->fb_state);
341 
342 
343    if (flags & ZINK_BLIT_SAVE_TEXTURES) {
344       util_blitter_save_fragment_sampler_states(ctx->blitter,
345                                                 ctx->di.num_samplers[PIPE_SHADER_FRAGMENT],
346                                                 (void**)ctx->sampler_states[PIPE_SHADER_FRAGMENT]);
347       util_blitter_save_fragment_sampler_views(ctx->blitter,
348                                                ctx->di.num_sampler_views[PIPE_SHADER_FRAGMENT],
349                                                ctx->sampler_views[PIPE_SHADER_FRAGMENT]);
350    }
351 
352    if (flags & ZINK_BLIT_NO_COND_RENDER && ctx->render_condition_active)
353       zink_stop_conditional_render(ctx);
354 }
355 
356 bool
zink_blit_region_fills(struct u_rect region,unsigned width,unsigned height)357 zink_blit_region_fills(struct u_rect region, unsigned width, unsigned height)
358 {
359    struct u_rect intersect = {0, width, 0, height};
360    struct u_rect r = {
361       MIN2(region.x0, region.x1),
362       MAX2(region.x0, region.x1),
363       MIN2(region.y0, region.y1),
364       MAX2(region.y0, region.y1),
365    };
366 
367    if (!u_rect_test_intersection(&r, &intersect))
368       /* is this even a thing? */
369       return false;
370 
371    u_rect_find_intersection(&r, &intersect);
372    if (intersect.x0 != 0 || intersect.y0 != 0 ||
373        intersect.x1 != width || intersect.y1 != height)
374       return false;
375 
376    return true;
377 }
378 
379 bool
zink_blit_region_covers(struct u_rect region,struct u_rect covers)380 zink_blit_region_covers(struct u_rect region, struct u_rect covers)
381 {
382    struct u_rect r = {
383       MIN2(region.x0, region.x1),
384       MAX2(region.x0, region.x1),
385       MIN2(region.y0, region.y1),
386       MAX2(region.y0, region.y1),
387    };
388    struct u_rect c = {
389       MIN2(covers.x0, covers.x1),
390       MAX2(covers.x0, covers.x1),
391       MIN2(covers.y0, covers.y1),
392       MAX2(covers.y0, covers.y1),
393    };
394    struct u_rect intersect;
395    if (!u_rect_test_intersection(&r, &c))
396       return false;
397 
398     u_rect_union(&intersect, &r, &c);
399     return intersect.x0 == c.x0 && intersect.y0 == c.y0 &&
400            intersect.x1 == c.x1 && intersect.y1 == c.y1;
401 }
402