~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/gallium/drivers/zink/zink_clear.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

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