panfrost: Enable rendering to 16-bit and 32-bit
Bifrost onwards handle this in hardware, and the Midgard lowering isn't too terrible. Enable the format, otherwise desktop GL apps such as Hacknet try to render to the format and get an incomplete framebuffer. Cc stable because apparently we've been advertising this format unintentionally as a result of some other interaction? Unclear how Hacknet is hitting this, maybe it's an app bug. Shrug, it's not a big deal regardless. Additionally, we need to restrict texturing from 32-bit normalized due to a restriction added with the v7 pixel format fiasco. That means restricting rendering to 32-bit normalized on v7 onwards. Closes: #7251 Signed-off-by: Alyssa Rosenzweig <alyssa@collabora.com> Tested-by: Dang Huynh <danct12@disroot.org> Cc: mesa-stable Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19358>
This commit is contained in:
committed by
Marge Bot
parent
3a9cdd780d
commit
1ff3b87ba2
@@ -398,15 +398,11 @@ const struct panfrost_format GENX(panfrost_pipe_format)[PIPE_FORMAT_COUNT] = {
|
||||
FMT(R9G9B9E5_FLOAT, R9F_G9F_B9F_E5F, RGB1, L, VT__),
|
||||
FMT(R8_SNORM, R8_SNORM, R001, L, VT__),
|
||||
FMT(R16_SNORM, R16_SNORM, R001, L, VT__),
|
||||
FMT(R32_SNORM, R32_SNORM, R001, L, VT__),
|
||||
FMT(R8G8_SNORM, RG8_SNORM, RG01, L, VT__),
|
||||
FMT(R16G16_SNORM, RG16_SNORM, RG01, L, VT__),
|
||||
FMT(R32G32_SNORM, RG32_SNORM, RG01, L, VT__),
|
||||
FMT(R8G8B8_SNORM, RGB8_SNORM, RGB1, L, VT__),
|
||||
FMT(R32G32B32_SNORM, RGB32_SNORM, RGB1, L, VT__),
|
||||
FMT(R8G8B8A8_SNORM, RGBA8_SNORM, RGBA, L, VT__),
|
||||
FMT(R16G16B16A16_SNORM, RGBA16_SNORM, RGBA, L, VT__),
|
||||
FMT(R32G32B32A32_SNORM, RGBA32_SNORM, RGBA, L, VT__),
|
||||
FMT(I8_SINT, R8I, RRRR, L, VTR_),
|
||||
FMT(L8_SINT, R8I, RRR1, L, VTR_),
|
||||
FMT(I8_UINT, R8UI, RRRR, L, VTR_),
|
||||
@@ -441,13 +437,34 @@ const struct panfrost_format GENX(panfrost_pipe_format)[PIPE_FORMAT_COUNT] = {
|
||||
FMT(R32G32B32_FLOAT, RGB32F, RGB1, L, VTR_),
|
||||
FMT(R32G32B32A32_FLOAT, RGBA32F, RGBA, L, VTR_),
|
||||
FMT(R8_UNORM, R8_UNORM, R001, L, VTR_),
|
||||
FMT(R16_UNORM, R16_UNORM, R001, L, VT__),
|
||||
FMT(R32_UNORM, R32_UNORM, R001, L, VT__),
|
||||
FMT(R16_UNORM, R16_UNORM, R001, L, VTR_),
|
||||
FMT(R8G8_UNORM, RG8_UNORM, RG01, L, VTR_),
|
||||
FMT(R16G16_UNORM, RG16_UNORM, RG01, L, VT__),
|
||||
FMT(R32G32_UNORM, RG32_UNORM, RG01, L, VT__),
|
||||
FMT(R16G16_UNORM, RG16_UNORM, RG01, L, VTR_),
|
||||
FMT(R8G8B8_UNORM, RGB8_UNORM, RGB1, L, VTR_),
|
||||
|
||||
/* 32-bit NORM is not texturable in v7 onwards. It's renderable
|
||||
* everywhere, but rendering without texturing is not useful.
|
||||
*/
|
||||
#if PAN_ARCH <= 6
|
||||
FMT(R32_UNORM, R32_UNORM, R001, L, VTR_),
|
||||
FMT(R32G32_UNORM, RG32_UNORM, RG01, L, VTR_),
|
||||
FMT(R32G32B32_UNORM, RGB32_UNORM, RGB1, L, VT__),
|
||||
FMT(R32G32B32A32_UNORM, RGBA32_UNORM, RGBA, L, VTR_),
|
||||
FMT(R32_SNORM, R32_SNORM, R001, L, VT__),
|
||||
FMT(R32G32_SNORM, RG32_SNORM, RG01, L, VT__),
|
||||
FMT(R32G32B32_SNORM, RGB32_SNORM, RGB1, L, VT__),
|
||||
FMT(R32G32B32A32_SNORM, RGBA32_SNORM, RGBA, L, VT__),
|
||||
#else
|
||||
FMT(R32_UNORM, R32_UNORM, R001, L, V___),
|
||||
FMT(R32G32_UNORM, RG32_UNORM, RG01, L, V___),
|
||||
FMT(R32G32B32_UNORM, RGB32_UNORM, RGB1, L, V___),
|
||||
FMT(R32G32B32A32_UNORM, RGBA32_UNORM, RGBA, L, V___),
|
||||
FMT(R32_SNORM, R32_SNORM, R001, L, V___),
|
||||
FMT(R32G32_SNORM, RG32_SNORM, RG01, L, V___),
|
||||
FMT(R32G32B32_SNORM, RGB32_SNORM, RGB1, L, V___),
|
||||
FMT(R32G32B32A32_SNORM, RGBA32_SNORM, RGBA, L, V___),
|
||||
#endif
|
||||
|
||||
/* Don't allow render/texture for 48-bit */
|
||||
FMT(R16G16B16_UNORM, RGB16_UNORM, RGB1, L, V___),
|
||||
FMT(R16G16B16_SINT, RGB16I, RGB1, L, V___),
|
||||
@@ -456,16 +473,9 @@ const struct panfrost_format GENX(panfrost_pipe_format)[PIPE_FORMAT_COUNT] = {
|
||||
FMT(R16G16B16_SSCALED, RGB16I, RGB1, L, V___),
|
||||
FMT(R16G16B16_SNORM, RGB16_SNORM, RGB1, L, V___),
|
||||
FMT(R16G16B16_UINT, RGB16UI, RGB1, L, V___),
|
||||
|
||||
#if PAN_ARCH <= 6
|
||||
FMT(R32G32B32_UNORM, RGB32_UNORM, RGB1, L, VT__),
|
||||
#else
|
||||
FMT(R32G32B32_UNORM, RGB32_UNORM, RGB1, L, V___),
|
||||
#endif
|
||||
FMT(R4G4B4A4_UNORM, RGBA4_UNORM, RGBA, L, VTR_),
|
||||
FMT(B4G4R4A4_UNORM, RGBA4_UNORM, BGRA, L, VTR_),
|
||||
FMT(R16G16B16A16_UNORM, RGBA16_UNORM, RGBA, L, VT__),
|
||||
FMT(R32G32B32A32_UNORM, RGBA32_UNORM, RGBA, L, VT__),
|
||||
FMT(R16G16B16A16_UNORM, RGBA16_UNORM, RGBA, L, VTR_),
|
||||
FMT(B8G8R8A8_UNORM, RGBA8_UNORM, BGRA, L, VTR_),
|
||||
FMT(B8G8R8X8_UNORM, RGBA8_UNORM, BGR1, L, VTR_),
|
||||
FMT(A8R8G8B8_UNORM, RGBA8_UNORM, GBAR, L, VTR_),
|
||||
|
||||
@@ -99,6 +99,13 @@ pan_is_format_native(const struct util_format_description *desc, bool broken_ld_
|
||||
if (desc->format == PIPE_FORMAT_R11G11B10_FLOAT)
|
||||
return false;
|
||||
|
||||
if (desc->is_array) {
|
||||
int c = util_format_get_first_non_void_channel(desc->format);
|
||||
assert(c >= 0);
|
||||
if (desc->channel[c].size > 8)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -118,12 +125,6 @@ pan_replicate(nir_builder *b, nir_ssa_def *v, unsigned num_components)
|
||||
return nir_vec(b, replicated, 4);
|
||||
}
|
||||
|
||||
static nir_ssa_def *
|
||||
pan_unpack_pure_32(nir_builder *b, nir_ssa_def *pack, unsigned num_components)
|
||||
{
|
||||
return nir_channels(b, pack, (1 << num_components) - 1);
|
||||
}
|
||||
|
||||
/* Pure x16 formats are x16 unpacked, so it's similar, but we need to pack
|
||||
* upper/lower halves of course */
|
||||
|
||||
@@ -205,6 +206,24 @@ pan_unpack_pure_8(nir_builder *b, nir_ssa_def *pack, unsigned num_components)
|
||||
return nir_channels(b, unpacked, (1 << num_components) - 1);
|
||||
}
|
||||
|
||||
static nir_ssa_def *
|
||||
pan_fsat(nir_builder *b, nir_ssa_def *v, bool is_signed)
|
||||
{
|
||||
if (is_signed)
|
||||
return nir_fsat_signed_mali(b, v);
|
||||
else
|
||||
return nir_fsat(b, v);
|
||||
}
|
||||
|
||||
static float
|
||||
norm_scale(bool snorm, unsigned bits)
|
||||
{
|
||||
if (snorm)
|
||||
return (1 << (bits - 1)) - 1;
|
||||
else
|
||||
return (1 << bits) - 1;
|
||||
}
|
||||
|
||||
/* For <= 8-bits per channel, [U,S]NORM formats are packed like [U,S]NORM 8,
|
||||
* with zeroes spacing out each component as needed */
|
||||
|
||||
@@ -226,11 +245,7 @@ pan_pack_norm(nir_builder *b, nir_ssa_def *v,
|
||||
|
||||
/* If a channel has N bits, we pad out to the byte by (8 - N) bits */
|
||||
nir_ssa_def *shifts = nir_imm_ivec4(b, 8 - x, 8 - y, 8 - z, 8 - w);
|
||||
|
||||
nir_ssa_def *clamped =
|
||||
is_signed ?
|
||||
nir_fsat_signed_mali(b, nir_pad_vec4(b, v)) :
|
||||
nir_fsat(b, nir_pad_vec4(b, v));
|
||||
nir_ssa_def *clamped = pan_fsat(b, nir_pad_vec4(b, v), is_signed);
|
||||
|
||||
nir_ssa_def *f = nir_fmul(b, clamped, scales);
|
||||
nir_ssa_def *u8 = nir_f2u8(b, nir_fround_even(b, f));
|
||||
@@ -371,6 +386,21 @@ pan_linear_to_srgb(nir_builder *b, nir_ssa_def *linear)
|
||||
return nir_vec(b, comp, 4);
|
||||
}
|
||||
|
||||
static nir_ssa_def *
|
||||
pan_unpack_pure(nir_builder *b, nir_ssa_def *packed, unsigned size, unsigned nr)
|
||||
{
|
||||
switch (size) {
|
||||
case 32:
|
||||
return nir_trim_vector(b, packed, nr);
|
||||
case 16:
|
||||
return pan_unpack_pure_16(b, packed, nr);
|
||||
case 8:
|
||||
return pan_unpack_pure_8(b, packed, nr);
|
||||
default:
|
||||
unreachable("Unrenderable size");
|
||||
}
|
||||
}
|
||||
|
||||
/* Generic dispatches for un/pack regardless of format */
|
||||
|
||||
static nir_ssa_def *
|
||||
@@ -382,18 +412,23 @@ pan_unpack(nir_builder *b,
|
||||
int c = util_format_get_first_non_void_channel(desc->format);
|
||||
assert(c >= 0);
|
||||
struct util_format_channel_description d = desc->channel[c];
|
||||
nir_ssa_def *unpacked = pan_unpack_pure(b, packed, d.size, desc->nr_channels);
|
||||
|
||||
if (d.size == 32 || d.size == 16) {
|
||||
assert(!d.normalized);
|
||||
assert(d.type == UTIL_FORMAT_TYPE_FLOAT || d.pure_integer);
|
||||
/* Normalized formats are unpacked as integers. We need to
|
||||
* convert to float for the final result.
|
||||
*/
|
||||
if (d.normalized) {
|
||||
bool snorm = desc->is_snorm;
|
||||
unsigned float_sz = (d.size <= 8 ? 16 : 32);
|
||||
float multiplier = norm_scale(snorm, d.size);
|
||||
|
||||
return d.size == 32 ? pan_unpack_pure_32(b, packed, desc->nr_channels) :
|
||||
pan_unpack_pure_16(b, packed, desc->nr_channels);
|
||||
} else if (d.size == 8) {
|
||||
assert(d.pure_integer);
|
||||
return pan_unpack_pure_8(b, packed, desc->nr_channels);
|
||||
nir_ssa_def *as_float =
|
||||
snorm ? nir_i2fN(b, unpacked, float_sz) :
|
||||
nir_u2fN(b, unpacked, float_sz);
|
||||
|
||||
return nir_fmul_imm(b, as_float, 1.0 / multiplier);
|
||||
} else {
|
||||
unreachable("Unrenderable size");
|
||||
return unpacked;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,28 +457,33 @@ pan_pack(nir_builder *b,
|
||||
if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
|
||||
unpacked = pan_linear_to_srgb(b, unpacked);
|
||||
|
||||
if (util_format_is_unorm8(desc))
|
||||
return pan_pack_unorm(b, unpacked, 8, 8, 8, 8);
|
||||
|
||||
if (util_format_is_snorm8(desc->format))
|
||||
return pan_pack_snorm(b, unpacked, 8, 8, 8, 8);
|
||||
|
||||
if (desc->is_array) {
|
||||
int c = util_format_get_first_non_void_channel(desc->format);
|
||||
assert(c >= 0);
|
||||
struct util_format_channel_description d = desc->channel[c];
|
||||
|
||||
if (d.size == 32 || d.size == 16) {
|
||||
assert(!d.normalized);
|
||||
assert(d.type == UTIL_FORMAT_TYPE_FLOAT || d.pure_integer);
|
||||
/* Pure formats are packed as-is */
|
||||
nir_ssa_def *raw = unpacked;
|
||||
|
||||
return d.size == 32 ?
|
||||
pan_replicate(b, unpacked, desc->nr_channels) :
|
||||
pan_pack_pure_16(b, unpacked, desc->nr_channels);
|
||||
} else if (d.size == 8) {
|
||||
assert(d.pure_integer);
|
||||
return pan_pack_pure_8(b, unpacked, desc->nr_channels);
|
||||
} else {
|
||||
/* Normalized formats get normalized first */
|
||||
if (d.normalized) {
|
||||
bool snorm = desc->is_snorm;
|
||||
float multiplier = norm_scale(snorm, d.size);
|
||||
nir_ssa_def *clamped = pan_fsat(b, unpacked, snorm);
|
||||
nir_ssa_def *normed = nir_fmul_imm(b, clamped, multiplier);
|
||||
|
||||
raw = nir_f2uN(b, normed, d.size);
|
||||
}
|
||||
|
||||
/* Pack the raw format */
|
||||
switch (d.size) {
|
||||
case 32:
|
||||
return pan_replicate(b, raw, desc->nr_channels);
|
||||
case 16:
|
||||
return pan_pack_pure_16(b, raw, desc->nr_channels);
|
||||
case 8:
|
||||
return pan_pack_pure_8(b, raw, desc->nr_channels);
|
||||
default:
|
||||
unreachable("Unrenderable size");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user