Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/zink/zink_clear.c
4570 views
1
/*
2
* Copyright 2018 Collabora Ltd.
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* on the rights to use, copy, modify, merge, publish, distribute, sub
8
* license, and/or sell copies of the Software, and to permit persons to whom
9
* the Software is furnished to do so, subject to the following conditions:
10
*
11
* The above copyright notice and this permission notice (including the next
12
* paragraph) shall be included in all copies or substantial portions of the
13
* Software.
14
*
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21
* USE OR OTHER DEALINGS IN THE SOFTWARE.
22
*/
23
24
#include "zink_context.h"
25
#include "zink_query.h"
26
#include "zink_resource.h"
27
#include "zink_screen.h"
28
29
#include "util/u_blitter.h"
30
#include "util/u_dynarray.h"
31
#include "util/format/u_format.h"
32
#include "util/format_srgb.h"
33
#include "util/u_framebuffer.h"
34
#include "util/u_inlines.h"
35
#include "util/u_rect.h"
36
#include "util/u_surface.h"
37
#include "util/u_helpers.h"
38
39
static inline bool
40
check_3d_layers(struct pipe_surface *psurf)
41
{
42
if (psurf->texture->target != PIPE_TEXTURE_3D)
43
return true;
44
/* SPEC PROBLEM:
45
* though the vk spec doesn't seem to explicitly address this, currently drivers
46
* are claiming that all 3D images have a single "3D" layer regardless of layercount,
47
* so we can never clear them if we aren't trying to clear only layer 0
48
*/
49
if (psurf->u.tex.first_layer)
50
return false;
51
52
if (psurf->u.tex.last_layer - psurf->u.tex.first_layer > 0)
53
return false;
54
return true;
55
}
56
57
static inline bool
58
scissor_states_equal(const struct pipe_scissor_state *a, const struct pipe_scissor_state *b)
59
{
60
return a->minx == b->minx && a->miny == b->miny && a->maxx == b->maxx && a->maxy == b->maxy;
61
}
62
63
static void
64
clear_in_rp(struct pipe_context *pctx,
65
unsigned buffers,
66
const struct pipe_scissor_state *scissor_state,
67
const union pipe_color_union *pcolor,
68
double depth, unsigned stencil)
69
{
70
struct zink_context *ctx = zink_context(pctx);
71
struct pipe_framebuffer_state *fb = &ctx->fb_state;
72
73
VkClearAttachment attachments[1 + PIPE_MAX_COLOR_BUFS];
74
int num_attachments = 0;
75
76
if (buffers & PIPE_CLEAR_COLOR) {
77
VkClearColorValue color;
78
color.float32[0] = pcolor->f[0];
79
color.float32[1] = pcolor->f[1];
80
color.float32[2] = pcolor->f[2];
81
color.float32[3] = pcolor->f[3];
82
83
for (unsigned i = 0; i < fb->nr_cbufs; i++) {
84
if (!(buffers & (PIPE_CLEAR_COLOR0 << i)) || !fb->cbufs[i])
85
continue;
86
87
attachments[num_attachments].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
88
attachments[num_attachments].colorAttachment = i;
89
attachments[num_attachments].clearValue.color = color;
90
++num_attachments;
91
}
92
}
93
94
if (buffers & PIPE_CLEAR_DEPTHSTENCIL && fb->zsbuf) {
95
VkImageAspectFlags aspect = 0;
96
if (buffers & PIPE_CLEAR_DEPTH)
97
aspect |= VK_IMAGE_ASPECT_DEPTH_BIT;
98
if (buffers & PIPE_CLEAR_STENCIL)
99
aspect |= VK_IMAGE_ASPECT_STENCIL_BIT;
100
101
attachments[num_attachments].aspectMask = aspect;
102
attachments[num_attachments].clearValue.depthStencil.depth = depth;
103
attachments[num_attachments].clearValue.depthStencil.stencil = stencil;
104
++num_attachments;
105
}
106
107
VkClearRect cr = {0};
108
if (scissor_state) {
109
cr.rect.offset.x = scissor_state->minx;
110
cr.rect.offset.y = scissor_state->miny;
111
cr.rect.extent.width = MIN2(fb->width, scissor_state->maxx - scissor_state->minx);
112
cr.rect.extent.height = MIN2(fb->height, scissor_state->maxy - scissor_state->miny);
113
} else {
114
cr.rect.extent.width = fb->width;
115
cr.rect.extent.height = fb->height;
116
}
117
cr.baseArrayLayer = 0;
118
cr.layerCount = util_framebuffer_get_num_layers(fb);
119
struct zink_batch *batch = zink_batch_rp(ctx);
120
vkCmdClearAttachments(batch->state->cmdbuf, num_attachments, attachments, 1, &cr);
121
}
122
123
static void
124
clear_color_no_rp(struct zink_context *ctx, struct zink_resource *res, const union pipe_color_union *pcolor, unsigned level, unsigned layer, unsigned layerCount)
125
{
126
struct zink_batch *batch = zink_batch_no_rp(ctx);
127
VkImageSubresourceRange range = {0};
128
range.baseMipLevel = level;
129
range.levelCount = 1;
130
range.baseArrayLayer = layer;
131
range.layerCount = layerCount;
132
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
133
134
VkClearColorValue color;
135
color.float32[0] = pcolor->f[0];
136
color.float32[1] = pcolor->f[1];
137
color.float32[2] = pcolor->f[2];
138
color.float32[3] = pcolor->f[3];
139
140
if (zink_resource_image_needs_barrier(res, VK_IMAGE_LAYOUT_GENERAL, 0, 0) &&
141
zink_resource_image_needs_barrier(res, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0))
142
zink_resource_image_barrier(ctx, NULL, res, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0);
143
zink_batch_reference_resource_rw(batch, res, true);
144
vkCmdClearColorImage(batch->state->cmdbuf, res->obj->image, res->layout, &color, 1, &range);
145
}
146
147
static void
148
clear_zs_no_rp(struct zink_context *ctx, struct zink_resource *res, VkImageAspectFlags aspects, double depth, unsigned stencil, unsigned level, unsigned layer, unsigned layerCount)
149
{
150
struct zink_batch *batch = zink_batch_no_rp(ctx);
151
VkImageSubresourceRange range = {0};
152
range.baseMipLevel = level;
153
range.levelCount = 1;
154
range.baseArrayLayer = layer;
155
range.layerCount = layerCount;
156
range.aspectMask = aspects;
157
158
VkClearDepthStencilValue zs_value = {depth, stencil};
159
160
if (zink_resource_image_needs_barrier(res, VK_IMAGE_LAYOUT_GENERAL, 0, 0) &&
161
zink_resource_image_needs_barrier(res, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0))
162
zink_resource_image_barrier(ctx, NULL, res, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0);
163
zink_batch_reference_resource_rw(batch, res, true);
164
vkCmdClearDepthStencilImage(batch->state->cmdbuf, res->obj->image, res->layout, &zs_value, 1, &range);
165
}
166
167
168
169
static struct zink_framebuffer_clear_data *
170
get_clear_data(struct zink_context *ctx, struct zink_framebuffer_clear *fb_clear, const struct pipe_scissor_state *scissor_state)
171
{
172
struct zink_framebuffer_clear_data *clear = NULL;
173
unsigned num_clears = zink_fb_clear_count(fb_clear);
174
if (num_clears) {
175
struct zink_framebuffer_clear_data *last_clear = zink_fb_clear_element(fb_clear, num_clears - 1);
176
/* if we're completely overwriting the previous clear, merge this into the previous clear */
177
if (!scissor_state || (last_clear->has_scissor && scissor_states_equal(&last_clear->scissor, scissor_state)))
178
clear = last_clear;
179
}
180
if (!clear) {
181
struct zink_framebuffer_clear_data cd = {0};
182
util_dynarray_append(&fb_clear->clears, struct zink_framebuffer_clear_data, cd);
183
clear = zink_fb_clear_element(fb_clear, zink_fb_clear_count(fb_clear) - 1);
184
}
185
return clear;
186
}
187
188
void
189
zink_clear(struct pipe_context *pctx,
190
unsigned buffers,
191
const struct pipe_scissor_state *scissor_state,
192
const union pipe_color_union *pcolor,
193
double depth, unsigned stencil)
194
{
195
struct zink_context *ctx = zink_context(pctx);
196
struct pipe_framebuffer_state *fb = &ctx->fb_state;
197
struct zink_batch *batch = &ctx->batch;
198
bool needs_rp = false;
199
200
if (scissor_state) {
201
struct u_rect scissor = {scissor_state->minx, scissor_state->maxx, scissor_state->miny, scissor_state->maxy};
202
needs_rp = !zink_blit_region_fills(scissor, fb->width, fb->height);
203
}
204
205
206
if (batch->in_rp) {
207
clear_in_rp(pctx, buffers, scissor_state, pcolor, depth, stencil);
208
return;
209
}
210
211
if (buffers & PIPE_CLEAR_COLOR) {
212
for (unsigned i = 0; i < fb->nr_cbufs; i++) {
213
if ((buffers & (PIPE_CLEAR_COLOR0 << i)) && fb->cbufs[i]) {
214
struct pipe_surface *psurf = fb->cbufs[i];
215
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i];
216
struct zink_framebuffer_clear_data *clear = get_clear_data(ctx, fb_clear, needs_rp ? scissor_state : NULL);
217
218
ctx->clears_enabled |= PIPE_CLEAR_COLOR0 << i;
219
clear->conditional = ctx->render_condition_active;
220
clear->has_scissor = needs_rp;
221
if (scissor_state && needs_rp)
222
clear->scissor = *scissor_state;
223
clear->color.color = *pcolor;
224
clear->color.srgb = psurf->format != psurf->texture->format &&
225
!util_format_is_srgb(psurf->format) && util_format_is_srgb(psurf->texture->format);
226
if (zink_fb_clear_first_needs_explicit(fb_clear))
227
ctx->rp_clears_enabled &= ~(PIPE_CLEAR_COLOR0 << i);
228
else
229
ctx->rp_clears_enabled |= PIPE_CLEAR_COLOR0 << i;
230
}
231
}
232
}
233
234
if (buffers & PIPE_CLEAR_DEPTHSTENCIL && fb->zsbuf) {
235
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[PIPE_MAX_COLOR_BUFS];
236
struct zink_framebuffer_clear_data *clear = get_clear_data(ctx, fb_clear, needs_rp ? scissor_state : NULL);
237
ctx->clears_enabled |= PIPE_CLEAR_DEPTHSTENCIL;
238
clear->conditional = ctx->render_condition_active;
239
clear->has_scissor = needs_rp;
240
if (scissor_state && needs_rp)
241
clear->scissor = *scissor_state;
242
if (buffers & PIPE_CLEAR_DEPTH)
243
clear->zs.depth = depth;
244
if (buffers & PIPE_CLEAR_STENCIL)
245
clear->zs.stencil = stencil;
246
clear->zs.bits |= (buffers & PIPE_CLEAR_DEPTHSTENCIL);
247
if (zink_fb_clear_first_needs_explicit(fb_clear))
248
ctx->rp_clears_enabled &= ~PIPE_CLEAR_DEPTHSTENCIL;
249
else
250
ctx->rp_clears_enabled |= (buffers & PIPE_CLEAR_DEPTHSTENCIL);
251
}
252
}
253
254
static inline bool
255
colors_equal(union pipe_color_union *a, union pipe_color_union *b)
256
{
257
return a->ui[0] == b->ui[0] && a->ui[1] == b->ui[1] && a->ui[2] == b->ui[2] && a->ui[3] == b->ui[3];
258
}
259
260
void
261
zink_clear_framebuffer(struct zink_context *ctx, unsigned clear_buffers)
262
{
263
unsigned to_clear = 0;
264
struct pipe_framebuffer_state *fb_state = &ctx->fb_state;
265
#ifndef NDEBUG
266
assert(!(clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) || zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS));
267
for (int i = 0; i < fb_state->nr_cbufs && clear_buffers >= PIPE_CLEAR_COLOR0; i++) {
268
assert(!(clear_buffers & (PIPE_CLEAR_COLOR0 << i)) || zink_fb_clear_enabled(ctx, i));
269
}
270
#endif
271
while (clear_buffers) {
272
struct zink_framebuffer_clear *color_clear = NULL;
273
struct zink_framebuffer_clear *zs_clear = NULL;
274
unsigned num_clears = 0;
275
for (int i = 0; i < fb_state->nr_cbufs && clear_buffers >= PIPE_CLEAR_COLOR0; i++) {
276
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i];
277
/* these need actual clear calls inside the rp */
278
if (!(clear_buffers & (PIPE_CLEAR_COLOR0 << i)))
279
continue;
280
if (color_clear) {
281
/* different number of clears -> do another clear */
282
//XXX: could potentially merge "some" of the clears into this one for a very, very small optimization
283
if (num_clears != zink_fb_clear_count(fb_clear))
284
goto out;
285
/* compare all the clears to determine if we can batch these buffers together */
286
for (int j = !zink_fb_clear_first_needs_explicit(fb_clear); j < num_clears; j++) {
287
struct zink_framebuffer_clear_data *a = zink_fb_clear_element(color_clear, j);
288
struct zink_framebuffer_clear_data *b = zink_fb_clear_element(fb_clear, j);
289
/* scissors don't match, fire this one off */
290
if (a->has_scissor != b->has_scissor || (a->has_scissor && !scissor_states_equal(&a->scissor, &b->scissor)))
291
goto out;
292
293
/* colors don't match, fire this one off */
294
if (!colors_equal(&a->color.color, &b->color.color))
295
goto out;
296
}
297
} else {
298
color_clear = fb_clear;
299
num_clears = zink_fb_clear_count(fb_clear);
300
}
301
302
clear_buffers &= ~(PIPE_CLEAR_COLOR0 << i);
303
to_clear |= (PIPE_CLEAR_COLOR0 << i);
304
}
305
clear_buffers &= ~PIPE_CLEAR_COLOR;
306
if (clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) {
307
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[PIPE_MAX_COLOR_BUFS];
308
if (color_clear) {
309
if (num_clears != zink_fb_clear_count(fb_clear))
310
goto out;
311
/* compare all the clears to determine if we can batch these buffers together */
312
for (int j = !zink_fb_clear_first_needs_explicit(fb_clear); j < zink_fb_clear_count(color_clear); j++) {
313
struct zink_framebuffer_clear_data *a = zink_fb_clear_element(color_clear, j);
314
struct zink_framebuffer_clear_data *b = zink_fb_clear_element(fb_clear, j);
315
/* scissors don't match, fire this one off */
316
if (a->has_scissor != b->has_scissor || (a->has_scissor && !scissor_states_equal(&a->scissor, &b->scissor)))
317
goto out;
318
}
319
}
320
zs_clear = fb_clear;
321
to_clear |= (clear_buffers & PIPE_CLEAR_DEPTHSTENCIL);
322
clear_buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
323
}
324
out:
325
if (to_clear) {
326
if (num_clears) {
327
for (int j = !zink_fb_clear_first_needs_explicit(color_clear); j < num_clears; j++) {
328
struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(color_clear, j);
329
struct zink_framebuffer_clear_data *zsclear = NULL;
330
/* zs bits are both set here if those aspects should be cleared at some point */
331
unsigned clear_bits = to_clear & ~PIPE_CLEAR_DEPTHSTENCIL;
332
if (zs_clear) {
333
zsclear = zink_fb_clear_element(zs_clear, j);
334
clear_bits |= zsclear->zs.bits;
335
}
336
zink_clear(&ctx->base, clear_bits,
337
clear->has_scissor ? &clear->scissor : NULL,
338
&clear->color.color,
339
zsclear ? zsclear->zs.depth : 0,
340
zsclear ? zsclear->zs.stencil : 0);
341
}
342
} else {
343
for (int j = !zink_fb_clear_first_needs_explicit(zs_clear); j < zink_fb_clear_count(zs_clear); j++) {
344
struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(zs_clear, j);
345
zink_clear(&ctx->base, clear->zs.bits,
346
clear->has_scissor ? &clear->scissor : NULL,
347
NULL,
348
clear->zs.depth,
349
clear->zs.stencil);
350
}
351
}
352
}
353
to_clear = 0;
354
}
355
for (int i = 0; i < ARRAY_SIZE(ctx->fb_clears); i++)
356
zink_fb_clear_reset(ctx, i);
357
}
358
359
static struct pipe_surface *
360
create_clear_surface(struct pipe_context *pctx, struct pipe_resource *pres, unsigned level, const struct pipe_box *box)
361
{
362
struct pipe_surface tmpl = {{0}};
363
364
tmpl.format = pres->format;
365
tmpl.u.tex.first_layer = box->z;
366
tmpl.u.tex.last_layer = box->z + box->depth - 1;
367
tmpl.u.tex.level = level;
368
return pctx->create_surface(pctx, pres, &tmpl);
369
}
370
371
void
372
zink_clear_texture(struct pipe_context *pctx,
373
struct pipe_resource *pres,
374
unsigned level,
375
const struct pipe_box *box,
376
const void *data)
377
{
378
struct zink_context *ctx = zink_context(pctx);
379
struct zink_resource *res = zink_resource(pres);
380
struct pipe_screen *pscreen = pctx->screen;
381
struct u_rect region = zink_rect_from_box(box);
382
bool needs_rp = !zink_blit_region_fills(region, pres->width0, pres->height0) || ctx->render_condition_active;
383
struct pipe_surface *surf = NULL;
384
385
if (res->aspect & VK_IMAGE_ASPECT_COLOR_BIT) {
386
union pipe_color_union color;
387
388
util_format_unpack_rgba(pres->format, color.ui, data, 1);
389
390
if (pscreen->is_format_supported(pscreen, pres->format, pres->target, 0, 0,
391
PIPE_BIND_RENDER_TARGET) && !needs_rp) {
392
zink_batch_no_rp(ctx);
393
clear_color_no_rp(ctx, res, &color, level, box->z, box->depth);
394
} else {
395
surf = create_clear_surface(pctx, pres, level, box);
396
zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS);
397
util_blitter_clear_render_target(ctx->blitter, surf, &color, box->x, box->y, box->width, box->height);
398
}
399
if (res->base.b.target == PIPE_BUFFER)
400
util_range_add(&res->base.b, &res->valid_buffer_range, box->x, box->x + box->width);
401
} else {
402
float depth = 0.0;
403
uint8_t stencil = 0;
404
405
if (res->aspect & VK_IMAGE_ASPECT_DEPTH_BIT)
406
util_format_unpack_z_float(pres->format, &depth, data, 1);
407
408
if (res->aspect & VK_IMAGE_ASPECT_STENCIL_BIT)
409
util_format_unpack_s_8uint(pres->format, &stencil, data, 1);
410
411
if (!needs_rp) {
412
zink_batch_no_rp(ctx);
413
clear_zs_no_rp(ctx, res, res->aspect, depth, stencil, level, box->z, box->depth);
414
} else {
415
unsigned flags = 0;
416
if (res->aspect & VK_IMAGE_ASPECT_DEPTH_BIT)
417
flags |= PIPE_CLEAR_DEPTH;
418
if (res->aspect & VK_IMAGE_ASPECT_STENCIL_BIT)
419
flags |= PIPE_CLEAR_STENCIL;
420
surf = create_clear_surface(pctx, pres, level, box);
421
zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS);
422
util_blitter_clear_depth_stencil(ctx->blitter, surf, flags, depth, stencil, box->x, box->y, box->width, box->height);
423
}
424
}
425
/* this will never destroy the surface */
426
pipe_surface_reference(&surf, NULL);
427
}
428
429
void
430
zink_clear_buffer(struct pipe_context *pctx,
431
struct pipe_resource *pres,
432
unsigned offset,
433
unsigned size,
434
const void *clear_value,
435
int clear_value_size)
436
{
437
struct zink_context *ctx = zink_context(pctx);
438
struct zink_resource *res = zink_resource(pres);
439
440
uint32_t clamped;
441
if (util_lower_clearsize_to_dword(clear_value, &clear_value_size, &clamped))
442
clear_value = &clamped;
443
if (offset % 4 == 0 && size % 4 == 0 && clear_value_size == sizeof(uint32_t)) {
444
/*
445
- dstOffset is the byte offset into the buffer at which to start filling,
446
and must be a multiple of 4.
447
448
- size is the number of bytes to fill, and must be either a multiple of 4,
449
or VK_WHOLE_SIZE to fill the range from offset to the end of the buffer
450
*/
451
struct zink_batch *batch = zink_batch_no_rp(ctx);
452
zink_batch_reference_resource_rw(batch, res, true);
453
util_range_add(&res->base.b, &res->valid_buffer_range, offset, offset + size);
454
vkCmdFillBuffer(batch->state->cmdbuf, res->obj->buffer, offset, size, *(uint32_t*)clear_value);
455
return;
456
}
457
struct pipe_transfer *xfer;
458
uint8_t *map = pipe_buffer_map_range(pctx, pres, offset, size,
459
PIPE_MAP_WRITE | PIPE_MAP_ONCE | PIPE_MAP_DISCARD_RANGE, &xfer);
460
if (!map)
461
return;
462
unsigned rem = size % clear_value_size;
463
uint8_t *ptr = map;
464
for (unsigned i = 0; i < (size - rem) / clear_value_size; i++) {
465
memcpy(ptr, clear_value, clear_value_size);
466
ptr += clear_value_size;
467
}
468
if (rem)
469
memcpy(map + size - rem, clear_value, rem);
470
pipe_buffer_unmap(pctx, xfer);
471
}
472
473
void
474
zink_clear_render_target(struct pipe_context *pctx, struct pipe_surface *dst,
475
const union pipe_color_union *color, unsigned dstx,
476
unsigned dsty, unsigned width, unsigned height,
477
bool render_condition_enabled)
478
{
479
struct zink_context *ctx = zink_context(pctx);
480
zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS | (render_condition_enabled ? 0 : ZINK_BLIT_NO_COND_RENDER));
481
util_blitter_clear_render_target(ctx->blitter, dst, color, dstx, dsty, width, height);
482
if (!render_condition_enabled && ctx->render_condition_active)
483
zink_start_conditional_render(ctx);
484
}
485
486
void
487
zink_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *dst,
488
unsigned clear_flags, double depth, unsigned stencil,
489
unsigned dstx, unsigned dsty, unsigned width, unsigned height,
490
bool render_condition_enabled)
491
{
492
struct zink_context *ctx = zink_context(pctx);
493
zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS | (render_condition_enabled ? 0 : ZINK_BLIT_NO_COND_RENDER));
494
util_blitter_clear_depth_stencil(ctx->blitter, dst, clear_flags, depth, stencil, dstx, dsty, width, height);
495
if (!render_condition_enabled && ctx->render_condition_active)
496
zink_start_conditional_render(ctx);
497
}
498
499
bool
500
zink_fb_clear_needs_explicit(struct zink_framebuffer_clear *fb_clear)
501
{
502
if (zink_fb_clear_count(fb_clear) != 1)
503
return true;
504
return zink_fb_clear_element_needs_explicit(zink_fb_clear_element(fb_clear, 0));
505
}
506
507
bool
508
zink_fb_clear_first_needs_explicit(struct zink_framebuffer_clear *fb_clear)
509
{
510
if (!zink_fb_clear_count(fb_clear))
511
return false;
512
return zink_fb_clear_element_needs_explicit(zink_fb_clear_element(fb_clear, 0));
513
}
514
515
void
516
zink_fb_clear_util_unpack_clear_color(struct zink_framebuffer_clear_data *clear, enum pipe_format format, union pipe_color_union *color)
517
{
518
const struct util_format_description *desc = util_format_description(format);
519
if (clear->color.srgb) {
520
/* if SRGB mode is disabled for the fb with a backing srgb image then we have to
521
* convert this to srgb color
522
*/
523
for (unsigned j = 0; j < MIN2(3, desc->nr_channels); j++) {
524
assert(desc->channel[j].normalized);
525
color->f[j] = util_format_srgb_to_linear_float(clear->color.color.f[j]);
526
}
527
color->f[3] = clear->color.color.f[3];
528
} else {
529
for (unsigned i = 0; i < 4; i++)
530
color->f[i] = clear->color.color.f[i];
531
}
532
}
533
534
static void
535
fb_clears_apply_internal(struct zink_context *ctx, struct pipe_resource *pres, int i)
536
{
537
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i];
538
539
if (!zink_fb_clear_enabled(ctx, i))
540
return;
541
if (ctx->batch.in_rp)
542
zink_clear_framebuffer(ctx, BITFIELD_BIT(i));
543
else if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
544
if (zink_fb_clear_needs_explicit(fb_clear) || !check_3d_layers(ctx->fb_state.cbufs[i]))
545
/* this will automatically trigger all the clears */
546
zink_batch_rp(ctx);
547
else {
548
struct pipe_surface *psurf = ctx->fb_state.cbufs[i];
549
struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, 0);
550
union pipe_color_union color;
551
zink_fb_clear_util_unpack_clear_color(clear, psurf->format, &color);
552
553
clear_color_no_rp(ctx, zink_resource(pres), &color,
554
psurf->u.tex.level, psurf->u.tex.first_layer,
555
psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1);
556
}
557
zink_fb_clear_reset(ctx, i);
558
return;
559
} else {
560
if (zink_fb_clear_needs_explicit(fb_clear) || !check_3d_layers(ctx->fb_state.zsbuf))
561
/* this will automatically trigger all the clears */
562
zink_batch_rp(ctx);
563
else {
564
struct pipe_surface *psurf = ctx->fb_state.zsbuf;
565
struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, 0);
566
VkImageAspectFlags aspects = 0;
567
if (clear->zs.bits & PIPE_CLEAR_DEPTH)
568
aspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
569
if (clear->zs.bits & PIPE_CLEAR_STENCIL)
570
aspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
571
clear_zs_no_rp(ctx, zink_resource(pres), aspects, clear->zs.depth, clear->zs.stencil,
572
psurf->u.tex.level, psurf->u.tex.first_layer,
573
psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1);
574
}
575
}
576
zink_fb_clear_reset(ctx, i);
577
}
578
579
void
580
zink_fb_clear_reset(struct zink_context *ctx, unsigned i)
581
{
582
util_dynarray_clear(&ctx->fb_clears[i].clears);
583
if (i == PIPE_MAX_COLOR_BUFS) {
584
ctx->clears_enabled &= ~PIPE_CLEAR_DEPTHSTENCIL;
585
ctx->rp_clears_enabled &= ~PIPE_CLEAR_DEPTHSTENCIL;
586
} else {
587
ctx->clears_enabled &= ~(PIPE_CLEAR_COLOR0 << i);
588
ctx->rp_clears_enabled &= ~(PIPE_CLEAR_COLOR0 << i);
589
}
590
}
591
592
void
593
zink_fb_clears_apply(struct zink_context *ctx, struct pipe_resource *pres)
594
{
595
if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
596
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
597
if (ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture == pres) {
598
fb_clears_apply_internal(ctx, pres, i);
599
return;
600
}
601
}
602
} else {
603
if (ctx->fb_state.zsbuf && ctx->fb_state.zsbuf->texture == pres) {
604
fb_clears_apply_internal(ctx, pres, PIPE_MAX_COLOR_BUFS);
605
}
606
}
607
}
608
609
void
610
zink_fb_clears_discard(struct zink_context *ctx, struct pipe_resource *pres)
611
{
612
if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
613
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
614
if (ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture == pres) {
615
if (zink_fb_clear_enabled(ctx, i)) {
616
zink_fb_clear_reset(ctx, i);
617
return;
618
}
619
}
620
}
621
} else {
622
if (zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS) && ctx->fb_state.zsbuf && ctx->fb_state.zsbuf->texture == pres) {
623
int i = PIPE_MAX_COLOR_BUFS;
624
zink_fb_clear_reset(ctx, i);
625
}
626
}
627
}
628
629
void
630
zink_clear_apply_conditionals(struct zink_context *ctx)
631
{
632
for (int i = 0; i < ARRAY_SIZE(ctx->fb_clears); i++) {
633
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i];
634
if (!zink_fb_clear_enabled(ctx, i))
635
continue;
636
for (int j = 0; j < zink_fb_clear_count(fb_clear); j++) {
637
struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, j);
638
if (clear->conditional) {
639
struct pipe_surface *surf;
640
if (i < PIPE_MAX_COLOR_BUFS)
641
surf = ctx->fb_state.cbufs[i];
642
else
643
surf = ctx->fb_state.zsbuf;
644
if (surf)
645
fb_clears_apply_internal(ctx, surf->texture, i);
646
else
647
zink_fb_clear_reset(ctx, i);
648
break;
649
}
650
}
651
}
652
}
653
654
static void
655
fb_clears_apply_or_discard_internal(struct zink_context *ctx, struct pipe_resource *pres, struct u_rect region, bool discard_only, bool invert, int i)
656
{
657
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i];
658
if (zink_fb_clear_enabled(ctx, i)) {
659
if (zink_blit_region_fills(region, pres->width0, pres->height0)) {
660
if (invert)
661
fb_clears_apply_internal(ctx, pres, i);
662
else
663
/* we know we can skip these */
664
zink_fb_clears_discard(ctx, pres);
665
return;
666
}
667
for (int j = 0; j < zink_fb_clear_count(fb_clear); j++) {
668
struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, j);
669
struct u_rect scissor = {clear->scissor.minx, clear->scissor.maxx,
670
clear->scissor.miny, clear->scissor.maxy};
671
if (!clear->has_scissor || zink_blit_region_covers(region, scissor)) {
672
/* this is a clear that isn't fully covered by our pending write */
673
if (!discard_only)
674
fb_clears_apply_internal(ctx, pres, i);
675
return;
676
}
677
}
678
if (!invert)
679
/* if we haven't already returned, then we know we can discard */
680
zink_fb_clears_discard(ctx, pres);
681
}
682
}
683
684
void
685
zink_fb_clears_apply_or_discard(struct zink_context *ctx, struct pipe_resource *pres, struct u_rect region, bool discard_only)
686
{
687
if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
688
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
689
if (ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture == pres) {
690
fb_clears_apply_or_discard_internal(ctx, pres, region, discard_only, false, i);
691
return;
692
}
693
}
694
} else {
695
if (zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS) && ctx->fb_state.zsbuf && ctx->fb_state.zsbuf->texture == pres) {
696
fb_clears_apply_or_discard_internal(ctx, pres, region, discard_only, false, PIPE_MAX_COLOR_BUFS);
697
}
698
}
699
}
700
701
void
702
zink_fb_clears_apply_region(struct zink_context *ctx, struct pipe_resource *pres, struct u_rect region)
703
{
704
if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
705
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
706
if (ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture == pres) {
707
fb_clears_apply_or_discard_internal(ctx, pres, region, false, true, i);
708
return;
709
}
710
}
711
} else {
712
if (ctx->fb_state.zsbuf && ctx->fb_state.zsbuf->texture == pres) {
713
fb_clears_apply_or_discard_internal(ctx, pres, region, false, true, PIPE_MAX_COLOR_BUFS);
714
}
715
}
716
}
717
718