Files
third_party_mesa3d/src/gallium/drivers/zink/zink_clear.c
Mike Blumenkrantz 1294aec650 zink: apply only the pending zs clear bits during deferred clears
both bits will have been flagged at this point in order to indicate
that the aspects will be cleared "at some point" during the loop, but
when actually iterating through the pending clears, only the bits set
in the clear call should be applied

Fixes: 5c629e9ff2 ("zink: defer pipe_context::clear calls when not currently in a renderpass")

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9366>
2021-03-02 19:24:52 +00:00

603 lines
24 KiB
C

/*
* Copyright 2018 Collabora Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "zink_context.h"
#include "zink_resource.h"
#include "zink_screen.h"
#include "util/u_blitter.h"
#include "util/u_dynarray.h"
#include "util/format/u_format.h"
#include "util/format_srgb.h"
#include "util/u_framebuffer.h"
#include "util/u_inlines.h"
#include "util/u_rect.h"
#include "util/u_surface.h"
static inline bool
check_3d_layers(struct pipe_surface *psurf)
{
if (psurf->texture->target != PIPE_TEXTURE_3D)
return true;
/* SPEC PROBLEM:
* though the vk spec doesn't seem to explicitly address this, currently drivers
* are claiming that all 3D images have a single "3D" layer regardless of layercount,
* so we can never clear them if we aren't trying to clear only layer 0
*/
if (psurf->u.tex.first_layer)
return false;
if (psurf->u.tex.last_layer - psurf->u.tex.first_layer > 0)
return false;
return true;
}
static inline bool
scissor_states_equal(const struct pipe_scissor_state *a, const struct pipe_scissor_state *b)
{
return a->minx == b->minx && a->miny == b->miny && a->maxx == b->maxx && a->maxy == b->maxy;
}
static void
clear_in_rp(struct pipe_context *pctx,
unsigned buffers,
const struct pipe_scissor_state *scissor_state,
const union pipe_color_union *pcolor,
double depth, unsigned stencil)
{
struct zink_context *ctx = zink_context(pctx);
struct pipe_framebuffer_state *fb = &ctx->fb_state;
VkClearAttachment attachments[1 + PIPE_MAX_COLOR_BUFS];
int num_attachments = 0;
if (buffers & PIPE_CLEAR_COLOR) {
VkClearColorValue color;
color.float32[0] = pcolor->f[0];
color.float32[1] = pcolor->f[1];
color.float32[2] = pcolor->f[2];
color.float32[3] = pcolor->f[3];
for (unsigned i = 0; i < fb->nr_cbufs; i++) {
if (!(buffers & (PIPE_CLEAR_COLOR0 << i)) || !fb->cbufs[i])
continue;
attachments[num_attachments].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
attachments[num_attachments].colorAttachment = i;
attachments[num_attachments].clearValue.color = color;
++num_attachments;
}
}
if (buffers & PIPE_CLEAR_DEPTHSTENCIL && fb->zsbuf) {
VkImageAspectFlags aspect = 0;
if (buffers & PIPE_CLEAR_DEPTH)
aspect |= VK_IMAGE_ASPECT_DEPTH_BIT;
if (buffers & PIPE_CLEAR_STENCIL)
aspect |= VK_IMAGE_ASPECT_STENCIL_BIT;
attachments[num_attachments].aspectMask = aspect;
attachments[num_attachments].clearValue.depthStencil.depth = depth;
attachments[num_attachments].clearValue.depthStencil.stencil = stencil;
++num_attachments;
}
VkClearRect cr = {};
if (scissor_state) {
cr.rect.offset.x = scissor_state->minx;
cr.rect.offset.y = scissor_state->miny;
cr.rect.extent.width = MIN2(fb->width, scissor_state->maxx - scissor_state->minx);
cr.rect.extent.height = MIN2(fb->height, scissor_state->maxy - scissor_state->miny);
} else {
cr.rect.extent.width = fb->width;
cr.rect.extent.height = fb->height;
}
cr.baseArrayLayer = 0;
cr.layerCount = util_framebuffer_get_num_layers(fb);
struct zink_batch *batch = zink_batch_rp(ctx);
vkCmdClearAttachments(batch->cmdbuf, num_attachments, attachments, 1, &cr);
}
static void
clear_color_no_rp(struct zink_context *ctx, struct zink_resource *res, const union pipe_color_union *pcolor, unsigned level, unsigned layer, unsigned layerCount)
{
struct zink_batch *batch = zink_batch_no_rp(ctx);
VkImageSubresourceRange range = {};
range.baseMipLevel = level;
range.levelCount = 1;
range.baseArrayLayer = layer;
range.layerCount = layerCount;
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
VkClearColorValue color;
color.float32[0] = pcolor->f[0];
color.float32[1] = pcolor->f[1];
color.float32[2] = pcolor->f[2];
color.float32[3] = pcolor->f[3];
if (zink_resource_image_needs_barrier(res, VK_IMAGE_LAYOUT_GENERAL, 0, 0) &&
zink_resource_image_needs_barrier(res, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0))
zink_resource_image_barrier(ctx, NULL, res, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0);
zink_batch_reference_resource_rw(batch, res, true);
vkCmdClearColorImage(batch->cmdbuf, res->image, res->layout, &color, 1, &range);
}
static void
clear_zs_no_rp(struct zink_context *ctx, struct zink_resource *res, VkImageAspectFlags aspects, double depth, unsigned stencil, unsigned level, unsigned layer, unsigned layerCount)
{
struct zink_batch *batch = zink_batch_no_rp(ctx);
VkImageSubresourceRange range = {};
range.baseMipLevel = level;
range.levelCount = 1;
range.baseArrayLayer = layer;
range.layerCount = layerCount;
range.aspectMask = aspects;
VkClearDepthStencilValue zs_value = {depth, stencil};
if (zink_resource_image_needs_barrier(res, VK_IMAGE_LAYOUT_GENERAL, 0, 0) &&
zink_resource_image_needs_barrier(res, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0))
zink_resource_image_barrier(ctx, NULL, res, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0);
zink_batch_reference_resource_rw(batch, res, true);
vkCmdClearDepthStencilImage(batch->cmdbuf, res->image, res->layout, &zs_value, 1, &range);
}
static struct zink_framebuffer_clear_data *
get_clear_data(struct zink_context *ctx, struct zink_framebuffer_clear *fb_clear, const struct pipe_scissor_state *scissor_state)
{
struct zink_framebuffer_clear_data *clear = NULL;
unsigned num_clears = zink_fb_clear_count(fb_clear);
if (num_clears) {
struct zink_framebuffer_clear_data *last_clear = zink_fb_clear_element(fb_clear, num_clears - 1);
/* if we're completely overwriting the previous clear, merge this into the previous clear */
if (!scissor_state || (last_clear->has_scissor && scissor_states_equal(&last_clear->scissor, scissor_state)))
clear = last_clear;
}
if (!clear) {
struct zink_framebuffer_clear_data cd = {};
util_dynarray_append(&fb_clear->clears, struct zink_framebuffer_clear_data, cd);
clear = zink_fb_clear_element(fb_clear, zink_fb_clear_count(fb_clear) - 1);
}
return clear;
}
void
zink_clear(struct pipe_context *pctx,
unsigned buffers,
const struct pipe_scissor_state *scissor_state,
const union pipe_color_union *pcolor,
double depth, unsigned stencil)
{
struct zink_context *ctx = zink_context(pctx);
struct pipe_framebuffer_state *fb = &ctx->fb_state;
struct zink_batch *batch = zink_curr_batch(ctx);
bool needs_rp = false;
if (scissor_state) {
struct u_rect scissor = {scissor_state->minx, scissor_state->maxx, scissor_state->miny, scissor_state->maxy};
needs_rp = !zink_blit_region_fills(scissor, fb->width, fb->height);
}
if (batch->in_rp) {
clear_in_rp(pctx, buffers, scissor_state, pcolor, depth, stencil);
return;
}
if (buffers & PIPE_CLEAR_COLOR) {
for (unsigned i = 0; i < fb->nr_cbufs; i++) {
if ((buffers & (PIPE_CLEAR_COLOR0 << i)) && fb->cbufs[i]) {
struct pipe_surface *psurf = fb->cbufs[i];
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i];
struct zink_framebuffer_clear_data *clear = get_clear_data(ctx, fb_clear, needs_rp ? scissor_state : NULL);
fb_clear->enabled = true;
clear->conditional = ctx->render_condition_active;
clear->has_scissor = needs_rp;
if (scissor_state && needs_rp)
clear->scissor = *scissor_state;
clear->color.color = *pcolor;
clear->color.srgb = psurf->format != psurf->texture->format &&
!util_format_is_srgb(psurf->format) && util_format_is_srgb(psurf->texture->format);
}
}
}
if (buffers & PIPE_CLEAR_DEPTHSTENCIL && fb->zsbuf) {
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[PIPE_MAX_COLOR_BUFS];
struct zink_framebuffer_clear_data *clear = get_clear_data(ctx, fb_clear, needs_rp ? scissor_state : NULL);
fb_clear->enabled = true;
clear->conditional = ctx->render_condition_active;
clear->has_scissor = needs_rp;
if (scissor_state && needs_rp)
clear->scissor = *scissor_state;
if (buffers & PIPE_CLEAR_DEPTH)
clear->zs.depth = depth;
if (buffers & PIPE_CLEAR_STENCIL)
clear->zs.stencil = stencil;
clear->zs.bits |= (buffers & PIPE_CLEAR_DEPTHSTENCIL);
}
}
static inline bool
colors_equal(union pipe_color_union *a, union pipe_color_union *b)
{
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];
}
void
zink_clear_framebuffer(struct zink_context *ctx, unsigned clear_buffers)
{
unsigned to_clear = 0;
struct pipe_framebuffer_state *fb_state = &ctx->fb_state;
while (clear_buffers) {
struct zink_framebuffer_clear *color_clear = NULL;
struct zink_framebuffer_clear *zs_clear = NULL;
unsigned num_clears = 0;
for (int i = 0; i < fb_state->nr_cbufs && clear_buffers >= PIPE_CLEAR_COLOR0; i++) {
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i];
/* these need actual clear calls inside the rp */
if (!(clear_buffers & (PIPE_CLEAR_COLOR0 << i)))
continue;
if (color_clear) {
/* different number of clears -> do another clear */
//XXX: could potentially merge "some" of the clears into this one for a very, very small optimization
if (num_clears != zink_fb_clear_count(fb_clear))
goto out;
/* compare all the clears to determine if we can batch these buffers together */
for (int j = !zink_fb_clear_first_needs_explicit(fb_clear); j < num_clears; j++) {
struct zink_framebuffer_clear_data *a = zink_fb_clear_element(color_clear, j);
struct zink_framebuffer_clear_data *b = zink_fb_clear_element(fb_clear, j);
/* scissors don't match, fire this one off */
if (a->has_scissor != b->has_scissor || (a->has_scissor && !scissor_states_equal(&a->scissor, &b->scissor)))
goto out;
/* colors don't match, fire this one off */
if (!colors_equal(&a->color.color, &b->color.color))
goto out;
}
} else {
color_clear = fb_clear;
num_clears = zink_fb_clear_count(fb_clear);
}
clear_buffers &= ~(PIPE_CLEAR_COLOR0 << i);
to_clear |= (PIPE_CLEAR_COLOR0 << i);
}
if (clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) {
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[PIPE_MAX_COLOR_BUFS];
if (color_clear) {
if (num_clears != zink_fb_clear_count(fb_clear))
goto out;
/* compare all the clears to determine if we can batch these buffers together */
for (int j = !zink_fb_clear_first_needs_explicit(fb_clear); j < zink_fb_clear_count(color_clear); j++) {
struct zink_framebuffer_clear_data *a = zink_fb_clear_element(color_clear, j);
struct zink_framebuffer_clear_data *b = zink_fb_clear_element(fb_clear, j);
/* scissors don't match, fire this one off */
if (a->has_scissor != b->has_scissor || (a->has_scissor && !scissor_states_equal(&a->scissor, &b->scissor)))
goto out;
}
}
zs_clear = fb_clear;
to_clear |= (clear_buffers & PIPE_CLEAR_DEPTHSTENCIL);
clear_buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
}
out:
if (to_clear) {
if (num_clears) {
for (int j = !zink_fb_clear_first_needs_explicit(color_clear); j < num_clears; j++) {
struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(color_clear, j);
struct zink_framebuffer_clear_data *zsclear = NULL;
/* zs bits are both set here if those aspects should be cleared at some point */
unsigned clear_bits = to_clear & ~PIPE_CLEAR_DEPTHSTENCIL;
if (zs_clear) {
zsclear = zink_fb_clear_element(zs_clear, j);
clear_bits |= zsclear->zs.bits;
}
zink_clear(&ctx->base, clear_bits,
clear->has_scissor ? &clear->scissor : NULL,
&clear->color.color,
zsclear ? zsclear->zs.depth : 0,
zsclear ? zsclear->zs.stencil : 0);
}
} else {
for (int j = !zink_fb_clear_first_needs_explicit(zs_clear); j < zink_fb_clear_count(zs_clear); j++) {
struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(zs_clear, j);
zink_clear(&ctx->base, clear->zs.bits,
clear->has_scissor ? &clear->scissor : NULL,
NULL,
clear->zs.depth,
clear->zs.stencil);
}
}
}
to_clear = 0;
}
for (int i = 0; i < ARRAY_SIZE(ctx->fb_clears); i++)
zink_fb_clear_reset(&ctx->fb_clears[i]);
}
static struct pipe_surface *
create_clear_surface(struct pipe_context *pctx, struct pipe_resource *pres, unsigned level, const struct pipe_box *box)
{
struct pipe_surface tmpl = {{0}};
tmpl.format = pres->format;
tmpl.u.tex.first_layer = box->z;
tmpl.u.tex.last_layer = box->z + box->depth - 1;
tmpl.u.tex.level = level;
return pctx->create_surface(pctx, pres, &tmpl);
}
void
zink_clear_texture(struct pipe_context *pctx,
struct pipe_resource *pres,
unsigned level,
const struct pipe_box *box,
const void *data)
{
struct zink_context *ctx = zink_context(pctx);
struct zink_resource *res = zink_resource(pres);
struct pipe_screen *pscreen = pctx->screen;
struct u_rect region = zink_rect_from_box(box);
bool needs_rp = !zink_blit_region_fills(region, pres->width0, pres->height0) || ctx->render_condition_active;
struct zink_batch *batch = zink_curr_batch(ctx);
struct pipe_surface *surf = NULL;
if (res->aspect & VK_IMAGE_ASPECT_COLOR_BIT) {
union pipe_color_union color;
util_format_unpack_rgba(pres->format, color.ui, data, 1);
if (pscreen->is_format_supported(pscreen, pres->format, pres->target, 0, 0,
PIPE_BIND_RENDER_TARGET) && !needs_rp && !batch->in_rp) {
clear_color_no_rp(ctx, res, &color, level, box->z, box->depth);
} else {
surf = create_clear_surface(pctx, pres, level, box);
zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS);
util_clear_render_target(pctx, surf, &color, box->x, box->y, box->width, box->height);
}
if (res->base.target == PIPE_BUFFER)
util_range_add(&res->base, &res->valid_buffer_range, box->x, box->x + box->width);
} else {
float depth = 0.0;
uint8_t stencil = 0;
if (res->aspect & VK_IMAGE_ASPECT_DEPTH_BIT)
util_format_unpack_z_float(pres->format, &depth, data, 1);
if (res->aspect & VK_IMAGE_ASPECT_STENCIL_BIT)
util_format_unpack_s_8uint(pres->format, &stencil, data, 1);
if (!needs_rp && !batch->in_rp)
clear_zs_no_rp(ctx, res, res->aspect, depth, stencil, level, box->z, box->depth);
else {
unsigned flags = 0;
if (res->aspect & VK_IMAGE_ASPECT_DEPTH_BIT)
flags |= PIPE_CLEAR_DEPTH;
if (res->aspect & VK_IMAGE_ASPECT_STENCIL_BIT)
flags |= PIPE_CLEAR_STENCIL;
surf = create_clear_surface(pctx, pres, level, box);
zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS);
util_blitter_clear_depth_stencil(ctx->blitter, surf, flags, depth, stencil, box->x, box->y, box->width, box->height);
}
}
pipe_surface_reference(&surf, NULL);
}
bool
zink_fb_clear_needs_explicit(struct zink_framebuffer_clear *fb_clear)
{
if (zink_fb_clear_count(fb_clear) != 1)
return true;
return zink_fb_clear_element_needs_explicit(zink_fb_clear_element(fb_clear, 0));
}
bool
zink_fb_clear_first_needs_explicit(struct zink_framebuffer_clear *fb_clear)
{
if (!zink_fb_clear_count(fb_clear))
return false;
return zink_fb_clear_element_needs_explicit(zink_fb_clear_element(fb_clear, 0));
}
static void
fb_clears_apply_internal(struct zink_context *ctx, struct pipe_resource *pres, int i)
{
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i];
if (!fb_clear->enabled)
return;
if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
assert(!zink_curr_batch(ctx)->in_rp);
if (zink_fb_clear_needs_explicit(fb_clear) || !check_3d_layers(ctx->fb_state.cbufs[i]))
/* this will automatically trigger all the clears */
zink_batch_rp(ctx);
else {
struct pipe_surface *psurf = ctx->fb_state.cbufs[i];
struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, 0);
union pipe_color_union color = clear->color.color;
if (clear->color.srgb) {
/* if SRGB mode is disabled for the fb with a backing srgb image then we have to
* convert this to srgb color
*/
color.f[0] = util_format_srgb_to_linear_float(clear->color.color.f[0]);
color.f[1] = util_format_srgb_to_linear_float(clear->color.color.f[1]);
color.f[2] = util_format_srgb_to_linear_float(clear->color.color.f[2]);
}
clear_color_no_rp(ctx, zink_resource(pres), &color,
psurf->u.tex.level, psurf->u.tex.first_layer,
psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1);
}
zink_fb_clear_reset(&ctx->fb_clears[i]);
return;
} else {
assert(!zink_curr_batch(ctx)->in_rp);
if (zink_fb_clear_needs_explicit(fb_clear) || !check_3d_layers(ctx->fb_state.zsbuf))
/* this will automatically trigger all the clears */
zink_batch_rp(ctx);
else {
struct pipe_surface *psurf = ctx->fb_state.zsbuf;
struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, 0);
VkImageAspectFlags aspects = 0;
if (clear->zs.bits & PIPE_CLEAR_DEPTH)
aspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
if (clear->zs.bits & PIPE_CLEAR_STENCIL)
aspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
clear_zs_no_rp(ctx, zink_resource(pres), aspects, clear->zs.depth, clear->zs.stencil,
psurf->u.tex.level, psurf->u.tex.first_layer,
psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1);
}
}
zink_fb_clear_reset(fb_clear);
}
void
zink_fb_clears_apply(struct zink_context *ctx, struct pipe_resource *pres)
{
if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
if (ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture == pres) {
fb_clears_apply_internal(ctx, pres, i);
return;
}
}
} else {
if (ctx->fb_state.zsbuf && ctx->fb_state.zsbuf->texture == pres) {
fb_clears_apply_internal(ctx, pres, PIPE_MAX_COLOR_BUFS);
}
}
}
void
zink_fb_clears_discard(struct zink_context *ctx, struct pipe_resource *pres)
{
if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
if (ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture == pres) {
if (ctx->fb_clears[i].enabled) {
zink_fb_clear_reset(&ctx->fb_clears[i]);
return;
}
}
}
} else {
if (ctx->fb_clears[PIPE_MAX_COLOR_BUFS].enabled && ctx->fb_state.zsbuf && ctx->fb_state.zsbuf->texture == pres) {
int i = PIPE_MAX_COLOR_BUFS;
zink_fb_clear_reset(&ctx->fb_clears[i]);
}
}
}
void
zink_clear_apply_conditionals(struct zink_context *ctx)
{
for (int i = 0; i < ARRAY_SIZE(ctx->fb_clears); i++) {
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i];
if (!fb_clear->enabled)
continue;
for (int j = 0; j < zink_fb_clear_count(fb_clear); j++) {
struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, j);
if (clear->conditional) {
struct pipe_surface *surf;
if (i < PIPE_MAX_COLOR_BUFS)
surf = ctx->fb_state.cbufs[i];
else
surf = ctx->fb_state.zsbuf;
if (surf)
fb_clears_apply_internal(ctx, surf->texture, i);
else
zink_fb_clear_reset(&ctx->fb_clears[i]);
break;
}
}
}
}
static void
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)
{
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[i];
if (fb_clear->enabled) {
if (zink_blit_region_fills(region, pres->width0, pres->height0)) {
if (invert)
fb_clears_apply_internal(ctx, pres, i);
else
/* we know we can skip these */
zink_fb_clears_discard(ctx, pres);
return;
}
for (int j = 0; j < zink_fb_clear_count(fb_clear); j++) {
struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, j);
struct u_rect scissor = {clear->scissor.minx, clear->scissor.maxx,
clear->scissor.miny, clear->scissor.maxy};
if (!clear->has_scissor || zink_blit_region_covers(region, scissor)) {
/* this is a clear that isn't fully covered by our pending write */
if (!discard_only)
fb_clears_apply_internal(ctx, pres, i);
return;
}
}
if (!invert)
/* if we haven't already returned, then we know we can discard */
zink_fb_clears_discard(ctx, pres);
}
}
void
zink_fb_clears_apply_or_discard(struct zink_context *ctx, struct pipe_resource *pres, struct u_rect region, bool discard_only)
{
if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
if (ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture == pres) {
fb_clears_apply_or_discard_internal(ctx, pres, region, discard_only, false, i);
return;
}
}
} else {
if (ctx->fb_clears[PIPE_MAX_COLOR_BUFS].enabled && ctx->fb_state.zsbuf && ctx->fb_state.zsbuf->texture == pres) {
fb_clears_apply_or_discard_internal(ctx, pres, region, discard_only, false, PIPE_MAX_COLOR_BUFS);
}
}
}
void
zink_fb_clears_apply_region(struct zink_context *ctx, struct pipe_resource *pres, struct u_rect region)
{
if (zink_resource(pres)->aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
if (ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture == pres) {
fb_clears_apply_or_discard_internal(ctx, pres, region, false, true, i);
return;
}
}
} else {
if (ctx->fb_state.zsbuf && ctx->fb_state.zsbuf->texture == pres) {
fb_clears_apply_or_discard_internal(ctx, pres, region, false, true, PIPE_MAX_COLOR_BUFS);
}
}
}