diff --git a/src/panfrost/lib/pan_format.c b/src/panfrost/lib/pan_format.c index bcb3ff0d592..e27f207b8cf 100644 --- a/src/panfrost/lib/pan_format.c +++ b/src/panfrost/lib/pan_format.c @@ -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_), diff --git a/src/panfrost/util/pan_lower_framebuffer.c b/src/panfrost/util/pan_lower_framebuffer.c index 80a88f636ae..c31d043babc 100644 --- a/src/panfrost/util/pan_lower_framebuffer.c +++ b/src/panfrost/util/pan_lower_framebuffer.c @@ -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"); } }