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