1 #include "zink_clear.h"
2 #include "zink_context.h"
3 #include "zink_format.h"
4 #include "zink_inlines.h"
5 #include "zink_kopper.h"
6 #include "zink_helpers.h"
7 #include "zink_query.h"
8 #include "zink_resource.h"
9 #include "zink_screen.h"
10
11 #include "util/u_blitter.h"
12 #include "util/u_rect.h"
13 #include "util/u_surface.h"
14 #include "util/format/u_format.h"
15
16 static void
apply_dst_clears(struct zink_context * ctx,const struct pipe_blit_info * info,bool discard_only)17 apply_dst_clears(struct zink_context *ctx, const struct pipe_blit_info *info, bool discard_only)
18 {
19 if (info->scissor_enable) {
20 struct u_rect rect = { info->scissor.minx, info->scissor.maxx,
21 info->scissor.miny, info->scissor.maxy };
22 zink_fb_clears_apply_or_discard(ctx, info->dst.resource, rect, discard_only);
23 } else
24 zink_fb_clears_apply_or_discard(ctx, info->dst.resource, zink_rect_from_box(&info->dst.box), discard_only);
25 }
26
27 static bool
blit_resolve(struct zink_context * ctx,const struct pipe_blit_info * info,bool * needs_present_readback)28 blit_resolve(struct zink_context *ctx, const struct pipe_blit_info *info, bool *needs_present_readback)
29 {
30 if (util_format_get_mask(info->dst.format) != info->mask ||
31 util_format_get_mask(info->src.format) != info->mask ||
32 util_format_is_depth_or_stencil(info->dst.format) ||
33 info->scissor_enable ||
34 info->alpha_blend)
35 return false;
36
37 if (info->src.box.width < 0 ||
38 info->dst.box.width < 0 ||
39 info->src.box.height < 0 ||
40 info->dst.box.height < 0 ||
41 info->src.box.depth < 0 ||
42 info->dst.box.depth < 0)
43 return false;
44 /* vulkan resolves can't downscale */
45 if (info->src.box.width > info->dst.box.width ||
46 info->src.box.height > info->dst.box.height ||
47 info->src.box.depth > info->dst.box.depth)
48 return false;
49
50 if (info->render_condition_enable &&
51 ctx->render_condition_active)
52 return false;
53
54 struct zink_resource *src = zink_resource(info->src.resource);
55 struct zink_resource *use_src = src;
56 struct zink_resource *dst = zink_resource(info->dst.resource);
57
58 struct zink_screen *screen = zink_screen(ctx->base.screen);
59 /* aliased/swizzled formats need u_blitter */
60 if (src->format != zink_get_format(screen, info->src.format) ||
61 dst->format != zink_get_format(screen, info->dst.format))
62 return false;
63 if (src->format != dst->format)
64 return false;
65
66
67 apply_dst_clears(ctx, info, false);
68 zink_fb_clears_apply_region(ctx, info->src.resource, zink_rect_from_box(&info->src.box));
69
70 if (src->obj->dt)
71 *needs_present_readback = zink_kopper_acquire_readback(ctx, src, &use_src);
72
73 struct zink_batch *batch = &ctx->batch;
74 zink_resource_setup_transfer_layouts(ctx, use_src, dst);
75 VkCommandBuffer cmdbuf = *needs_present_readback ?
76 ctx->batch.state->cmdbuf :
77 zink_get_cmdbuf(ctx, src, dst);
78 if (cmdbuf == ctx->batch.state->cmdbuf)
79 zink_flush_dgc_if_enabled(ctx);
80 zink_batch_reference_resource_rw(batch, use_src, false);
81 zink_batch_reference_resource_rw(batch, dst, true);
82
83 bool marker = zink_cmd_debug_marker_begin(ctx, cmdbuf, "blit_resolve(%s->%s, %dx%d->%dx%d)",
84 util_format_short_name(info->src.format),
85 util_format_short_name(info->src.format),
86 info->src.box.width, info->src.box.height,
87 info->dst.box.width, info->dst.box.height);
88 VkImageResolve region = {0};
89
90 region.srcSubresource.aspectMask = src->aspect;
91 region.srcSubresource.mipLevel = info->src.level;
92 region.srcOffset.x = info->src.box.x;
93 region.srcOffset.y = info->src.box.y;
94
95 if (src->base.b.array_size > 1) {
96 region.srcOffset.z = 0;
97 region.srcSubresource.baseArrayLayer = info->src.box.z;
98 region.srcSubresource.layerCount = info->src.box.depth;
99 } else {
100 assert(info->src.box.depth == 1);
101 region.srcOffset.z = info->src.box.z;
102 region.srcSubresource.baseArrayLayer = 0;
103 region.srcSubresource.layerCount = 1;
104 }
105
106 region.dstSubresource.aspectMask = dst->aspect;
107 region.dstSubresource.mipLevel = info->dst.level;
108 region.dstOffset.x = info->dst.box.x;
109 region.dstOffset.y = info->dst.box.y;
110
111 if (dst->base.b.array_size > 1) {
112 region.dstOffset.z = 0;
113 region.dstSubresource.baseArrayLayer = info->dst.box.z;
114 region.dstSubresource.layerCount = info->dst.box.depth;
115 } else {
116 assert(info->dst.box.depth == 1);
117 region.dstOffset.z = info->dst.box.z;
118 region.dstSubresource.baseArrayLayer = 0;
119 region.dstSubresource.layerCount = 1;
120 }
121
122 region.extent.width = info->dst.box.width;
123 region.extent.height = info->dst.box.height;
124 region.extent.depth = info->dst.box.depth;
125 if (region.srcOffset.x + region.extent.width >= u_minify(src->base.b.width0, region.srcSubresource.mipLevel))
126 region.extent.width = u_minify(src->base.b.width0, region.srcSubresource.mipLevel) - region.srcOffset.x;
127 if (region.dstOffset.x + region.extent.width >= u_minify(dst->base.b.width0, region.dstSubresource.mipLevel))
128 region.extent.width = u_minify(dst->base.b.width0, region.dstSubresource.mipLevel) - region.dstOffset.x;
129 if (region.srcOffset.y + region.extent.height >= u_minify(src->base.b.height0, region.srcSubresource.mipLevel))
130 region.extent.height = u_minify(src->base.b.height0, region.srcSubresource.mipLevel) - region.srcOffset.y;
131 if (region.dstOffset.y + region.extent.height >= u_minify(dst->base.b.height0, region.dstSubresource.mipLevel))
132 region.extent.height = u_minify(dst->base.b.height0, region.dstSubresource.mipLevel) - region.dstOffset.y;
133 if (region.srcOffset.z + region.extent.depth >= u_minify(src->base.b.depth0, region.srcSubresource.mipLevel))
134 region.extent.depth = u_minify(src->base.b.depth0, region.srcSubresource.mipLevel) - region.srcOffset.z;
135 if (region.dstOffset.z + region.extent.depth >= u_minify(dst->base.b.depth0, region.dstSubresource.mipLevel))
136 region.extent.depth = u_minify(dst->base.b.depth0, region.dstSubresource.mipLevel) - region.dstOffset.z;
137 VKCTX(CmdResolveImage)(cmdbuf, use_src->obj->image, src->layout,
138 dst->obj->image, dst->layout,
139 1, ®ion);
140 zink_cmd_debug_marker_end(ctx, cmdbuf, marker);
141
142 return true;
143 }
144
145 static bool
blit_native(struct zink_context * ctx,const struct pipe_blit_info * info,bool * needs_present_readback)146 blit_native(struct zink_context *ctx, const struct pipe_blit_info *info, bool *needs_present_readback)
147 {
148 if (util_format_get_mask(info->dst.format) != info->mask ||
149 util_format_get_mask(info->src.format) != info->mask ||
150 info->scissor_enable ||
151 info->alpha_blend)
152 return false;
153
154 if (info->render_condition_enable &&
155 ctx->render_condition_active)
156 return false;
157
158 if (util_format_is_depth_or_stencil(info->dst.format) &&
159 (info->dst.format != info->src.format || info->filter == PIPE_TEX_FILTER_LINEAR))
160 return false;
161
162 /* vkCmdBlitImage must not be used for multisampled source or destination images. */
163 if (info->src.resource->nr_samples > 1 || info->dst.resource->nr_samples > 1)
164 return false;
165
166 struct zink_resource *src = zink_resource(info->src.resource);
167 struct zink_resource *use_src = src;
168 struct zink_resource *dst = zink_resource(info->dst.resource);
169
170 struct zink_screen *screen = zink_screen(ctx->base.screen);
171 if (src->format != zink_get_format(screen, info->src.format) ||
172 dst->format != zink_get_format(screen, info->dst.format))
173 return false;
174 if (src->format != VK_FORMAT_A8_UNORM_KHR && zink_format_is_emulated_alpha(info->src.format))
175 return false;
176
177 if (!(src->obj->vkfeats & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ||
178 !(dst->obj->vkfeats & VK_FORMAT_FEATURE_BLIT_DST_BIT))
179 return false;
180
181 if ((util_format_is_pure_sint(info->src.format) !=
182 util_format_is_pure_sint(info->dst.format)) ||
183 (util_format_is_pure_uint(info->src.format) !=
184 util_format_is_pure_uint(info->dst.format)))
185 return false;
186
187 if (info->filter == PIPE_TEX_FILTER_LINEAR &&
188 !(src->obj->vkfeats & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT))
189 return false;
190
191
192 VkImageBlit region = {0};
193 region.srcSubresource.aspectMask = src->aspect;
194 region.srcSubresource.mipLevel = info->src.level;
195 region.srcOffsets[0].x = info->src.box.x;
196 region.srcOffsets[0].y = info->src.box.y;
197 region.srcOffsets[1].x = info->src.box.x + info->src.box.width;
198 region.srcOffsets[1].y = info->src.box.y + info->src.box.height;
199
200 enum pipe_texture_target src_target = src->base.b.target;
201 if (src->need_2D)
202 src_target = src_target == PIPE_TEXTURE_1D ? PIPE_TEXTURE_2D : PIPE_TEXTURE_2D_ARRAY;
203 switch (src_target) {
204 case PIPE_TEXTURE_CUBE:
205 case PIPE_TEXTURE_CUBE_ARRAY:
206 case PIPE_TEXTURE_2D_ARRAY:
207 case PIPE_TEXTURE_1D_ARRAY:
208 /* these use layer */
209 region.srcSubresource.baseArrayLayer = info->src.box.z;
210 /* VUID-vkCmdBlitImage-srcImage-00240 */
211 if (region.srcSubresource.baseArrayLayer && dst->base.b.target == PIPE_TEXTURE_3D)
212 return false;
213 region.srcSubresource.layerCount = info->src.box.depth;
214 region.srcOffsets[0].z = 0;
215 region.srcOffsets[1].z = 1;
216 break;
217 case PIPE_TEXTURE_3D:
218 /* this uses depth */
219 region.srcSubresource.baseArrayLayer = 0;
220 region.srcSubresource.layerCount = 1;
221 region.srcOffsets[0].z = info->src.box.z;
222 region.srcOffsets[1].z = info->src.box.z + info->src.box.depth;
223 break;
224 default:
225 /* these must only copy one layer */
226 region.srcSubresource.baseArrayLayer = 0;
227 region.srcSubresource.layerCount = 1;
228 region.srcOffsets[0].z = 0;
229 region.srcOffsets[1].z = 1;
230 }
231
232 region.dstSubresource.aspectMask = dst->aspect;
233 region.dstSubresource.mipLevel = info->dst.level;
234 region.dstOffsets[0].x = info->dst.box.x;
235 region.dstOffsets[0].y = info->dst.box.y;
236 region.dstOffsets[1].x = info->dst.box.x + info->dst.box.width;
237 region.dstOffsets[1].y = info->dst.box.y + info->dst.box.height;
238 assert(region.dstOffsets[0].x != region.dstOffsets[1].x);
239 assert(region.dstOffsets[0].y != region.dstOffsets[1].y);
240
241 enum pipe_texture_target dst_target = dst->base.b.target;
242 if (dst->need_2D)
243 dst_target = dst_target == PIPE_TEXTURE_1D ? PIPE_TEXTURE_2D : PIPE_TEXTURE_2D_ARRAY;
244 switch (dst_target) {
245 case PIPE_TEXTURE_CUBE:
246 case PIPE_TEXTURE_CUBE_ARRAY:
247 case PIPE_TEXTURE_2D_ARRAY:
248 case PIPE_TEXTURE_1D_ARRAY:
249 /* these use layer */
250 region.dstSubresource.baseArrayLayer = info->dst.box.z;
251 /* VUID-vkCmdBlitImage-srcImage-00240 */
252 if (region.dstSubresource.baseArrayLayer && src->base.b.target == PIPE_TEXTURE_3D)
253 return false;
254 region.dstSubresource.layerCount = info->dst.box.depth;
255 region.dstOffsets[0].z = 0;
256 region.dstOffsets[1].z = 1;
257 break;
258 case PIPE_TEXTURE_3D:
259 /* this uses depth */
260 region.dstSubresource.baseArrayLayer = 0;
261 region.dstSubresource.layerCount = 1;
262 region.dstOffsets[0].z = info->dst.box.z;
263 region.dstOffsets[1].z = info->dst.box.z + info->dst.box.depth;
264 break;
265 default:
266 /* these must only copy one layer */
267 region.dstSubresource.baseArrayLayer = 0;
268 region.dstSubresource.layerCount = 1;
269 region.dstOffsets[0].z = 0;
270 region.dstOffsets[1].z = 1;
271 }
272 assert(region.dstOffsets[0].z != region.dstOffsets[1].z);
273
274 apply_dst_clears(ctx, info, false);
275 zink_fb_clears_apply_region(ctx, info->src.resource, zink_rect_from_box(&info->src.box));
276
277 if (src->obj->dt)
278 *needs_present_readback = zink_kopper_acquire_readback(ctx, src, &use_src);
279
280 struct zink_batch *batch = &ctx->batch;
281 zink_resource_setup_transfer_layouts(ctx, use_src, dst);
282 VkCommandBuffer cmdbuf = *needs_present_readback ?
283 ctx->batch.state->cmdbuf :
284 zink_get_cmdbuf(ctx, src, dst);
285 if (cmdbuf == ctx->batch.state->cmdbuf)
286 zink_flush_dgc_if_enabled(ctx);
287 zink_batch_reference_resource_rw(batch, use_src, false);
288 zink_batch_reference_resource_rw(batch, dst, true);
289
290 bool marker = zink_cmd_debug_marker_begin(ctx, cmdbuf, "blit_native(%s->%s, %dx%d->%dx%d)",
291 util_format_short_name(info->src.format),
292 util_format_short_name(info->src.format),
293 info->src.box.width, info->src.box.height,
294 info->dst.box.width, info->dst.box.height);
295
296 VKCTX(CmdBlitImage)(cmdbuf, use_src->obj->image, src->layout,
297 dst->obj->image, dst->layout,
298 1, ®ion,
299 zink_filter(info->filter));
300
301 zink_cmd_debug_marker_end(ctx, cmdbuf, marker);
302
303 return true;
304 }
305
306 static bool
try_copy_region(struct pipe_context * pctx,const struct pipe_blit_info * info)307 try_copy_region(struct pipe_context *pctx, const struct pipe_blit_info *info)
308 {
309 struct zink_context *ctx = zink_context(pctx);
310 struct zink_resource *src = zink_resource(info->src.resource);
311 struct zink_resource *dst = zink_resource(info->dst.resource);
312 /* if we're copying between resources with matching aspects then we can probably just copy_region */
313 if (src->aspect != dst->aspect)
314 return false;
315 struct pipe_blit_info new_info = *info;
316
317 if (src->aspect & VK_IMAGE_ASPECT_STENCIL_BIT &&
318 new_info.render_condition_enable &&
319 !ctx->render_condition_active)
320 new_info.render_condition_enable = false;
321
322 return util_try_blit_via_copy_region(pctx, &new_info, ctx->render_condition_active);
323 }
324
325 void
zink_blit(struct pipe_context * pctx,const struct pipe_blit_info * info)326 zink_blit(struct pipe_context *pctx,
327 const struct pipe_blit_info *info)
328 {
329 struct zink_context *ctx = zink_context(pctx);
330 const struct util_format_description *src_desc = util_format_description(info->src.format);
331 const struct util_format_description *dst_desc = util_format_description(info->dst.format);
332
333 struct zink_resource *src = zink_resource(info->src.resource);
334 struct zink_resource *use_src = src;
335 struct zink_resource *dst = zink_resource(info->dst.resource);
336 bool needs_present_readback = false;
337 if (zink_is_swapchain(dst)) {
338 if (!zink_kopper_acquire(ctx, dst, UINT64_MAX))
339 return;
340 }
341
342 if (src_desc == dst_desc ||
343 src_desc->nr_channels != 4 || src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
344 (src_desc->nr_channels == 4 && src_desc->channel[3].type != UTIL_FORMAT_TYPE_VOID)) {
345 /* we can't blit RGBX -> RGBA formats directly since they're emulated
346 * so we have to use sampler views
347 */
348 if (info->src.resource->nr_samples > 1 &&
349 info->dst.resource->nr_samples <= 1) {
350 if (blit_resolve(ctx, info, &needs_present_readback))
351 goto end;
352 } else {
353 if (try_copy_region(pctx, info))
354 goto end;
355 if (blit_native(ctx, info, &needs_present_readback))
356 goto end;
357 }
358 }
359
360
361
362 bool stencil_blit = false;
363 if (!util_blitter_is_blit_supported(ctx->blitter, info)) {
364 if (util_format_is_depth_or_stencil(info->src.resource->format)) {
365 struct pipe_blit_info depth_blit = *info;
366 depth_blit.mask = PIPE_MASK_Z;
367 stencil_blit = util_blitter_is_blit_supported(ctx->blitter, &depth_blit);
368 if (stencil_blit) {
369 zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS | ZINK_BLIT_SAVE_TEXTURES);
370 util_blitter_blit(ctx->blitter, &depth_blit);
371 }
372 }
373 if (!stencil_blit) {
374 mesa_loge("ZINK: blit unsupported %s -> %s",
375 util_format_short_name(info->src.resource->format),
376 util_format_short_name(info->dst.resource->format));
377 goto end;
378 }
379 }
380
381 if (src->obj->dt) {
382 zink_fb_clears_apply_region(ctx, info->src.resource, zink_rect_from_box(&info->src.box));
383 needs_present_readback = zink_kopper_acquire_readback(ctx, src, &use_src);
384 }
385
386 /* this is discard_only because we're about to start a renderpass that will
387 * flush all pending clears anyway
388 */
389 apply_dst_clears(ctx, info, true);
390 zink_fb_clears_apply_region(ctx, info->src.resource, zink_rect_from_box(&info->src.box));
391 unsigned rp_clears_enabled = ctx->rp_clears_enabled;
392 unsigned clears_enabled = ctx->clears_enabled;
393 if (!dst->fb_bind_count) {
394 /* avoid applying clears from fb unbind by storing and re-setting them after the blit */
395 ctx->rp_clears_enabled = 0;
396 ctx->clears_enabled = 0;
397 } else {
398 unsigned bit;
399 /* convert to PIPE_CLEAR_XYZ */
400 if (dst->fb_binds & BITFIELD_BIT(PIPE_MAX_COLOR_BUFS))
401 bit = PIPE_CLEAR_DEPTHSTENCIL;
402 else
403 bit = dst->fb_binds << 2;
404 rp_clears_enabled &= ~bit;
405 clears_enabled &= ~bit;
406 ctx->rp_clears_enabled &= bit;
407 ctx->clears_enabled &= bit;
408 }
409
410 /* this will draw a full-resource quad, so ignore existing data */
411 bool whole = util_blit_covers_whole_resource(info);
412 if (whole)
413 pctx->invalidate_resource(pctx, info->dst.resource);
414
415 zink_flush_dgc_if_enabled(ctx);
416 ctx->unordered_blitting = !(info->render_condition_enable && ctx->render_condition_active) &&
417 zink_screen(ctx->base.screen)->info.have_KHR_dynamic_rendering &&
418 !needs_present_readback &&
419 zink_get_cmdbuf(ctx, src, dst) == ctx->batch.state->reordered_cmdbuf;
420 VkCommandBuffer cmdbuf = ctx->batch.state->cmdbuf;
421 VkPipeline pipeline = ctx->gfx_pipeline_state.pipeline;
422 bool in_rp = ctx->batch.in_rp;
423 uint64_t tc_data = ctx->dynamic_fb.tc_info.data;
424 bool queries_disabled = ctx->queries_disabled;
425 bool rp_changed = ctx->rp_changed || (!ctx->fb_state.zsbuf && util_format_is_depth_or_stencil(info->dst.format));
426 unsigned ds3_states = ctx->ds3_states;
427 bool rp_tc_info_updated = ctx->rp_tc_info_updated;
428 if (ctx->unordered_blitting) {
429 /* for unordered blit, swap the unordered cmdbuf for the main one for the whole op to avoid conditional hell */
430 ctx->batch.state->cmdbuf = ctx->batch.state->reordered_cmdbuf;
431 ctx->batch.in_rp = false;
432 ctx->rp_changed = true;
433 ctx->queries_disabled = true;
434 ctx->batch.state->has_barriers = true;
435 ctx->pipeline_changed[0] = true;
436 zink_reset_ds3_states(ctx);
437 zink_select_draw_vbo(ctx);
438 }
439 zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS | ZINK_BLIT_SAVE_TEXTURES);
440 if (zink_format_needs_mutable(info->src.format, info->src.resource->format))
441 zink_resource_object_init_mutable(ctx, src);
442 if (zink_format_needs_mutable(info->dst.format, info->dst.resource->format))
443 zink_resource_object_init_mutable(ctx, dst);
444 zink_blit_barriers(ctx, use_src, dst, whole);
445 ctx->blitting = true;
446
447 if (stencil_blit) {
448 struct pipe_surface *dst_view, dst_templ;
449 util_blitter_default_dst_texture(&dst_templ, info->dst.resource, info->dst.level, info->dst.box.z);
450 dst_view = pctx->create_surface(pctx, info->dst.resource, &dst_templ);
451
452 util_blitter_clear_depth_stencil(ctx->blitter, dst_view, PIPE_CLEAR_STENCIL,
453 0, 0, info->dst.box.x, info->dst.box.y,
454 info->dst.box.width, info->dst.box.height);
455 zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS | ZINK_BLIT_SAVE_TEXTURES | ZINK_BLIT_SAVE_FS_CONST_BUF);
456 util_blitter_stencil_fallback(ctx->blitter,
457 info->dst.resource,
458 info->dst.level,
459 &info->dst.box,
460 info->src.resource,
461 info->src.level,
462 &info->src.box,
463 info->scissor_enable ? &info->scissor : NULL);
464
465 pipe_surface_release(pctx, &dst_view);
466 } else {
467 struct pipe_blit_info new_info = *info;
468 new_info.src.resource = &use_src->base.b;
469 util_blitter_blit(ctx->blitter, &new_info);
470 }
471 ctx->blitting = false;
472 ctx->rp_clears_enabled = rp_clears_enabled;
473 ctx->clears_enabled = clears_enabled;
474 if (ctx->unordered_blitting) {
475 zink_batch_no_rp(ctx);
476 ctx->batch.in_rp = in_rp;
477 ctx->gfx_pipeline_state.rp_state = zink_update_rendering_info(ctx);
478 ctx->rp_changed = rp_changed;
479 ctx->rp_tc_info_updated |= rp_tc_info_updated;
480 ctx->queries_disabled = queries_disabled;
481 ctx->dynamic_fb.tc_info.data = tc_data;
482 ctx->batch.state->cmdbuf = cmdbuf;
483 ctx->gfx_pipeline_state.pipeline = pipeline;
484 ctx->pipeline_changed[0] = true;
485 ctx->ds3_states = ds3_states;
486 zink_select_draw_vbo(ctx);
487 }
488 ctx->unordered_blitting = false;
489 end:
490 if (needs_present_readback) {
491 src->obj->unordered_read = false;
492 dst->obj->unordered_write = false;
493 zink_kopper_present_readback(ctx, src);
494 }
495 }
496
497 /* similar to radeonsi */
498 void
zink_blit_begin(struct zink_context * ctx,enum zink_blit_flags flags)499 zink_blit_begin(struct zink_context *ctx, enum zink_blit_flags flags)
500 {
501 util_blitter_save_vertex_elements(ctx->blitter, ctx->element_state);
502 util_blitter_save_viewport(ctx->blitter, ctx->vp_state.viewport_states);
503
504 util_blitter_save_vertex_buffers(ctx->blitter, ctx->vertex_buffers,
505 util_last_bit(ctx->gfx_pipeline_state.vertex_buffers_enabled_mask));
506 util_blitter_save_vertex_shader(ctx->blitter, ctx->gfx_stages[MESA_SHADER_VERTEX]);
507 util_blitter_save_tessctrl_shader(ctx->blitter, ctx->gfx_stages[MESA_SHADER_TESS_CTRL]);
508 util_blitter_save_tesseval_shader(ctx->blitter, ctx->gfx_stages[MESA_SHADER_TESS_EVAL]);
509 util_blitter_save_geometry_shader(ctx->blitter, ctx->gfx_stages[MESA_SHADER_GEOMETRY]);
510 util_blitter_save_rasterizer(ctx->blitter, ctx->rast_state);
511 util_blitter_save_so_targets(ctx->blitter, ctx->num_so_targets, ctx->so_targets);
512
513 if (flags & ZINK_BLIT_SAVE_FS_CONST_BUF)
514 util_blitter_save_fragment_constant_buffer_slot(ctx->blitter, ctx->ubos[MESA_SHADER_FRAGMENT]);
515
516 if (flags & ZINK_BLIT_SAVE_FS) {
517 util_blitter_save_blend(ctx->blitter, ctx->gfx_pipeline_state.blend_state);
518 util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->dsa_state);
519 util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
520 util_blitter_save_sample_mask(ctx->blitter, ctx->gfx_pipeline_state.sample_mask, ctx->gfx_pipeline_state.min_samples + 1);
521 util_blitter_save_scissor(ctx->blitter, ctx->vp_state.scissor_states);
522 /* also util_blitter_save_window_rectangles when we have that? */
523
524 util_blitter_save_fragment_shader(ctx->blitter, ctx->gfx_stages[MESA_SHADER_FRAGMENT]);
525 }
526
527 if (flags & ZINK_BLIT_SAVE_FB)
528 util_blitter_save_framebuffer(ctx->blitter, &ctx->fb_state);
529
530
531 if (flags & ZINK_BLIT_SAVE_TEXTURES) {
532 util_blitter_save_fragment_sampler_states(ctx->blitter,
533 ctx->di.num_samplers[MESA_SHADER_FRAGMENT],
534 (void**)ctx->sampler_states[MESA_SHADER_FRAGMENT]);
535 util_blitter_save_fragment_sampler_views(ctx->blitter,
536 ctx->di.num_sampler_views[MESA_SHADER_FRAGMENT],
537 ctx->sampler_views[MESA_SHADER_FRAGMENT]);
538 }
539
540 if (flags & ZINK_BLIT_NO_COND_RENDER && ctx->render_condition_active)
541 zink_stop_conditional_render(ctx);
542 }
543
544 void
zink_blit_barriers(struct zink_context * ctx,struct zink_resource * src,struct zink_resource * dst,bool whole_dst)545 zink_blit_barriers(struct zink_context *ctx, struct zink_resource *src, struct zink_resource *dst, bool whole_dst)
546 {
547 struct zink_screen *screen = zink_screen(ctx->base.screen);
548 if (src && zink_is_swapchain(src)) {
549 if (!zink_kopper_acquire(ctx, src, UINT64_MAX))
550 return;
551 } else if (dst && zink_is_swapchain(dst)) {
552 if (!zink_kopper_acquire(ctx, dst, UINT64_MAX))
553 return;
554 }
555
556 VkAccessFlagBits flags;
557 VkPipelineStageFlagBits pipeline;
558 if (util_format_is_depth_or_stencil(dst->base.b.format)) {
559 flags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
560 if (!whole_dst)
561 flags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
562 pipeline = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
563 } else {
564 flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
565 if (!whole_dst)
566 flags |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
567 pipeline = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
568 }
569 if (src == dst) {
570 VkImageLayout layout = zink_screen(ctx->base.screen)->info.have_EXT_attachment_feedback_loop_layout ?
571 VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT :
572 VK_IMAGE_LAYOUT_GENERAL;
573 screen->image_barrier(ctx, src, layout, VK_ACCESS_SHADER_READ_BIT | flags, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | pipeline);
574 } else {
575 if (src) {
576 VkImageLayout layout = util_format_is_depth_or_stencil(src->base.b.format) &&
577 src->obj->vkusage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ?
578 VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL :
579 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
580 screen->image_barrier(ctx, src, layout,
581 VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
582 if (!ctx->unordered_blitting)
583 src->obj->unordered_read = false;
584 }
585 VkImageLayout layout = util_format_is_depth_or_stencil(dst->base.b.format) ?
586 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL :
587 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
588 screen->image_barrier(ctx, dst, layout, flags, pipeline);
589 }
590 if (!ctx->unordered_blitting)
591 dst->obj->unordered_read = dst->obj->unordered_write = false;
592 }
593
594 bool
zink_blit_region_fills(struct u_rect region,unsigned width,unsigned height)595 zink_blit_region_fills(struct u_rect region, unsigned width, unsigned height)
596 {
597 struct u_rect intersect = {0, width, 0, height};
598 struct u_rect r = {
599 MIN2(region.x0, region.x1),
600 MAX2(region.x0, region.x1),
601 MIN2(region.y0, region.y1),
602 MAX2(region.y0, region.y1),
603 };
604
605 if (!u_rect_test_intersection(&r, &intersect))
606 /* is this even a thing? */
607 return false;
608
609 u_rect_find_intersection(&r, &intersect);
610 if (intersect.x0 != 0 || intersect.y0 != 0 ||
611 intersect.x1 != width || intersect.y1 != height)
612 return false;
613
614 return true;
615 }
616
617 bool
zink_blit_region_covers(struct u_rect region,struct u_rect covers)618 zink_blit_region_covers(struct u_rect region, struct u_rect covers)
619 {
620 struct u_rect r = {
621 MIN2(region.x0, region.x1),
622 MAX2(region.x0, region.x1),
623 MIN2(region.y0, region.y1),
624 MAX2(region.y0, region.y1),
625 };
626 struct u_rect c = {
627 MIN2(covers.x0, covers.x1),
628 MAX2(covers.x0, covers.x1),
629 MIN2(covers.y0, covers.y1),
630 MAX2(covers.y0, covers.y1),
631 };
632 struct u_rect intersect;
633 if (!u_rect_test_intersection(&r, &c))
634 return false;
635
636 u_rect_union(&intersect, &r, &c);
637 return intersect.x0 == c.x0 && intersect.y0 == c.y0 &&
638 intersect.x1 == c.x1 && intersect.y1 == c.y1;
639 }
640