panfrost: Handle non-dithered clear colours

In b9c095cc2c ("panfrost: Rewrite the clear colour packing code"),
packing of clear colours was corrected to use the tilebuffer's
fractional bits, fixing dithering of the clear colour with formats like
RGB565. Unfortunately, that commit did so unconditionally. If the
framebuffer is dithered, but dithering is disabled at the time of
the clear, we would incorrectly dither the clear.

This is a regression, as the old (broken) code passed the relevant CTS
test. What's the catch? Depending on dither state, there are two
formulas to pack tilebuffer colours. We need to handle both. Fixes
KHR-GLES31.core.draw_buffers_indexed.color_masks.

Fixes: b9c095cc2c ("panfrost: Rewrite the clear colour packing code")
Signed-off-by: Alyssa Rosenzweig <alyssa@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12460>
This commit is contained in:
Alyssa Rosenzweig 2021-08-18 22:16:56 +00:00 committed by Marge Bot
parent 1b710d4a96
commit 22538b89b3
5 changed files with 24 additions and 13 deletions

View file

@ -936,7 +936,7 @@ panfrost_batch_clear(struct panfrost_batch *batch,
continue;
enum pipe_format format = ctx->pipe_framebuffer.cbufs[i]->format;
pan_pack_color(batch->clear_color[i], color, format);
pan_pack_color(batch->clear_color[i], color, format, false);
}
}

View file

@ -52,13 +52,22 @@ pan_pack_color_32(uint32_t *packed, uint32_t v)
}
/* For m integer bits and n fractional bits, calculate the conversion factor,
* multiply the source value, and convert to integer rounding to even */
* multiply the source value, and convert to integer rounding to even. When
* dithering, the fractional bits are used. When not dithered, only the integer
* bits are used and the fractional bits must remain zero. */
static inline uint32_t
float_to_fixed(float f, unsigned bits_int, unsigned bits_frac)
float_to_fixed(float f, unsigned bits_int, unsigned bits_frac, bool dither)
{
float factor = ((1 << bits_int) - 1) << bits_frac;
return _mesa_roundevenf(f * factor);
uint32_t m = (1 << bits_int) - 1;
if (dither) {
float factor = m << bits_frac;
return _mesa_roundevenf(f * factor);
} else {
uint32_t v = _mesa_roundevenf(f * (float) m);
return v << bits_frac;
}
}
/* These values are shared across hardware versions. Don't include GenXML. */
@ -116,7 +125,8 @@ pan_pack_raw(uint32_t *packed, const union pipe_color_union *color, enum pipe_fo
}
void
pan_pack_color(uint32_t *packed, const union pipe_color_union *color, enum pipe_format format)
pan_pack_color(uint32_t *packed, const union pipe_color_union *color,
enum pipe_format format, bool dithered)
{
/* Set of blendable formats is common across versions. TODO: v9 */
enum mali_color_buffer_internal_format internal =
@ -157,10 +167,10 @@ pan_pack_color(uint32_t *packed, const union pipe_color_union *color, enum pipe_
assert(count_a == 32);
/* Convert the transformed float colour to the given layout */
uint32_t ur = float_to_fixed(r, l.int_r, l.frac_r) << 0;
uint32_t ug = float_to_fixed(g, l.int_g, l.frac_g) << count_r;
uint32_t ub = float_to_fixed(b, l.int_b, l.frac_b) << count_g;
uint32_t ua = float_to_fixed(a, l.int_a, l.frac_a) << count_b;
uint32_t ur = float_to_fixed(r, l.int_r, l.frac_r, dithered) << 0;
uint32_t ug = float_to_fixed(g, l.int_g, l.frac_g, dithered) << count_r;
uint32_t ub = float_to_fixed(b, l.int_b, l.frac_b, dithered) << count_g;
uint32_t ua = float_to_fixed(a, l.int_a, l.frac_a, dithered) << count_b;
pan_pack_color_32(packed, ur | ug | ub | ua);
}

View file

@ -61,6 +61,7 @@ panfrost_format_to_bifrost_blend(const struct panfrost_device *dev,
bool dithered);
void
pan_pack_color(uint32_t *packed, const union pipe_color_union *color, enum pipe_format format);
pan_pack_color(uint32_t *packed, const union pipe_color_union *color,
enum pipe_format format, bool dithered);
#endif /* PAN_UTIL_H */

View file

@ -115,7 +115,7 @@ int main(int argc, const char **argv)
for (unsigned i = 0; i < ARRAY_SIZE(clear_tests); ++i) {
struct test T = clear_tests[i];
uint32_t packed[4];
pan_pack_color(&packed[0], &T.colour, T.format);
pan_pack_color(&packed[0], &T.colour, T.format, T.dithered);
ASSERT_EQ(T.packed, packed);
}

View file

@ -593,7 +593,7 @@ panvk_cmd_prepare_clear_values(struct panvk_cmd_buffer *cmdbuf,
}
} else if (attachment->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
union pipe_color_union *col = (union pipe_color_union *) &in[i].color;
pan_pack_color(cmdbuf->state.clear[i].color, col, fmt);
pan_pack_color(cmdbuf->state.clear[i].color, col, fmt, false);
}
}
}