1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2018 Collabora Ltd. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "zink_context.h" 25bf215546Sopenharmony_ci#include "zink_kopper.h" 26bf215546Sopenharmony_ci#include "zink_framebuffer.h" 27bf215546Sopenharmony_ci#include "zink_query.h" 28bf215546Sopenharmony_ci#include "zink_resource.h" 29bf215546Sopenharmony_ci#include "zink_screen.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci#include "util/u_blitter.h" 32bf215546Sopenharmony_ci#include "util/u_dynarray.h" 33bf215546Sopenharmony_ci#include "util/format/u_format.h" 34bf215546Sopenharmony_ci#include "util/format_srgb.h" 35bf215546Sopenharmony_ci#include "util/u_framebuffer.h" 36bf215546Sopenharmony_ci#include "util/u_inlines.h" 37bf215546Sopenharmony_ci#include "util/u_rect.h" 38bf215546Sopenharmony_ci#include "util/u_surface.h" 39bf215546Sopenharmony_ci#include "util/u_helpers.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_cistatic inline bool 42bf215546Sopenharmony_ciscissor_states_equal(const struct pipe_scissor_state *a, const struct pipe_scissor_state *b) 43bf215546Sopenharmony_ci{ 44bf215546Sopenharmony_ci return a->minx == b->minx && a->miny == b->miny && a->maxx == b->maxx && a->maxy == b->maxy; 45bf215546Sopenharmony_ci} 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_cistatic void 48bf215546Sopenharmony_ciclear_in_rp(struct pipe_context *pctx, 49bf215546Sopenharmony_ci unsigned buffers, 50bf215546Sopenharmony_ci const struct pipe_scissor_state *scissor_state, 51bf215546Sopenharmony_ci const union pipe_color_union *pcolor, 52bf215546Sopenharmony_ci double depth, unsigned stencil) 53bf215546Sopenharmony_ci{ 54bf215546Sopenharmony_ci struct zink_context *ctx = zink_context(pctx); 55bf215546Sopenharmony_ci struct pipe_framebuffer_state *fb = &ctx->fb_state; 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci VkClearAttachment attachments[1 + PIPE_MAX_COLOR_BUFS]; 58bf215546Sopenharmony_ci int num_attachments = 0; 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci if (buffers & PIPE_CLEAR_COLOR) { 61bf215546Sopenharmony_ci VkClearColorValue color; 62bf215546Sopenharmony_ci color.uint32[0] = pcolor->ui[0]; 63bf215546Sopenharmony_ci color.uint32[1] = pcolor->ui[1]; 64bf215546Sopenharmony_ci color.uint32[2] = pcolor->ui[2]; 65bf215546Sopenharmony_ci color.uint32[3] = pcolor->ui[3]; 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci for (unsigned i = 0; i < fb->nr_cbufs; i++) { 68bf215546Sopenharmony_ci if (!(buffers & (PIPE_CLEAR_COLOR0 << i)) || !fb->cbufs[i]) 69bf215546Sopenharmony_ci continue; 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci attachments[num_attachments].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 72bf215546Sopenharmony_ci attachments[num_attachments].colorAttachment = i; 73bf215546Sopenharmony_ci attachments[num_attachments].clearValue.color = color; 74bf215546Sopenharmony_ci ++num_attachments; 75bf215546Sopenharmony_ci } 76bf215546Sopenharmony_ci } 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci if (buffers & PIPE_CLEAR_DEPTHSTENCIL && fb->zsbuf) { 79bf215546Sopenharmony_ci VkImageAspectFlags aspect = 0; 80bf215546Sopenharmony_ci if (buffers & PIPE_CLEAR_DEPTH) 81bf215546Sopenharmony_ci aspect |= VK_IMAGE_ASPECT_DEPTH_BIT; 82bf215546Sopenharmony_ci if (buffers & PIPE_CLEAR_STENCIL) 83bf215546Sopenharmony_ci aspect |= VK_IMAGE_ASPECT_STENCIL_BIT; 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci attachments[num_attachments].aspectMask = aspect; 86bf215546Sopenharmony_ci attachments[num_attachments].clearValue.depthStencil.depth = depth; 87bf215546Sopenharmony_ci attachments[num_attachments].clearValue.depthStencil.stencil = stencil; 88bf215546Sopenharmony_ci ++num_attachments; 89bf215546Sopenharmony_ci } 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci VkClearRect cr = {0}; 92bf215546Sopenharmony_ci if (scissor_state) { 93bf215546Sopenharmony_ci cr.rect.offset.x = scissor_state->minx; 94bf215546Sopenharmony_ci cr.rect.offset.y = scissor_state->miny; 95bf215546Sopenharmony_ci cr.rect.extent.width = MIN2(fb->width, scissor_state->maxx - scissor_state->minx); 96bf215546Sopenharmony_ci cr.rect.extent.height = MIN2(fb->height, scissor_state->maxy - scissor_state->miny); 97bf215546Sopenharmony_ci } else { 98bf215546Sopenharmony_ci cr.rect.extent.width = fb->width; 99bf215546Sopenharmony_ci cr.rect.extent.height = fb->height; 100bf215546Sopenharmony_ci } 101bf215546Sopenharmony_ci cr.baseArrayLayer = 0; 102bf215546Sopenharmony_ci cr.layerCount = util_framebuffer_get_num_layers(fb); 103bf215546Sopenharmony_ci struct zink_batch *batch = &ctx->batch; 104bf215546Sopenharmony_ci assert(batch->in_rp); 105bf215546Sopenharmony_ci VKCTX(CmdClearAttachments)(batch->state->cmdbuf, num_attachments, attachments, 1, &cr); 106bf215546Sopenharmony_ci /* 107bf215546Sopenharmony_ci Rendering within a subpass containing a feedback loop creates a data race, except in the following 108bf215546Sopenharmony_ci cases: 109bf215546Sopenharmony_ci • If a memory dependency is inserted between when the attachment is written and when it is 110bf215546Sopenharmony_ci subsequently read by later fragments. Pipeline barriers expressing a subpass self-dependency 111bf215546Sopenharmony_ci are the only way to achieve this, and one must be inserted every time a fragment will read 112bf215546Sopenharmony_ci values at a particular sample (x, y, layer, sample) coordinate, if those values have been written 113bf215546Sopenharmony_ci since the most recent pipeline barrier 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci VK 1.3.211, Chapter 8: Render Pass 116bf215546Sopenharmony_ci */ 117bf215546Sopenharmony_ci if (ctx->fbfetch_outputs) 118bf215546Sopenharmony_ci ctx->base.texture_barrier(&ctx->base, PIPE_TEXTURE_BARRIER_FRAMEBUFFER); 119bf215546Sopenharmony_ci} 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_cistatic struct zink_framebuffer_clear_data * 122bf215546Sopenharmony_ciadd_new_clear(struct zink_framebuffer_clear *fb_clear) 123bf215546Sopenharmony_ci{ 124bf215546Sopenharmony_ci struct zink_framebuffer_clear_data cd = {0}; 125bf215546Sopenharmony_ci util_dynarray_append(&fb_clear->clears, struct zink_framebuffer_clear_data, cd); 126bf215546Sopenharmony_ci return zink_fb_clear_element(fb_clear, zink_fb_clear_count(fb_clear) - 1); 127bf215546Sopenharmony_ci} 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_cistatic struct zink_framebuffer_clear_data * 130bf215546Sopenharmony_ciget_clear_data(struct zink_context *ctx, struct zink_framebuffer_clear *fb_clear, const struct pipe_scissor_state *scissor_state) 131bf215546Sopenharmony_ci{ 132bf215546Sopenharmony_ci unsigned num_clears = zink_fb_clear_count(fb_clear); 133bf215546Sopenharmony_ci if (num_clears) { 134bf215546Sopenharmony_ci struct zink_framebuffer_clear_data *last_clear = zink_fb_clear_element(fb_clear, num_clears - 1); 135bf215546Sopenharmony_ci /* if we're completely overwriting the previous clear, merge this into the previous clear */ 136bf215546Sopenharmony_ci if (!scissor_state || (last_clear->has_scissor && scissor_states_equal(&last_clear->scissor, scissor_state))) 137bf215546Sopenharmony_ci return last_clear; 138bf215546Sopenharmony_ci } 139bf215546Sopenharmony_ci return add_new_clear(fb_clear); 140bf215546Sopenharmony_ci} 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_cistatic void 143bf215546Sopenharmony_ciclamp_color(const struct util_format_description *desc, union pipe_color_union *dst, const union pipe_color_union *src, unsigned i) 144bf215546Sopenharmony_ci{ 145bf215546Sopenharmony_ci int non_void = util_format_get_first_non_void_channel(desc->format); 146bf215546Sopenharmony_ci switch (desc->channel[i].type) { 147bf215546Sopenharmony_ci case UTIL_FORMAT_TYPE_VOID: 148bf215546Sopenharmony_ci if (desc->channel[non_void].type == UTIL_FORMAT_TYPE_FLOAT) { 149bf215546Sopenharmony_ci dst->f[i] = uif(UINT32_MAX); 150bf215546Sopenharmony_ci } else { 151bf215546Sopenharmony_ci if (desc->channel[non_void].normalized) 152bf215546Sopenharmony_ci dst->f[i] = 1.0; 153bf215546Sopenharmony_ci else if (desc->channel[non_void].type == UTIL_FORMAT_TYPE_SIGNED) 154bf215546Sopenharmony_ci dst->i[i] = INT32_MAX; 155bf215546Sopenharmony_ci else 156bf215546Sopenharmony_ci dst->ui[i] = UINT32_MAX; 157bf215546Sopenharmony_ci } 158bf215546Sopenharmony_ci break; 159bf215546Sopenharmony_ci case UTIL_FORMAT_TYPE_SIGNED: 160bf215546Sopenharmony_ci if (desc->channel[i].normalized) 161bf215546Sopenharmony_ci dst->i[i] = src->i[i]; 162bf215546Sopenharmony_ci else { 163bf215546Sopenharmony_ci dst->i[i] = MAX2(src->i[i], -(1<<(desc->channel[i].size - 1))); 164bf215546Sopenharmony_ci dst->i[i] = MIN2(dst->i[i], (1 << (desc->channel[i].size - 1)) - 1); 165bf215546Sopenharmony_ci } 166bf215546Sopenharmony_ci break; 167bf215546Sopenharmony_ci case UTIL_FORMAT_TYPE_UNSIGNED: 168bf215546Sopenharmony_ci if (desc->channel[i].normalized) 169bf215546Sopenharmony_ci dst->ui[i] = src->ui[i]; 170bf215546Sopenharmony_ci else 171bf215546Sopenharmony_ci dst->ui[i] = MIN2(src->ui[i], BITFIELD_MASK(desc->channel[i].size)); 172bf215546Sopenharmony_ci break; 173bf215546Sopenharmony_ci case UTIL_FORMAT_TYPE_FIXED: 174bf215546Sopenharmony_ci case UTIL_FORMAT_TYPE_FLOAT: 175bf215546Sopenharmony_ci dst->ui[i] = src->ui[i]; 176bf215546Sopenharmony_ci break; 177bf215546Sopenharmony_ci } 178bf215546Sopenharmony_ci} 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_civoid 181bf215546Sopenharmony_cizink_clear(struct pipe_context *pctx, 182bf215546Sopenharmony_ci unsigned buffers, 183bf215546Sopenharmony_ci const struct pipe_scissor_state *scissor_state, 184bf215546Sopenharmony_ci const union pipe_color_union *pcolor, 185bf215546Sopenharmony_ci double depth, unsigned stencil) 186bf215546Sopenharmony_ci{ 187bf215546Sopenharmony_ci struct zink_context *ctx = zink_context(pctx); 188bf215546Sopenharmony_ci struct pipe_framebuffer_state *fb = &ctx->fb_state; 189bf215546Sopenharmony_ci struct zink_batch *batch = &ctx->batch; 190bf215546Sopenharmony_ci bool needs_rp = false; 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci if (unlikely(!zink_screen(pctx->screen)->info.have_EXT_conditional_rendering && !zink_check_conditional_render(ctx))) 193bf215546Sopenharmony_ci return; 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci if (scissor_state) { 196bf215546Sopenharmony_ci struct u_rect scissor = {scissor_state->minx, scissor_state->maxx, scissor_state->miny, scissor_state->maxy}; 197bf215546Sopenharmony_ci needs_rp = !zink_blit_region_fills(scissor, fb->width, fb->height); 198bf215546Sopenharmony_ci } 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci if (unlikely(ctx->fb_layer_mismatch)) { 201bf215546Sopenharmony_ci /* this is a terrible scenario: 202bf215546Sopenharmony_ci * at least one attachment has a layerCount greater than the others, 203bf215546Sopenharmony_ci * so iterate over all the mismatched attachments and pre-clear them separately, 204bf215546Sopenharmony_ci * then continue to flag them as need (additional) clearing 205bf215546Sopenharmony_ci * to avoid loadOp=LOAD 206bf215546Sopenharmony_ci */ 207bf215546Sopenharmony_ci unsigned x = 0; 208bf215546Sopenharmony_ci unsigned y = 0; 209bf215546Sopenharmony_ci unsigned w = ctx->fb_state.width; 210bf215546Sopenharmony_ci unsigned h = ctx->fb_state.height; 211bf215546Sopenharmony_ci if (scissor_state) { 212bf215546Sopenharmony_ci x = scissor_state->minx; 213bf215546Sopenharmony_ci y = scissor_state->miny; 214bf215546Sopenharmony_ci w = scissor_state->minx + scissor_state->maxx; 215bf215546Sopenharmony_ci h = scissor_state->miny + scissor_state->maxy; 216bf215546Sopenharmony_ci } 217bf215546Sopenharmony_ci unsigned clear_buffers = buffers >> 2; 218bf215546Sopenharmony_ci for (unsigned i = 0; i < ctx->fb_state.nr_cbufs; i++) { 219bf215546Sopenharmony_ci if (ctx->fb_state.cbufs[i] && 220bf215546Sopenharmony_ci (ctx->fb_layer_mismatch & clear_buffers & BITFIELD_BIT(i))) { 221bf215546Sopenharmony_ci if (ctx->void_clears & (PIPE_CLEAR_COLOR0 << i)) { 222bf215546Sopenharmony_ci union pipe_color_union color; 223bf215546Sopenharmony_ci color.f[0] = color.f[1] = color.f[2] = 0; 224bf215546Sopenharmony_ci color.f[3] = 1.0; 225bf215546Sopenharmony_ci pctx->clear_render_target(pctx, ctx->fb_state.cbufs[i], &color, 226bf215546Sopenharmony_ci 0, 0, 227bf215546Sopenharmony_ci ctx->fb_state.cbufs[i]->width, ctx->fb_state.cbufs[i]->height, 228bf215546Sopenharmony_ci ctx->render_condition_active); 229bf215546Sopenharmony_ci } 230bf215546Sopenharmony_ci pctx->clear_render_target(pctx, ctx->fb_state.cbufs[i], pcolor, 231bf215546Sopenharmony_ci x, y, w, h, ctx->render_condition_active); 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci } 234bf215546Sopenharmony_ci if (ctx->fb_state.zsbuf && (buffers & PIPE_CLEAR_DEPTHSTENCIL)) 235bf215546Sopenharmony_ci pctx->clear_depth_stencil(pctx, ctx->fb_state.zsbuf, buffers & PIPE_CLEAR_DEPTHSTENCIL, depth, stencil, 236bf215546Sopenharmony_ci x, y, w, h, ctx->render_condition_active); 237bf215546Sopenharmony_ci } 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci if (batch->in_rp) { 240bf215546Sopenharmony_ci clear_in_rp(pctx, buffers, scissor_state, pcolor, depth, stencil); 241bf215546Sopenharmony_ci return; 242bf215546Sopenharmony_ci } 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci unsigned rp_clears_enabled = ctx->rp_clears_enabled; 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci if (ctx->void_clears & buffers) { 247bf215546Sopenharmony_ci unsigned void_clears = ctx->void_clears & buffers; 248bf215546Sopenharmony_ci ctx->void_clears &= ~buffers; 249bf215546Sopenharmony_ci union pipe_color_union color; 250bf215546Sopenharmony_ci color.f[0] = color.f[1] = color.f[2] = 0; 251bf215546Sopenharmony_ci color.f[3] = 1.0; 252bf215546Sopenharmony_ci for (unsigned i = 0; i < fb->nr_cbufs; i++) { 253bf215546Sopenharmony_ci if ((void_clears & (PIPE_CLEAR_COLOR0 << i)) && fb->cbufs[i]) { 254bf215546Sopenharmony_ci struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i]; 255bf215546Sopenharmony_ci unsigned num_clears = zink_fb_clear_count(fb_clear); 256bf215546Sopenharmony_ci if (num_clears) { 257bf215546Sopenharmony_ci if (zink_fb_clear_first_needs_explicit(fb_clear)) { 258bf215546Sopenharmony_ci /* a scissored clear exists: 259bf215546Sopenharmony_ci * - extend the clear array 260bf215546Sopenharmony_ci * - shift existing clears back by one position 261bf215546Sopenharmony_ci * - inject void clear base of array 262bf215546Sopenharmony_ci */ 263bf215546Sopenharmony_ci add_new_clear(fb_clear); 264bf215546Sopenharmony_ci struct zink_framebuffer_clear_data *clear = fb_clear->clears.data; 265bf215546Sopenharmony_ci memcpy(clear + 1, clear, num_clears); 266bf215546Sopenharmony_ci memcpy(&clear->color, &color, sizeof(color)); 267bf215546Sopenharmony_ci } else { 268bf215546Sopenharmony_ci /* no void clear needed */ 269bf215546Sopenharmony_ci } 270bf215546Sopenharmony_ci void_clears &= ~(PIPE_CLEAR_COLOR0 << i); 271bf215546Sopenharmony_ci } 272bf215546Sopenharmony_ci } 273bf215546Sopenharmony_ci } 274bf215546Sopenharmony_ci if (void_clears) 275bf215546Sopenharmony_ci pctx->clear(pctx, void_clears, NULL, &color, 0, 0); 276bf215546Sopenharmony_ci } 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci if (buffers & PIPE_CLEAR_COLOR) { 279bf215546Sopenharmony_ci for (unsigned i = 0; i < fb->nr_cbufs; i++) { 280bf215546Sopenharmony_ci if ((buffers & (PIPE_CLEAR_COLOR0 << i)) && fb->cbufs[i]) { 281bf215546Sopenharmony_ci struct pipe_surface *psurf = fb->cbufs[i]; 282bf215546Sopenharmony_ci const struct util_format_description *desc = util_format_description(psurf->format); 283bf215546Sopenharmony_ci struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i]; 284bf215546Sopenharmony_ci struct zink_framebuffer_clear_data *clear = get_clear_data(ctx, fb_clear, needs_rp ? scissor_state : NULL); 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci ctx->clears_enabled |= PIPE_CLEAR_COLOR0 << i; 287bf215546Sopenharmony_ci clear->conditional = ctx->render_condition_active; 288bf215546Sopenharmony_ci clear->has_scissor = needs_rp; 289bf215546Sopenharmony_ci if (scissor_state && needs_rp) 290bf215546Sopenharmony_ci clear->scissor = *scissor_state; 291bf215546Sopenharmony_ci for (unsigned i = 0; i < 4; i++) 292bf215546Sopenharmony_ci clamp_color(desc, &clear->color, pcolor, i); 293bf215546Sopenharmony_ci if (zink_fb_clear_first_needs_explicit(fb_clear)) 294bf215546Sopenharmony_ci ctx->rp_clears_enabled &= ~(PIPE_CLEAR_COLOR0 << i); 295bf215546Sopenharmony_ci else 296bf215546Sopenharmony_ci ctx->rp_clears_enabled |= PIPE_CLEAR_COLOR0 << i; 297bf215546Sopenharmony_ci } 298bf215546Sopenharmony_ci } 299bf215546Sopenharmony_ci } 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci if (buffers & PIPE_CLEAR_DEPTHSTENCIL && fb->zsbuf) { 302bf215546Sopenharmony_ci struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[PIPE_MAX_COLOR_BUFS]; 303bf215546Sopenharmony_ci struct zink_framebuffer_clear_data *clear = get_clear_data(ctx, fb_clear, needs_rp ? scissor_state : NULL); 304bf215546Sopenharmony_ci ctx->clears_enabled |= PIPE_CLEAR_DEPTHSTENCIL; 305bf215546Sopenharmony_ci clear->conditional = ctx->render_condition_active; 306bf215546Sopenharmony_ci clear->has_scissor = needs_rp; 307bf215546Sopenharmony_ci if (scissor_state && needs_rp) 308bf215546Sopenharmony_ci clear->scissor = *scissor_state; 309bf215546Sopenharmony_ci if (buffers & PIPE_CLEAR_DEPTH) 310bf215546Sopenharmony_ci clear->zs.depth = depth; 311bf215546Sopenharmony_ci if (buffers & PIPE_CLEAR_STENCIL) 312bf215546Sopenharmony_ci clear->zs.stencil = stencil; 313bf215546Sopenharmony_ci clear->zs.bits |= (buffers & PIPE_CLEAR_DEPTHSTENCIL); 314bf215546Sopenharmony_ci if (zink_fb_clear_first_needs_explicit(fb_clear)) 315bf215546Sopenharmony_ci ctx->rp_clears_enabled &= ~PIPE_CLEAR_DEPTHSTENCIL; 316bf215546Sopenharmony_ci else 317bf215546Sopenharmony_ci ctx->rp_clears_enabled |= (buffers & PIPE_CLEAR_DEPTHSTENCIL); 318bf215546Sopenharmony_ci } 319bf215546Sopenharmony_ci assert(!ctx->batch.in_rp); 320bf215546Sopenharmony_ci ctx->rp_changed |= ctx->rp_clears_enabled != rp_clears_enabled; 321bf215546Sopenharmony_ci} 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_cistatic inline bool 324bf215546Sopenharmony_cicolors_equal(union pipe_color_union *a, union pipe_color_union *b) 325bf215546Sopenharmony_ci{ 326bf215546Sopenharmony_ci 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]; 327bf215546Sopenharmony_ci} 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_civoid 330bf215546Sopenharmony_cizink_clear_framebuffer(struct zink_context *ctx, unsigned clear_buffers) 331bf215546Sopenharmony_ci{ 332bf215546Sopenharmony_ci unsigned to_clear = 0; 333bf215546Sopenharmony_ci struct pipe_framebuffer_state *fb_state = &ctx->fb_state; 334bf215546Sopenharmony_ci#ifndef NDEBUG 335bf215546Sopenharmony_ci assert(!(clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) || zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS)); 336bf215546Sopenharmony_ci for (int i = 0; i < fb_state->nr_cbufs && clear_buffers >= PIPE_CLEAR_COLOR0; i++) { 337bf215546Sopenharmony_ci assert(!(clear_buffers & (PIPE_CLEAR_COLOR0 << i)) || zink_fb_clear_enabled(ctx, i)); 338bf215546Sopenharmony_ci } 339bf215546Sopenharmony_ci#endif 340bf215546Sopenharmony_ci while (clear_buffers) { 341bf215546Sopenharmony_ci struct zink_framebuffer_clear *color_clear = NULL; 342bf215546Sopenharmony_ci struct zink_framebuffer_clear *zs_clear = NULL; 343bf215546Sopenharmony_ci unsigned num_clears = 0; 344bf215546Sopenharmony_ci for (int i = 0; i < fb_state->nr_cbufs && clear_buffers >= PIPE_CLEAR_COLOR0; i++) { 345bf215546Sopenharmony_ci struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i]; 346bf215546Sopenharmony_ci /* these need actual clear calls inside the rp */ 347bf215546Sopenharmony_ci if (!(clear_buffers & (PIPE_CLEAR_COLOR0 << i))) 348bf215546Sopenharmony_ci continue; 349bf215546Sopenharmony_ci if (color_clear) { 350bf215546Sopenharmony_ci /* different number of clears -> do another clear */ 351bf215546Sopenharmony_ci //XXX: could potentially merge "some" of the clears into this one for a very, very small optimization 352bf215546Sopenharmony_ci if (num_clears != zink_fb_clear_count(fb_clear)) 353bf215546Sopenharmony_ci goto out; 354bf215546Sopenharmony_ci /* compare all the clears to determine if we can batch these buffers together */ 355bf215546Sopenharmony_ci for (int j = !zink_fb_clear_first_needs_explicit(fb_clear); j < num_clears; j++) { 356bf215546Sopenharmony_ci struct zink_framebuffer_clear_data *a = zink_fb_clear_element(color_clear, j); 357bf215546Sopenharmony_ci struct zink_framebuffer_clear_data *b = zink_fb_clear_element(fb_clear, j); 358bf215546Sopenharmony_ci /* scissors don't match, fire this one off */ 359bf215546Sopenharmony_ci if (a->has_scissor != b->has_scissor || (a->has_scissor && !scissor_states_equal(&a->scissor, &b->scissor))) 360bf215546Sopenharmony_ci goto out; 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ci /* colors don't match, fire this one off */ 363bf215546Sopenharmony_ci if (!colors_equal(&a->color, &b->color)) 364bf215546Sopenharmony_ci goto out; 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci } else { 367bf215546Sopenharmony_ci color_clear = fb_clear; 368bf215546Sopenharmony_ci num_clears = zink_fb_clear_count(fb_clear); 369bf215546Sopenharmony_ci } 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci clear_buffers &= ~(PIPE_CLEAR_COLOR0 << i); 372bf215546Sopenharmony_ci to_clear |= (PIPE_CLEAR_COLOR0 << i); 373bf215546Sopenharmony_ci } 374bf215546Sopenharmony_ci clear_buffers &= ~PIPE_CLEAR_COLOR; 375bf215546Sopenharmony_ci if (clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) { 376bf215546Sopenharmony_ci struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[PIPE_MAX_COLOR_BUFS]; 377bf215546Sopenharmony_ci if (color_clear) { 378bf215546Sopenharmony_ci if (num_clears != zink_fb_clear_count(fb_clear)) 379bf215546Sopenharmony_ci goto out; 380bf215546Sopenharmony_ci /* compare all the clears to determine if we can batch these buffers together */ 381bf215546Sopenharmony_ci for (int j = !zink_fb_clear_first_needs_explicit(fb_clear); j < zink_fb_clear_count(color_clear); j++) { 382bf215546Sopenharmony_ci struct zink_framebuffer_clear_data *a = zink_fb_clear_element(color_clear, j); 383bf215546Sopenharmony_ci struct zink_framebuffer_clear_data *b = zink_fb_clear_element(fb_clear, j); 384bf215546Sopenharmony_ci /* scissors don't match, fire this one off */ 385bf215546Sopenharmony_ci if (a->has_scissor != b->has_scissor || (a->has_scissor && !scissor_states_equal(&a->scissor, &b->scissor))) 386bf215546Sopenharmony_ci goto out; 387bf215546Sopenharmony_ci } 388bf215546Sopenharmony_ci } 389bf215546Sopenharmony_ci zs_clear = fb_clear; 390bf215546Sopenharmony_ci to_clear |= (clear_buffers & PIPE_CLEAR_DEPTHSTENCIL); 391bf215546Sopenharmony_ci clear_buffers &= ~PIPE_CLEAR_DEPTHSTENCIL; 392bf215546Sopenharmony_ci } 393bf215546Sopenharmony_ciout: 394bf215546Sopenharmony_ci if (to_clear) { 395bf215546Sopenharmony_ci if (num_clears) { 396bf215546Sopenharmony_ci for (int j = !zink_fb_clear_first_needs_explicit(color_clear); j < num_clears; j++) { 397bf215546Sopenharmony_ci struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(color_clear, j); 398bf215546Sopenharmony_ci struct zink_framebuffer_clear_data *zsclear = NULL; 399bf215546Sopenharmony_ci /* zs bits are both set here if those aspects should be cleared at some point */ 400bf215546Sopenharmony_ci unsigned clear_bits = to_clear & ~PIPE_CLEAR_DEPTHSTENCIL; 401bf215546Sopenharmony_ci if (zs_clear) { 402bf215546Sopenharmony_ci zsclear = zink_fb_clear_element(zs_clear, j); 403bf215546Sopenharmony_ci clear_bits |= zsclear->zs.bits; 404bf215546Sopenharmony_ci } 405bf215546Sopenharmony_ci zink_clear(&ctx->base, clear_bits, 406bf215546Sopenharmony_ci clear->has_scissor ? &clear->scissor : NULL, 407bf215546Sopenharmony_ci &clear->color, 408bf215546Sopenharmony_ci zsclear ? zsclear->zs.depth : 0, 409bf215546Sopenharmony_ci zsclear ? zsclear->zs.stencil : 0); 410bf215546Sopenharmony_ci } 411bf215546Sopenharmony_ci } else { 412bf215546Sopenharmony_ci for (int j = !zink_fb_clear_first_needs_explicit(zs_clear); j < zink_fb_clear_count(zs_clear); j++) { 413bf215546Sopenharmony_ci struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(zs_clear, j); 414bf215546Sopenharmony_ci zink_clear(&ctx->base, clear->zs.bits, 415bf215546Sopenharmony_ci clear->has_scissor ? &clear->scissor : NULL, 416bf215546Sopenharmony_ci NULL, 417bf215546Sopenharmony_ci clear->zs.depth, 418bf215546Sopenharmony_ci clear->zs.stencil); 419bf215546Sopenharmony_ci } 420bf215546Sopenharmony_ci } 421bf215546Sopenharmony_ci } 422bf215546Sopenharmony_ci to_clear = 0; 423bf215546Sopenharmony_ci } 424bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(ctx->fb_clears); i++) 425bf215546Sopenharmony_ci zink_fb_clear_reset(ctx, i); 426bf215546Sopenharmony_ci} 427bf215546Sopenharmony_ci 428bf215546Sopenharmony_cistatic struct pipe_surface * 429bf215546Sopenharmony_cicreate_clear_surface(struct pipe_context *pctx, struct pipe_resource *pres, unsigned level, const struct pipe_box *box) 430bf215546Sopenharmony_ci{ 431bf215546Sopenharmony_ci struct pipe_surface tmpl = {{0}}; 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_ci tmpl.format = pres->format; 434bf215546Sopenharmony_ci tmpl.u.tex.first_layer = box->z; 435bf215546Sopenharmony_ci tmpl.u.tex.last_layer = box->z + box->depth - 1; 436bf215546Sopenharmony_ci tmpl.u.tex.level = level; 437bf215546Sopenharmony_ci return pctx->create_surface(pctx, pres, &tmpl); 438bf215546Sopenharmony_ci} 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_cistatic void 441bf215546Sopenharmony_ciset_clear_fb(struct pipe_context *pctx, struct pipe_surface *psurf, struct pipe_surface *zsurf) 442bf215546Sopenharmony_ci{ 443bf215546Sopenharmony_ci struct pipe_framebuffer_state fb_state; 444bf215546Sopenharmony_ci fb_state.width = psurf ? psurf->width : zsurf->width; 445bf215546Sopenharmony_ci fb_state.height = psurf ? psurf->height : zsurf->height; 446bf215546Sopenharmony_ci fb_state.nr_cbufs = !!psurf; 447bf215546Sopenharmony_ci fb_state.cbufs[0] = psurf; 448bf215546Sopenharmony_ci fb_state.zsbuf = zsurf; 449bf215546Sopenharmony_ci pctx->set_framebuffer_state(pctx, &fb_state); 450bf215546Sopenharmony_ci} 451bf215546Sopenharmony_ci 452bf215546Sopenharmony_civoid 453bf215546Sopenharmony_cizink_clear_texture(struct pipe_context *pctx, 454bf215546Sopenharmony_ci struct pipe_resource *pres, 455bf215546Sopenharmony_ci unsigned level, 456bf215546Sopenharmony_ci const struct pipe_box *box, 457bf215546Sopenharmony_ci const void *data) 458bf215546Sopenharmony_ci{ 459bf215546Sopenharmony_ci struct zink_context *ctx = zink_context(pctx); 460bf215546Sopenharmony_ci struct zink_resource *res = zink_resource(pres); 461bf215546Sopenharmony_ci struct pipe_surface *surf = NULL; 462bf215546Sopenharmony_ci struct pipe_scissor_state scissor = {box->x, box->y, box->x + box->width, box->y + box->height}; 463bf215546Sopenharmony_ci 464bf215546Sopenharmony_ci if (res->aspect & VK_IMAGE_ASPECT_COLOR_BIT) { 465bf215546Sopenharmony_ci union pipe_color_union color; 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_ci util_format_unpack_rgba(pres->format, color.ui, data, 1); 468bf215546Sopenharmony_ci 469bf215546Sopenharmony_ci surf = create_clear_surface(pctx, pres, level, box); 470bf215546Sopenharmony_ci util_blitter_save_framebuffer(ctx->blitter, &ctx->fb_state); 471bf215546Sopenharmony_ci set_clear_fb(pctx, surf, NULL); 472bf215546Sopenharmony_ci pctx->clear(pctx, PIPE_CLEAR_COLOR0, &scissor, &color, 0, 0); 473bf215546Sopenharmony_ci util_blitter_restore_fb_state(ctx->blitter); 474bf215546Sopenharmony_ci } else { 475bf215546Sopenharmony_ci float depth = 0.0; 476bf215546Sopenharmony_ci uint8_t stencil = 0; 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_ci if (res->aspect & VK_IMAGE_ASPECT_DEPTH_BIT) 479bf215546Sopenharmony_ci util_format_unpack_z_float(pres->format, &depth, data, 1); 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci if (res->aspect & VK_IMAGE_ASPECT_STENCIL_BIT) 482bf215546Sopenharmony_ci util_format_unpack_s_8uint(pres->format, &stencil, data, 1); 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci unsigned flags = 0; 485bf215546Sopenharmony_ci if (res->aspect & VK_IMAGE_ASPECT_DEPTH_BIT) 486bf215546Sopenharmony_ci flags |= PIPE_CLEAR_DEPTH; 487bf215546Sopenharmony_ci if (res->aspect & VK_IMAGE_ASPECT_STENCIL_BIT) 488bf215546Sopenharmony_ci flags |= PIPE_CLEAR_STENCIL; 489bf215546Sopenharmony_ci surf = create_clear_surface(pctx, pres, level, box); 490bf215546Sopenharmony_ci util_blitter_save_framebuffer(ctx->blitter, &ctx->fb_state); 491bf215546Sopenharmony_ci set_clear_fb(pctx, NULL, surf); 492bf215546Sopenharmony_ci pctx->clear(pctx, flags, &scissor, NULL, depth, stencil); 493bf215546Sopenharmony_ci util_blitter_restore_fb_state(ctx->blitter); 494bf215546Sopenharmony_ci } 495bf215546Sopenharmony_ci /* this will never destroy the surface */ 496bf215546Sopenharmony_ci pipe_surface_reference(&surf, NULL); 497bf215546Sopenharmony_ci} 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_civoid 500bf215546Sopenharmony_cizink_clear_buffer(struct pipe_context *pctx, 501bf215546Sopenharmony_ci struct pipe_resource *pres, 502bf215546Sopenharmony_ci unsigned offset, 503bf215546Sopenharmony_ci unsigned size, 504bf215546Sopenharmony_ci const void *clear_value, 505bf215546Sopenharmony_ci int clear_value_size) 506bf215546Sopenharmony_ci{ 507bf215546Sopenharmony_ci struct zink_context *ctx = zink_context(pctx); 508bf215546Sopenharmony_ci struct zink_resource *res = zink_resource(pres); 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_ci uint32_t clamped; 511bf215546Sopenharmony_ci if (util_lower_clearsize_to_dword(clear_value, &clear_value_size, &clamped)) 512bf215546Sopenharmony_ci clear_value = &clamped; 513bf215546Sopenharmony_ci if (offset % 4 == 0 && size % 4 == 0 && clear_value_size == sizeof(uint32_t)) { 514bf215546Sopenharmony_ci /* 515bf215546Sopenharmony_ci - dstOffset is the byte offset into the buffer at which to start filling, 516bf215546Sopenharmony_ci and must be a multiple of 4. 517bf215546Sopenharmony_ci 518bf215546Sopenharmony_ci - size is the number of bytes to fill, and must be either a multiple of 4, 519bf215546Sopenharmony_ci or VK_WHOLE_SIZE to fill the range from offset to the end of the buffer 520bf215546Sopenharmony_ci */ 521bf215546Sopenharmony_ci struct zink_batch *batch = &ctx->batch; 522bf215546Sopenharmony_ci zink_batch_no_rp(ctx); 523bf215546Sopenharmony_ci zink_batch_reference_resource_rw(batch, res, true); 524bf215546Sopenharmony_ci util_range_add(&res->base.b, &res->valid_buffer_range, offset, offset + size); 525bf215546Sopenharmony_ci zink_resource_buffer_barrier(ctx, res, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); 526bf215546Sopenharmony_ci res->obj->unordered_read = res->obj->unordered_write = false; 527bf215546Sopenharmony_ci VKCTX(CmdFillBuffer)(batch->state->cmdbuf, res->obj->buffer, offset, size, *(uint32_t*)clear_value); 528bf215546Sopenharmony_ci return; 529bf215546Sopenharmony_ci } 530bf215546Sopenharmony_ci struct pipe_transfer *xfer; 531bf215546Sopenharmony_ci uint8_t *map = pipe_buffer_map_range(pctx, pres, offset, size, 532bf215546Sopenharmony_ci PIPE_MAP_WRITE | PIPE_MAP_ONCE | PIPE_MAP_DISCARD_RANGE, &xfer); 533bf215546Sopenharmony_ci if (!map) 534bf215546Sopenharmony_ci return; 535bf215546Sopenharmony_ci unsigned rem = size % clear_value_size; 536bf215546Sopenharmony_ci uint8_t *ptr = map; 537bf215546Sopenharmony_ci for (unsigned i = 0; i < (size - rem) / clear_value_size; i++) { 538bf215546Sopenharmony_ci memcpy(ptr, clear_value, clear_value_size); 539bf215546Sopenharmony_ci ptr += clear_value_size; 540bf215546Sopenharmony_ci } 541bf215546Sopenharmony_ci if (rem) 542bf215546Sopenharmony_ci memcpy(map + size - rem, clear_value, rem); 543bf215546Sopenharmony_ci pipe_buffer_unmap(pctx, xfer); 544bf215546Sopenharmony_ci} 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_civoid 547bf215546Sopenharmony_cizink_clear_render_target(struct pipe_context *pctx, struct pipe_surface *dst, 548bf215546Sopenharmony_ci const union pipe_color_union *color, unsigned dstx, 549bf215546Sopenharmony_ci unsigned dsty, unsigned width, unsigned height, 550bf215546Sopenharmony_ci bool render_condition_enabled) 551bf215546Sopenharmony_ci{ 552bf215546Sopenharmony_ci struct zink_context *ctx = zink_context(pctx); 553bf215546Sopenharmony_ci bool render_condition_active = ctx->render_condition_active; 554bf215546Sopenharmony_ci if (!render_condition_enabled && render_condition_active) { 555bf215546Sopenharmony_ci zink_stop_conditional_render(ctx); 556bf215546Sopenharmony_ci ctx->render_condition_active = false; 557bf215546Sopenharmony_ci } 558bf215546Sopenharmony_ci util_blitter_save_framebuffer(ctx->blitter, &ctx->fb_state); 559bf215546Sopenharmony_ci set_clear_fb(pctx, dst, NULL); 560bf215546Sopenharmony_ci struct pipe_scissor_state scissor = {dstx, dsty, dstx + width, dsty + height}; 561bf215546Sopenharmony_ci pctx->clear(pctx, PIPE_CLEAR_COLOR0, &scissor, color, 0, 0); 562bf215546Sopenharmony_ci util_blitter_restore_fb_state(ctx->blitter); 563bf215546Sopenharmony_ci if (!render_condition_enabled && render_condition_active) 564bf215546Sopenharmony_ci zink_start_conditional_render(ctx); 565bf215546Sopenharmony_ci ctx->render_condition_active = render_condition_active; 566bf215546Sopenharmony_ci} 567bf215546Sopenharmony_ci 568bf215546Sopenharmony_civoid 569bf215546Sopenharmony_cizink_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *dst, 570bf215546Sopenharmony_ci unsigned clear_flags, double depth, unsigned stencil, 571bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned width, unsigned height, 572bf215546Sopenharmony_ci bool render_condition_enabled) 573bf215546Sopenharmony_ci{ 574bf215546Sopenharmony_ci struct zink_context *ctx = zink_context(pctx); 575bf215546Sopenharmony_ci bool render_condition_active = ctx->render_condition_active; 576bf215546Sopenharmony_ci if (!render_condition_enabled && render_condition_active) { 577bf215546Sopenharmony_ci zink_stop_conditional_render(ctx); 578bf215546Sopenharmony_ci ctx->render_condition_active = false; 579bf215546Sopenharmony_ci } 580bf215546Sopenharmony_ci bool cur_attachment = zink_csurface(ctx->fb_state.zsbuf) == zink_csurface(dst); 581bf215546Sopenharmony_ci if (dstx > ctx->fb_state.width || dsty > ctx->fb_state.height || 582bf215546Sopenharmony_ci dstx + width > ctx->fb_state.width || 583bf215546Sopenharmony_ci dsty + height > ctx->fb_state.height) 584bf215546Sopenharmony_ci cur_attachment = false; 585bf215546Sopenharmony_ci if (!cur_attachment) { 586bf215546Sopenharmony_ci util_blitter_save_framebuffer(ctx->blitter, &ctx->fb_state); 587bf215546Sopenharmony_ci set_clear_fb(pctx, NULL, dst); 588bf215546Sopenharmony_ci } 589bf215546Sopenharmony_ci struct pipe_scissor_state scissor = {dstx, dsty, dstx + width, dsty + height}; 590bf215546Sopenharmony_ci pctx->clear(pctx, clear_flags, &scissor, NULL, depth, stencil); 591bf215546Sopenharmony_ci if (!cur_attachment) 592bf215546Sopenharmony_ci util_blitter_restore_fb_state(ctx->blitter); 593bf215546Sopenharmony_ci if (!render_condition_enabled && render_condition_active) 594bf215546Sopenharmony_ci zink_start_conditional_render(ctx); 595bf215546Sopenharmony_ci ctx->render_condition_active = render_condition_active; 596bf215546Sopenharmony_ci} 597bf215546Sopenharmony_ci 598bf215546Sopenharmony_cibool 599bf215546Sopenharmony_cizink_fb_clear_needs_explicit(struct zink_framebuffer_clear *fb_clear) 600bf215546Sopenharmony_ci{ 601bf215546Sopenharmony_ci if (zink_fb_clear_count(fb_clear) != 1) 602bf215546Sopenharmony_ci return true; 603bf215546Sopenharmony_ci return zink_fb_clear_element_needs_explicit(zink_fb_clear_element(fb_clear, 0)); 604bf215546Sopenharmony_ci} 605bf215546Sopenharmony_ci 606bf215546Sopenharmony_cibool 607bf215546Sopenharmony_cizink_fb_clear_first_needs_explicit(struct zink_framebuffer_clear *fb_clear) 608bf215546Sopenharmony_ci{ 609bf215546Sopenharmony_ci if (!zink_fb_clear_count(fb_clear)) 610bf215546Sopenharmony_ci return false; 611bf215546Sopenharmony_ci return zink_fb_clear_element_needs_explicit(zink_fb_clear_element(fb_clear, 0)); 612bf215546Sopenharmony_ci} 613bf215546Sopenharmony_ci 614bf215546Sopenharmony_cistatic void 615bf215546Sopenharmony_cifb_clears_apply_internal(struct zink_context *ctx, struct pipe_resource *pres, int i) 616bf215546Sopenharmony_ci{ 617bf215546Sopenharmony_ci if (!zink_fb_clear_enabled(ctx, i)) 618bf215546Sopenharmony_ci return; 619bf215546Sopenharmony_ci if (ctx->batch.in_rp) 620bf215546Sopenharmony_ci zink_clear_framebuffer(ctx, BITFIELD_BIT(i)); 621bf215546Sopenharmony_ci else 622bf215546Sopenharmony_ci /* this will automatically trigger all the clears */ 623bf215546Sopenharmony_ci zink_batch_rp(ctx); 624bf215546Sopenharmony_ci zink_fb_clear_reset(ctx, i); 625bf215546Sopenharmony_ci} 626bf215546Sopenharmony_ci 627bf215546Sopenharmony_civoid 628bf215546Sopenharmony_cizink_fb_clear_reset(struct zink_context *ctx, unsigned i) 629bf215546Sopenharmony_ci{ 630bf215546Sopenharmony_ci unsigned rp_clears_enabled = ctx->clears_enabled; 631bf215546Sopenharmony_ci util_dynarray_clear(&ctx->fb_clears[i].clears); 632bf215546Sopenharmony_ci if (i == PIPE_MAX_COLOR_BUFS) { 633bf215546Sopenharmony_ci ctx->clears_enabled &= ~PIPE_CLEAR_DEPTHSTENCIL; 634bf215546Sopenharmony_ci ctx->rp_clears_enabled &= ~PIPE_CLEAR_DEPTHSTENCIL; 635bf215546Sopenharmony_ci } else { 636bf215546Sopenharmony_ci ctx->clears_enabled &= ~(PIPE_CLEAR_COLOR0 << i); 637bf215546Sopenharmony_ci ctx->rp_clears_enabled &= ~(PIPE_CLEAR_COLOR0 << i); 638bf215546Sopenharmony_ci } 639bf215546Sopenharmony_ci if (ctx->rp_clears_enabled != rp_clears_enabled) 640bf215546Sopenharmony_ci ctx->rp_loadop_changed = true; 641bf215546Sopenharmony_ci} 642bf215546Sopenharmony_ci 643bf215546Sopenharmony_civoid 644bf215546Sopenharmony_cizink_fb_clears_apply(struct zink_context *ctx, struct pipe_resource *pres) 645bf215546Sopenharmony_ci{ 646bf215546Sopenharmony_ci if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) { 647bf215546Sopenharmony_ci for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) { 648bf215546Sopenharmony_ci if (ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture == pres) { 649bf215546Sopenharmony_ci fb_clears_apply_internal(ctx, pres, i); 650bf215546Sopenharmony_ci } 651bf215546Sopenharmony_ci } 652bf215546Sopenharmony_ci } else { 653bf215546Sopenharmony_ci if (ctx->fb_state.zsbuf && ctx->fb_state.zsbuf->texture == pres) { 654bf215546Sopenharmony_ci fb_clears_apply_internal(ctx, pres, PIPE_MAX_COLOR_BUFS); 655bf215546Sopenharmony_ci } 656bf215546Sopenharmony_ci } 657bf215546Sopenharmony_ci} 658bf215546Sopenharmony_ci 659bf215546Sopenharmony_civoid 660bf215546Sopenharmony_cizink_fb_clears_discard(struct zink_context *ctx, struct pipe_resource *pres) 661bf215546Sopenharmony_ci{ 662bf215546Sopenharmony_ci if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) { 663bf215546Sopenharmony_ci for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) { 664bf215546Sopenharmony_ci if (ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture == pres) { 665bf215546Sopenharmony_ci if (zink_fb_clear_enabled(ctx, i)) { 666bf215546Sopenharmony_ci zink_fb_clear_reset(ctx, i); 667bf215546Sopenharmony_ci } 668bf215546Sopenharmony_ci } 669bf215546Sopenharmony_ci } 670bf215546Sopenharmony_ci } else { 671bf215546Sopenharmony_ci if (zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS) && ctx->fb_state.zsbuf && ctx->fb_state.zsbuf->texture == pres) { 672bf215546Sopenharmony_ci int i = PIPE_MAX_COLOR_BUFS; 673bf215546Sopenharmony_ci zink_fb_clear_reset(ctx, i); 674bf215546Sopenharmony_ci } 675bf215546Sopenharmony_ci } 676bf215546Sopenharmony_ci} 677bf215546Sopenharmony_ci 678bf215546Sopenharmony_civoid 679bf215546Sopenharmony_cizink_clear_apply_conditionals(struct zink_context *ctx) 680bf215546Sopenharmony_ci{ 681bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(ctx->fb_clears); i++) { 682bf215546Sopenharmony_ci struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i]; 683bf215546Sopenharmony_ci if (!zink_fb_clear_enabled(ctx, i)) 684bf215546Sopenharmony_ci continue; 685bf215546Sopenharmony_ci for (int j = 0; j < zink_fb_clear_count(fb_clear); j++) { 686bf215546Sopenharmony_ci struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, j); 687bf215546Sopenharmony_ci if (clear->conditional) { 688bf215546Sopenharmony_ci struct pipe_surface *surf; 689bf215546Sopenharmony_ci if (i < PIPE_MAX_COLOR_BUFS) 690bf215546Sopenharmony_ci surf = ctx->fb_state.cbufs[i]; 691bf215546Sopenharmony_ci else 692bf215546Sopenharmony_ci surf = ctx->fb_state.zsbuf; 693bf215546Sopenharmony_ci if (surf) 694bf215546Sopenharmony_ci fb_clears_apply_internal(ctx, surf->texture, i); 695bf215546Sopenharmony_ci else 696bf215546Sopenharmony_ci zink_fb_clear_reset(ctx, i); 697bf215546Sopenharmony_ci break; 698bf215546Sopenharmony_ci } 699bf215546Sopenharmony_ci } 700bf215546Sopenharmony_ci } 701bf215546Sopenharmony_ci} 702bf215546Sopenharmony_ci 703bf215546Sopenharmony_cistatic void 704bf215546Sopenharmony_cifb_clears_apply_or_discard_internal(struct zink_context *ctx, struct pipe_resource *pres, struct u_rect region, bool discard_only, bool invert, int i) 705bf215546Sopenharmony_ci{ 706bf215546Sopenharmony_ci struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i]; 707bf215546Sopenharmony_ci if (zink_fb_clear_enabled(ctx, i)) { 708bf215546Sopenharmony_ci if (zink_blit_region_fills(region, pres->width0, pres->height0)) { 709bf215546Sopenharmony_ci if (invert) 710bf215546Sopenharmony_ci fb_clears_apply_internal(ctx, pres, i); 711bf215546Sopenharmony_ci else 712bf215546Sopenharmony_ci /* we know we can skip these */ 713bf215546Sopenharmony_ci zink_fb_clears_discard(ctx, pres); 714bf215546Sopenharmony_ci return; 715bf215546Sopenharmony_ci } 716bf215546Sopenharmony_ci for (int j = 0; j < zink_fb_clear_count(fb_clear); j++) { 717bf215546Sopenharmony_ci struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, j); 718bf215546Sopenharmony_ci struct u_rect scissor = {clear->scissor.minx, clear->scissor.maxx, 719bf215546Sopenharmony_ci clear->scissor.miny, clear->scissor.maxy}; 720bf215546Sopenharmony_ci if (!clear->has_scissor || zink_blit_region_covers(region, scissor)) { 721bf215546Sopenharmony_ci /* this is a clear that isn't fully covered by our pending write */ 722bf215546Sopenharmony_ci if (!discard_only) 723bf215546Sopenharmony_ci fb_clears_apply_internal(ctx, pres, i); 724bf215546Sopenharmony_ci return; 725bf215546Sopenharmony_ci } 726bf215546Sopenharmony_ci } 727bf215546Sopenharmony_ci if (!invert) 728bf215546Sopenharmony_ci /* if we haven't already returned, then we know we can discard */ 729bf215546Sopenharmony_ci zink_fb_clears_discard(ctx, pres); 730bf215546Sopenharmony_ci } 731bf215546Sopenharmony_ci} 732bf215546Sopenharmony_ci 733bf215546Sopenharmony_civoid 734bf215546Sopenharmony_cizink_fb_clears_apply_or_discard(struct zink_context *ctx, struct pipe_resource *pres, struct u_rect region, bool discard_only) 735bf215546Sopenharmony_ci{ 736bf215546Sopenharmony_ci if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) { 737bf215546Sopenharmony_ci for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) { 738bf215546Sopenharmony_ci if (ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture == pres) { 739bf215546Sopenharmony_ci fb_clears_apply_or_discard_internal(ctx, pres, region, discard_only, false, i); 740bf215546Sopenharmony_ci } 741bf215546Sopenharmony_ci } 742bf215546Sopenharmony_ci } else { 743bf215546Sopenharmony_ci if (zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS) && ctx->fb_state.zsbuf && ctx->fb_state.zsbuf->texture == pres) { 744bf215546Sopenharmony_ci fb_clears_apply_or_discard_internal(ctx, pres, region, discard_only, false, PIPE_MAX_COLOR_BUFS); 745bf215546Sopenharmony_ci } 746bf215546Sopenharmony_ci } 747bf215546Sopenharmony_ci} 748bf215546Sopenharmony_ci 749bf215546Sopenharmony_civoid 750bf215546Sopenharmony_cizink_fb_clears_apply_region(struct zink_context *ctx, struct pipe_resource *pres, struct u_rect region) 751bf215546Sopenharmony_ci{ 752bf215546Sopenharmony_ci if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) { 753bf215546Sopenharmony_ci for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) { 754bf215546Sopenharmony_ci if (ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture == pres) { 755bf215546Sopenharmony_ci fb_clears_apply_or_discard_internal(ctx, pres, region, false, true, i); 756bf215546Sopenharmony_ci } 757bf215546Sopenharmony_ci } 758bf215546Sopenharmony_ci } else { 759bf215546Sopenharmony_ci if (ctx->fb_state.zsbuf && ctx->fb_state.zsbuf->texture == pres) { 760bf215546Sopenharmony_ci fb_clears_apply_or_discard_internal(ctx, pres, region, false, true, PIPE_MAX_COLOR_BUFS); 761bf215546Sopenharmony_ci } 762bf215546Sopenharmony_ci } 763bf215546Sopenharmony_ci} 764