Path: blob/21.2-virgl/src/gallium/drivers/zink/zink_clear.c
4570 views
/*1* Copyright 2018 Collabora Ltd.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* on the rights to use, copy, modify, merge, publish, distribute, sub7* license, and/or sell copies of the Software, and to permit persons to whom8* the Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,18* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR19* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE20* USE OR OTHER DEALINGS IN THE SOFTWARE.21*/2223#include "zink_context.h"24#include "zink_query.h"25#include "zink_resource.h"26#include "zink_screen.h"2728#include "util/u_blitter.h"29#include "util/u_dynarray.h"30#include "util/format/u_format.h"31#include "util/format_srgb.h"32#include "util/u_framebuffer.h"33#include "util/u_inlines.h"34#include "util/u_rect.h"35#include "util/u_surface.h"36#include "util/u_helpers.h"3738static inline bool39check_3d_layers(struct pipe_surface *psurf)40{41if (psurf->texture->target != PIPE_TEXTURE_3D)42return true;43/* SPEC PROBLEM:44* though the vk spec doesn't seem to explicitly address this, currently drivers45* are claiming that all 3D images have a single "3D" layer regardless of layercount,46* so we can never clear them if we aren't trying to clear only layer 047*/48if (psurf->u.tex.first_layer)49return false;5051if (psurf->u.tex.last_layer - psurf->u.tex.first_layer > 0)52return false;53return true;54}5556static inline bool57scissor_states_equal(const struct pipe_scissor_state *a, const struct pipe_scissor_state *b)58{59return a->minx == b->minx && a->miny == b->miny && a->maxx == b->maxx && a->maxy == b->maxy;60}6162static void63clear_in_rp(struct pipe_context *pctx,64unsigned buffers,65const struct pipe_scissor_state *scissor_state,66const union pipe_color_union *pcolor,67double depth, unsigned stencil)68{69struct zink_context *ctx = zink_context(pctx);70struct pipe_framebuffer_state *fb = &ctx->fb_state;7172VkClearAttachment attachments[1 + PIPE_MAX_COLOR_BUFS];73int num_attachments = 0;7475if (buffers & PIPE_CLEAR_COLOR) {76VkClearColorValue color;77color.float32[0] = pcolor->f[0];78color.float32[1] = pcolor->f[1];79color.float32[2] = pcolor->f[2];80color.float32[3] = pcolor->f[3];8182for (unsigned i = 0; i < fb->nr_cbufs; i++) {83if (!(buffers & (PIPE_CLEAR_COLOR0 << i)) || !fb->cbufs[i])84continue;8586attachments[num_attachments].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;87attachments[num_attachments].colorAttachment = i;88attachments[num_attachments].clearValue.color = color;89++num_attachments;90}91}9293if (buffers & PIPE_CLEAR_DEPTHSTENCIL && fb->zsbuf) {94VkImageAspectFlags aspect = 0;95if (buffers & PIPE_CLEAR_DEPTH)96aspect |= VK_IMAGE_ASPECT_DEPTH_BIT;97if (buffers & PIPE_CLEAR_STENCIL)98aspect |= VK_IMAGE_ASPECT_STENCIL_BIT;99100attachments[num_attachments].aspectMask = aspect;101attachments[num_attachments].clearValue.depthStencil.depth = depth;102attachments[num_attachments].clearValue.depthStencil.stencil = stencil;103++num_attachments;104}105106VkClearRect cr = {0};107if (scissor_state) {108cr.rect.offset.x = scissor_state->minx;109cr.rect.offset.y = scissor_state->miny;110cr.rect.extent.width = MIN2(fb->width, scissor_state->maxx - scissor_state->minx);111cr.rect.extent.height = MIN2(fb->height, scissor_state->maxy - scissor_state->miny);112} else {113cr.rect.extent.width = fb->width;114cr.rect.extent.height = fb->height;115}116cr.baseArrayLayer = 0;117cr.layerCount = util_framebuffer_get_num_layers(fb);118struct zink_batch *batch = zink_batch_rp(ctx);119vkCmdClearAttachments(batch->state->cmdbuf, num_attachments, attachments, 1, &cr);120}121122static void123clear_color_no_rp(struct zink_context *ctx, struct zink_resource *res, const union pipe_color_union *pcolor, unsigned level, unsigned layer, unsigned layerCount)124{125struct zink_batch *batch = zink_batch_no_rp(ctx);126VkImageSubresourceRange range = {0};127range.baseMipLevel = level;128range.levelCount = 1;129range.baseArrayLayer = layer;130range.layerCount = layerCount;131range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;132133VkClearColorValue color;134color.float32[0] = pcolor->f[0];135color.float32[1] = pcolor->f[1];136color.float32[2] = pcolor->f[2];137color.float32[3] = pcolor->f[3];138139if (zink_resource_image_needs_barrier(res, VK_IMAGE_LAYOUT_GENERAL, 0, 0) &&140zink_resource_image_needs_barrier(res, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0))141zink_resource_image_barrier(ctx, NULL, res, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0);142zink_batch_reference_resource_rw(batch, res, true);143vkCmdClearColorImage(batch->state->cmdbuf, res->obj->image, res->layout, &color, 1, &range);144}145146static void147clear_zs_no_rp(struct zink_context *ctx, struct zink_resource *res, VkImageAspectFlags aspects, double depth, unsigned stencil, unsigned level, unsigned layer, unsigned layerCount)148{149struct zink_batch *batch = zink_batch_no_rp(ctx);150VkImageSubresourceRange range = {0};151range.baseMipLevel = level;152range.levelCount = 1;153range.baseArrayLayer = layer;154range.layerCount = layerCount;155range.aspectMask = aspects;156157VkClearDepthStencilValue zs_value = {depth, stencil};158159if (zink_resource_image_needs_barrier(res, VK_IMAGE_LAYOUT_GENERAL, 0, 0) &&160zink_resource_image_needs_barrier(res, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0))161zink_resource_image_barrier(ctx, NULL, res, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0);162zink_batch_reference_resource_rw(batch, res, true);163vkCmdClearDepthStencilImage(batch->state->cmdbuf, res->obj->image, res->layout, &zs_value, 1, &range);164}165166167168static struct zink_framebuffer_clear_data *169get_clear_data(struct zink_context *ctx, struct zink_framebuffer_clear *fb_clear, const struct pipe_scissor_state *scissor_state)170{171struct zink_framebuffer_clear_data *clear = NULL;172unsigned num_clears = zink_fb_clear_count(fb_clear);173if (num_clears) {174struct zink_framebuffer_clear_data *last_clear = zink_fb_clear_element(fb_clear, num_clears - 1);175/* if we're completely overwriting the previous clear, merge this into the previous clear */176if (!scissor_state || (last_clear->has_scissor && scissor_states_equal(&last_clear->scissor, scissor_state)))177clear = last_clear;178}179if (!clear) {180struct zink_framebuffer_clear_data cd = {0};181util_dynarray_append(&fb_clear->clears, struct zink_framebuffer_clear_data, cd);182clear = zink_fb_clear_element(fb_clear, zink_fb_clear_count(fb_clear) - 1);183}184return clear;185}186187void188zink_clear(struct pipe_context *pctx,189unsigned buffers,190const struct pipe_scissor_state *scissor_state,191const union pipe_color_union *pcolor,192double depth, unsigned stencil)193{194struct zink_context *ctx = zink_context(pctx);195struct pipe_framebuffer_state *fb = &ctx->fb_state;196struct zink_batch *batch = &ctx->batch;197bool needs_rp = false;198199if (scissor_state) {200struct u_rect scissor = {scissor_state->minx, scissor_state->maxx, scissor_state->miny, scissor_state->maxy};201needs_rp = !zink_blit_region_fills(scissor, fb->width, fb->height);202}203204205if (batch->in_rp) {206clear_in_rp(pctx, buffers, scissor_state, pcolor, depth, stencil);207return;208}209210if (buffers & PIPE_CLEAR_COLOR) {211for (unsigned i = 0; i < fb->nr_cbufs; i++) {212if ((buffers & (PIPE_CLEAR_COLOR0 << i)) && fb->cbufs[i]) {213struct pipe_surface *psurf = fb->cbufs[i];214struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i];215struct zink_framebuffer_clear_data *clear = get_clear_data(ctx, fb_clear, needs_rp ? scissor_state : NULL);216217ctx->clears_enabled |= PIPE_CLEAR_COLOR0 << i;218clear->conditional = ctx->render_condition_active;219clear->has_scissor = needs_rp;220if (scissor_state && needs_rp)221clear->scissor = *scissor_state;222clear->color.color = *pcolor;223clear->color.srgb = psurf->format != psurf->texture->format &&224!util_format_is_srgb(psurf->format) && util_format_is_srgb(psurf->texture->format);225if (zink_fb_clear_first_needs_explicit(fb_clear))226ctx->rp_clears_enabled &= ~(PIPE_CLEAR_COLOR0 << i);227else228ctx->rp_clears_enabled |= PIPE_CLEAR_COLOR0 << i;229}230}231}232233if (buffers & PIPE_CLEAR_DEPTHSTENCIL && fb->zsbuf) {234struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[PIPE_MAX_COLOR_BUFS];235struct zink_framebuffer_clear_data *clear = get_clear_data(ctx, fb_clear, needs_rp ? scissor_state : NULL);236ctx->clears_enabled |= PIPE_CLEAR_DEPTHSTENCIL;237clear->conditional = ctx->render_condition_active;238clear->has_scissor = needs_rp;239if (scissor_state && needs_rp)240clear->scissor = *scissor_state;241if (buffers & PIPE_CLEAR_DEPTH)242clear->zs.depth = depth;243if (buffers & PIPE_CLEAR_STENCIL)244clear->zs.stencil = stencil;245clear->zs.bits |= (buffers & PIPE_CLEAR_DEPTHSTENCIL);246if (zink_fb_clear_first_needs_explicit(fb_clear))247ctx->rp_clears_enabled &= ~PIPE_CLEAR_DEPTHSTENCIL;248else249ctx->rp_clears_enabled |= (buffers & PIPE_CLEAR_DEPTHSTENCIL);250}251}252253static inline bool254colors_equal(union pipe_color_union *a, union pipe_color_union *b)255{256return a->ui[0] == b->ui[0] && a->ui[1] == b->ui[1] && a->ui[2] == b->ui[2] && a->ui[3] == b->ui[3];257}258259void260zink_clear_framebuffer(struct zink_context *ctx, unsigned clear_buffers)261{262unsigned to_clear = 0;263struct pipe_framebuffer_state *fb_state = &ctx->fb_state;264#ifndef NDEBUG265assert(!(clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) || zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS));266for (int i = 0; i < fb_state->nr_cbufs && clear_buffers >= PIPE_CLEAR_COLOR0; i++) {267assert(!(clear_buffers & (PIPE_CLEAR_COLOR0 << i)) || zink_fb_clear_enabled(ctx, i));268}269#endif270while (clear_buffers) {271struct zink_framebuffer_clear *color_clear = NULL;272struct zink_framebuffer_clear *zs_clear = NULL;273unsigned num_clears = 0;274for (int i = 0; i < fb_state->nr_cbufs && clear_buffers >= PIPE_CLEAR_COLOR0; i++) {275struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i];276/* these need actual clear calls inside the rp */277if (!(clear_buffers & (PIPE_CLEAR_COLOR0 << i)))278continue;279if (color_clear) {280/* different number of clears -> do another clear */281//XXX: could potentially merge "some" of the clears into this one for a very, very small optimization282if (num_clears != zink_fb_clear_count(fb_clear))283goto out;284/* compare all the clears to determine if we can batch these buffers together */285for (int j = !zink_fb_clear_first_needs_explicit(fb_clear); j < num_clears; j++) {286struct zink_framebuffer_clear_data *a = zink_fb_clear_element(color_clear, j);287struct zink_framebuffer_clear_data *b = zink_fb_clear_element(fb_clear, j);288/* scissors don't match, fire this one off */289if (a->has_scissor != b->has_scissor || (a->has_scissor && !scissor_states_equal(&a->scissor, &b->scissor)))290goto out;291292/* colors don't match, fire this one off */293if (!colors_equal(&a->color.color, &b->color.color))294goto out;295}296} else {297color_clear = fb_clear;298num_clears = zink_fb_clear_count(fb_clear);299}300301clear_buffers &= ~(PIPE_CLEAR_COLOR0 << i);302to_clear |= (PIPE_CLEAR_COLOR0 << i);303}304clear_buffers &= ~PIPE_CLEAR_COLOR;305if (clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) {306struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[PIPE_MAX_COLOR_BUFS];307if (color_clear) {308if (num_clears != zink_fb_clear_count(fb_clear))309goto out;310/* compare all the clears to determine if we can batch these buffers together */311for (int j = !zink_fb_clear_first_needs_explicit(fb_clear); j < zink_fb_clear_count(color_clear); j++) {312struct zink_framebuffer_clear_data *a = zink_fb_clear_element(color_clear, j);313struct zink_framebuffer_clear_data *b = zink_fb_clear_element(fb_clear, j);314/* scissors don't match, fire this one off */315if (a->has_scissor != b->has_scissor || (a->has_scissor && !scissor_states_equal(&a->scissor, &b->scissor)))316goto out;317}318}319zs_clear = fb_clear;320to_clear |= (clear_buffers & PIPE_CLEAR_DEPTHSTENCIL);321clear_buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;322}323out:324if (to_clear) {325if (num_clears) {326for (int j = !zink_fb_clear_first_needs_explicit(color_clear); j < num_clears; j++) {327struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(color_clear, j);328struct zink_framebuffer_clear_data *zsclear = NULL;329/* zs bits are both set here if those aspects should be cleared at some point */330unsigned clear_bits = to_clear & ~PIPE_CLEAR_DEPTHSTENCIL;331if (zs_clear) {332zsclear = zink_fb_clear_element(zs_clear, j);333clear_bits |= zsclear->zs.bits;334}335zink_clear(&ctx->base, clear_bits,336clear->has_scissor ? &clear->scissor : NULL,337&clear->color.color,338zsclear ? zsclear->zs.depth : 0,339zsclear ? zsclear->zs.stencil : 0);340}341} else {342for (int j = !zink_fb_clear_first_needs_explicit(zs_clear); j < zink_fb_clear_count(zs_clear); j++) {343struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(zs_clear, j);344zink_clear(&ctx->base, clear->zs.bits,345clear->has_scissor ? &clear->scissor : NULL,346NULL,347clear->zs.depth,348clear->zs.stencil);349}350}351}352to_clear = 0;353}354for (int i = 0; i < ARRAY_SIZE(ctx->fb_clears); i++)355zink_fb_clear_reset(ctx, i);356}357358static struct pipe_surface *359create_clear_surface(struct pipe_context *pctx, struct pipe_resource *pres, unsigned level, const struct pipe_box *box)360{361struct pipe_surface tmpl = {{0}};362363tmpl.format = pres->format;364tmpl.u.tex.first_layer = box->z;365tmpl.u.tex.last_layer = box->z + box->depth - 1;366tmpl.u.tex.level = level;367return pctx->create_surface(pctx, pres, &tmpl);368}369370void371zink_clear_texture(struct pipe_context *pctx,372struct pipe_resource *pres,373unsigned level,374const struct pipe_box *box,375const void *data)376{377struct zink_context *ctx = zink_context(pctx);378struct zink_resource *res = zink_resource(pres);379struct pipe_screen *pscreen = pctx->screen;380struct u_rect region = zink_rect_from_box(box);381bool needs_rp = !zink_blit_region_fills(region, pres->width0, pres->height0) || ctx->render_condition_active;382struct pipe_surface *surf = NULL;383384if (res->aspect & VK_IMAGE_ASPECT_COLOR_BIT) {385union pipe_color_union color;386387util_format_unpack_rgba(pres->format, color.ui, data, 1);388389if (pscreen->is_format_supported(pscreen, pres->format, pres->target, 0, 0,390PIPE_BIND_RENDER_TARGET) && !needs_rp) {391zink_batch_no_rp(ctx);392clear_color_no_rp(ctx, res, &color, level, box->z, box->depth);393} else {394surf = create_clear_surface(pctx, pres, level, box);395zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS);396util_blitter_clear_render_target(ctx->blitter, surf, &color, box->x, box->y, box->width, box->height);397}398if (res->base.b.target == PIPE_BUFFER)399util_range_add(&res->base.b, &res->valid_buffer_range, box->x, box->x + box->width);400} else {401float depth = 0.0;402uint8_t stencil = 0;403404if (res->aspect & VK_IMAGE_ASPECT_DEPTH_BIT)405util_format_unpack_z_float(pres->format, &depth, data, 1);406407if (res->aspect & VK_IMAGE_ASPECT_STENCIL_BIT)408util_format_unpack_s_8uint(pres->format, &stencil, data, 1);409410if (!needs_rp) {411zink_batch_no_rp(ctx);412clear_zs_no_rp(ctx, res, res->aspect, depth, stencil, level, box->z, box->depth);413} else {414unsigned flags = 0;415if (res->aspect & VK_IMAGE_ASPECT_DEPTH_BIT)416flags |= PIPE_CLEAR_DEPTH;417if (res->aspect & VK_IMAGE_ASPECT_STENCIL_BIT)418flags |= PIPE_CLEAR_STENCIL;419surf = create_clear_surface(pctx, pres, level, box);420zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS);421util_blitter_clear_depth_stencil(ctx->blitter, surf, flags, depth, stencil, box->x, box->y, box->width, box->height);422}423}424/* this will never destroy the surface */425pipe_surface_reference(&surf, NULL);426}427428void429zink_clear_buffer(struct pipe_context *pctx,430struct pipe_resource *pres,431unsigned offset,432unsigned size,433const void *clear_value,434int clear_value_size)435{436struct zink_context *ctx = zink_context(pctx);437struct zink_resource *res = zink_resource(pres);438439uint32_t clamped;440if (util_lower_clearsize_to_dword(clear_value, &clear_value_size, &clamped))441clear_value = &clamped;442if (offset % 4 == 0 && size % 4 == 0 && clear_value_size == sizeof(uint32_t)) {443/*444- dstOffset is the byte offset into the buffer at which to start filling,445and must be a multiple of 4.446447- size is the number of bytes to fill, and must be either a multiple of 4,448or VK_WHOLE_SIZE to fill the range from offset to the end of the buffer449*/450struct zink_batch *batch = zink_batch_no_rp(ctx);451zink_batch_reference_resource_rw(batch, res, true);452util_range_add(&res->base.b, &res->valid_buffer_range, offset, offset + size);453vkCmdFillBuffer(batch->state->cmdbuf, res->obj->buffer, offset, size, *(uint32_t*)clear_value);454return;455}456struct pipe_transfer *xfer;457uint8_t *map = pipe_buffer_map_range(pctx, pres, offset, size,458PIPE_MAP_WRITE | PIPE_MAP_ONCE | PIPE_MAP_DISCARD_RANGE, &xfer);459if (!map)460return;461unsigned rem = size % clear_value_size;462uint8_t *ptr = map;463for (unsigned i = 0; i < (size - rem) / clear_value_size; i++) {464memcpy(ptr, clear_value, clear_value_size);465ptr += clear_value_size;466}467if (rem)468memcpy(map + size - rem, clear_value, rem);469pipe_buffer_unmap(pctx, xfer);470}471472void473zink_clear_render_target(struct pipe_context *pctx, struct pipe_surface *dst,474const union pipe_color_union *color, unsigned dstx,475unsigned dsty, unsigned width, unsigned height,476bool render_condition_enabled)477{478struct zink_context *ctx = zink_context(pctx);479zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS | (render_condition_enabled ? 0 : ZINK_BLIT_NO_COND_RENDER));480util_blitter_clear_render_target(ctx->blitter, dst, color, dstx, dsty, width, height);481if (!render_condition_enabled && ctx->render_condition_active)482zink_start_conditional_render(ctx);483}484485void486zink_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *dst,487unsigned clear_flags, double depth, unsigned stencil,488unsigned dstx, unsigned dsty, unsigned width, unsigned height,489bool render_condition_enabled)490{491struct zink_context *ctx = zink_context(pctx);492zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS | (render_condition_enabled ? 0 : ZINK_BLIT_NO_COND_RENDER));493util_blitter_clear_depth_stencil(ctx->blitter, dst, clear_flags, depth, stencil, dstx, dsty, width, height);494if (!render_condition_enabled && ctx->render_condition_active)495zink_start_conditional_render(ctx);496}497498bool499zink_fb_clear_needs_explicit(struct zink_framebuffer_clear *fb_clear)500{501if (zink_fb_clear_count(fb_clear) != 1)502return true;503return zink_fb_clear_element_needs_explicit(zink_fb_clear_element(fb_clear, 0));504}505506bool507zink_fb_clear_first_needs_explicit(struct zink_framebuffer_clear *fb_clear)508{509if (!zink_fb_clear_count(fb_clear))510return false;511return zink_fb_clear_element_needs_explicit(zink_fb_clear_element(fb_clear, 0));512}513514void515zink_fb_clear_util_unpack_clear_color(struct zink_framebuffer_clear_data *clear, enum pipe_format format, union pipe_color_union *color)516{517const struct util_format_description *desc = util_format_description(format);518if (clear->color.srgb) {519/* if SRGB mode is disabled for the fb with a backing srgb image then we have to520* convert this to srgb color521*/522for (unsigned j = 0; j < MIN2(3, desc->nr_channels); j++) {523assert(desc->channel[j].normalized);524color->f[j] = util_format_srgb_to_linear_float(clear->color.color.f[j]);525}526color->f[3] = clear->color.color.f[3];527} else {528for (unsigned i = 0; i < 4; i++)529color->f[i] = clear->color.color.f[i];530}531}532533static void534fb_clears_apply_internal(struct zink_context *ctx, struct pipe_resource *pres, int i)535{536struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i];537538if (!zink_fb_clear_enabled(ctx, i))539return;540if (ctx->batch.in_rp)541zink_clear_framebuffer(ctx, BITFIELD_BIT(i));542else if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) {543if (zink_fb_clear_needs_explicit(fb_clear) || !check_3d_layers(ctx->fb_state.cbufs[i]))544/* this will automatically trigger all the clears */545zink_batch_rp(ctx);546else {547struct pipe_surface *psurf = ctx->fb_state.cbufs[i];548struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, 0);549union pipe_color_union color;550zink_fb_clear_util_unpack_clear_color(clear, psurf->format, &color);551552clear_color_no_rp(ctx, zink_resource(pres), &color,553psurf->u.tex.level, psurf->u.tex.first_layer,554psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1);555}556zink_fb_clear_reset(ctx, i);557return;558} else {559if (zink_fb_clear_needs_explicit(fb_clear) || !check_3d_layers(ctx->fb_state.zsbuf))560/* this will automatically trigger all the clears */561zink_batch_rp(ctx);562else {563struct pipe_surface *psurf = ctx->fb_state.zsbuf;564struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, 0);565VkImageAspectFlags aspects = 0;566if (clear->zs.bits & PIPE_CLEAR_DEPTH)567aspects |= VK_IMAGE_ASPECT_DEPTH_BIT;568if (clear->zs.bits & PIPE_CLEAR_STENCIL)569aspects |= VK_IMAGE_ASPECT_STENCIL_BIT;570clear_zs_no_rp(ctx, zink_resource(pres), aspects, clear->zs.depth, clear->zs.stencil,571psurf->u.tex.level, psurf->u.tex.first_layer,572psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1);573}574}575zink_fb_clear_reset(ctx, i);576}577578void579zink_fb_clear_reset(struct zink_context *ctx, unsigned i)580{581util_dynarray_clear(&ctx->fb_clears[i].clears);582if (i == PIPE_MAX_COLOR_BUFS) {583ctx->clears_enabled &= ~PIPE_CLEAR_DEPTHSTENCIL;584ctx->rp_clears_enabled &= ~PIPE_CLEAR_DEPTHSTENCIL;585} else {586ctx->clears_enabled &= ~(PIPE_CLEAR_COLOR0 << i);587ctx->rp_clears_enabled &= ~(PIPE_CLEAR_COLOR0 << i);588}589}590591void592zink_fb_clears_apply(struct zink_context *ctx, struct pipe_resource *pres)593{594if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) {595for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {596if (ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture == pres) {597fb_clears_apply_internal(ctx, pres, i);598return;599}600}601} else {602if (ctx->fb_state.zsbuf && ctx->fb_state.zsbuf->texture == pres) {603fb_clears_apply_internal(ctx, pres, PIPE_MAX_COLOR_BUFS);604}605}606}607608void609zink_fb_clears_discard(struct zink_context *ctx, struct pipe_resource *pres)610{611if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) {612for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {613if (ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture == pres) {614if (zink_fb_clear_enabled(ctx, i)) {615zink_fb_clear_reset(ctx, i);616return;617}618}619}620} else {621if (zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS) && ctx->fb_state.zsbuf && ctx->fb_state.zsbuf->texture == pres) {622int i = PIPE_MAX_COLOR_BUFS;623zink_fb_clear_reset(ctx, i);624}625}626}627628void629zink_clear_apply_conditionals(struct zink_context *ctx)630{631for (int i = 0; i < ARRAY_SIZE(ctx->fb_clears); i++) {632struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i];633if (!zink_fb_clear_enabled(ctx, i))634continue;635for (int j = 0; j < zink_fb_clear_count(fb_clear); j++) {636struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, j);637if (clear->conditional) {638struct pipe_surface *surf;639if (i < PIPE_MAX_COLOR_BUFS)640surf = ctx->fb_state.cbufs[i];641else642surf = ctx->fb_state.zsbuf;643if (surf)644fb_clears_apply_internal(ctx, surf->texture, i);645else646zink_fb_clear_reset(ctx, i);647break;648}649}650}651}652653static void654fb_clears_apply_or_discard_internal(struct zink_context *ctx, struct pipe_resource *pres, struct u_rect region, bool discard_only, bool invert, int i)655{656struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i];657if (zink_fb_clear_enabled(ctx, i)) {658if (zink_blit_region_fills(region, pres->width0, pres->height0)) {659if (invert)660fb_clears_apply_internal(ctx, pres, i);661else662/* we know we can skip these */663zink_fb_clears_discard(ctx, pres);664return;665}666for (int j = 0; j < zink_fb_clear_count(fb_clear); j++) {667struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, j);668struct u_rect scissor = {clear->scissor.minx, clear->scissor.maxx,669clear->scissor.miny, clear->scissor.maxy};670if (!clear->has_scissor || zink_blit_region_covers(region, scissor)) {671/* this is a clear that isn't fully covered by our pending write */672if (!discard_only)673fb_clears_apply_internal(ctx, pres, i);674return;675}676}677if (!invert)678/* if we haven't already returned, then we know we can discard */679zink_fb_clears_discard(ctx, pres);680}681}682683void684zink_fb_clears_apply_or_discard(struct zink_context *ctx, struct pipe_resource *pres, struct u_rect region, bool discard_only)685{686if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) {687for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {688if (ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture == pres) {689fb_clears_apply_or_discard_internal(ctx, pres, region, discard_only, false, i);690return;691}692}693} else {694if (zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS) && ctx->fb_state.zsbuf && ctx->fb_state.zsbuf->texture == pres) {695fb_clears_apply_or_discard_internal(ctx, pres, region, discard_only, false, PIPE_MAX_COLOR_BUFS);696}697}698}699700void701zink_fb_clears_apply_region(struct zink_context *ctx, struct pipe_resource *pres, struct u_rect region)702{703if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) {704for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {705if (ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture == pres) {706fb_clears_apply_or_discard_internal(ctx, pres, region, false, true, i);707return;708}709}710} else {711if (ctx->fb_state.zsbuf && ctx->fb_state.zsbuf->texture == pres) {712fb_clears_apply_or_discard_internal(ctx, pres, region, false, true, PIPE_MAX_COLOR_BUFS);713}714}715}716717718