panfrost: Emit blend descriptors on Bifrost

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4724>
This commit is contained in:
Tomeu Vizoso 2020-04-24 08:40:51 +02:00
parent 33b13b9fbd
commit 3c98c452f0
9 changed files with 197 additions and 53 deletions

View file

@ -90,6 +90,31 @@ pan_format_from_glsl(const struct glsl_type *type)
MALI_NR_CHANNELS(4);
}
static enum bifrost_shader_type
bifrost_blend_type_from_nir(nir_alu_type nir_type)
{
switch(nir_type) {
case 0: /* Render target not in use */
return 0;
case nir_type_float16:
return BIFROST_BLEND_F16;
case nir_type_float32:
return BIFROST_BLEND_F32;
case nir_type_int32:
return BIFROST_BLEND_I32;
case nir_type_uint32:
return BIFROST_BLEND_U32;
case nir_type_int16:
return BIFROST_BLEND_I16;
case nir_type_uint16:
return BIFROST_BLEND_U16;
default:
DBG("Unsupported blend shader type for NIR alu type %d", nir_type);
assert(0);
return 0;
}
}
void
panfrost_shader_compile(struct panfrost_context *ctx,
enum pipe_shader_ir ir_type,
@ -197,6 +222,10 @@ panfrost_shader_compile(struct panfrost_context *ctx,
state->uniform_cutoff = program.uniform_cutoff;
state->work_reg_count = program.work_register_count;
if (dev->quirks & IS_BIFROST)
for (unsigned i = 0; i < BIFROST_MAX_RENDER_TARGET_COUNT; i++)
state->blend_types[i] = bifrost_blend_type_from_nir(program.blend_types[i]);
unsigned default_vec1_swizzle = panfrost_get_default_swizzle(1);
unsigned default_vec2_swizzle = panfrost_get_default_swizzle(2);
unsigned default_vec4_swizzle = panfrost_get_default_swizzle(4);

View file

@ -615,7 +615,7 @@ panfrost_frag_meta_zsa_update(struct panfrost_context *ctx,
static void
panfrost_frag_meta_blend_update(struct panfrost_context *ctx,
struct mali_shader_meta *fragmeta,
struct midgard_blend_rt *rts)
void *rts)
{
const struct panfrost_device *dev = pan_device(ctx->base.screen);
@ -679,22 +679,56 @@ panfrost_frag_meta_blend_update(struct panfrost_context *ctx,
/* Additional blend descriptor tacked on for jobs using MFBD */
for (unsigned i = 0; i < rt_count; ++i) {
rts[i].flags = 0x200;
if (dev->quirks & IS_BIFROST) {
struct bifrost_blend_rt *brts = rts;
struct panfrost_shader_state *fs;
fs = panfrost_get_shader_state(ctx, PIPE_SHADER_FRAGMENT);
bool is_srgb = (ctx->pipe_framebuffer.nr_cbufs > i) &&
(ctx->pipe_framebuffer.cbufs[i]) &&
util_format_is_srgb(ctx->pipe_framebuffer.cbufs[i]->format);
brts[i].flags = 0x200;
if (blend[i].is_shader) {
/* The blend shader's address needs to be at
* the same top 32 bit as the fragment shader.
* TODO: Ensure that's always the case.
*/
assert((blend[i].shader.gpu & (0xffffffffull << 32)) ==
(fs->bo->gpu & (0xffffffffull << 32)));
brts[i].shader = blend[i].shader.gpu;
brts[i].unk2 = 0x0;
} else {
enum pipe_format format = ctx->pipe_framebuffer.cbufs[i]->format;
const struct util_format_description *format_desc;
format_desc = util_format_description(format);
SET_BIT(rts[i].flags, MALI_BLEND_MRT_SHADER, blend[i].is_shader);
SET_BIT(rts[i].flags, MALI_BLEND_LOAD_TIB, !blend[i].no_blending);
SET_BIT(rts[i].flags, MALI_BLEND_SRGB, is_srgb);
SET_BIT(rts[i].flags, MALI_BLEND_NO_DITHER, !ctx->blend->base.dither);
brts[i].equation = *blend[i].equation.equation;
if (blend[i].is_shader) {
rts[i].blend.shader = blend[i].shader.gpu | blend[i].shader.first_tag;
/* TODO: this is a bit more complicated */
brts[i].constant = blend[i].equation.constant;
brts[i].format = panfrost_format_to_bifrost_blend(format_desc);
brts[i].unk2 = 0x19;
brts[i].shader_type = fs->blend_types[i];
}
} else {
rts[i].blend.equation = *blend[i].equation.equation;
rts[i].blend.constant = blend[i].equation.constant;
struct midgard_blend_rt *mrts = rts;
mrts[i].flags = 0x200;
bool is_srgb = (ctx->pipe_framebuffer.nr_cbufs > i) &&
(ctx->pipe_framebuffer.cbufs[i]) &&
util_format_is_srgb(ctx->pipe_framebuffer.cbufs[i]->format);
SET_BIT(mrts[i].flags, MALI_BLEND_MRT_SHADER, blend[i].is_shader);
SET_BIT(mrts[i].flags, MALI_BLEND_LOAD_TIB, !blend[i].no_blending);
SET_BIT(mrts[i].flags, MALI_BLEND_SRGB, is_srgb);
SET_BIT(mrts[i].flags, MALI_BLEND_NO_DITHER, !ctx->blend->base.dither);
if (blend[i].is_shader) {
mrts[i].blend.shader = blend[i].shader.gpu | blend[i].shader.first_tag;
} else {
mrts[i].blend.equation = *blend[i].equation.equation;
mrts[i].blend.constant = blend[i].equation.constant;
}
}
}
}
@ -702,7 +736,7 @@ panfrost_frag_meta_blend_update(struct panfrost_context *ctx,
static void
panfrost_frag_shader_meta_init(struct panfrost_context *ctx,
struct mali_shader_meta *fragmeta,
struct midgard_blend_rt *rts)
void *rts)
{
const struct panfrost_device *dev = pan_device(ctx->base.screen);
struct panfrost_shader_state *fs;
@ -779,20 +813,31 @@ panfrost_emit_shader_meta(struct panfrost_batch *batch,
struct panfrost_device *dev = pan_device(ctx->base.screen);
unsigned rt_count = MAX2(ctx->pipe_framebuffer.nr_cbufs, 1);
size_t desc_size = sizeof(meta);
struct midgard_blend_rt rts[4];
void *rts = NULL;
struct panfrost_transfer xfer;
unsigned rt_size;
assert(rt_count <= ARRAY_SIZE(rts));
if (dev->quirks & MIDGARD_SFBD)
rt_size = 0;
else if (dev->quirks & IS_BIFROST)
rt_size = sizeof(struct bifrost_blend_rt);
else
rt_size = sizeof(struct midgard_blend_rt);
desc_size += rt_size * rt_count;
if (rt_size)
rts = rzalloc_size(ctx, rt_size * rt_count);
panfrost_frag_shader_meta_init(ctx, &meta, rts);
if (!(dev->quirks & MIDGARD_SFBD))
desc_size += sizeof(*rts) * rt_count;
xfer = panfrost_allocate_transient(batch, desc_size);
memcpy(xfer.cpu, &meta, sizeof(meta));
memcpy(xfer.cpu + sizeof(meta), rts, sizeof(*rts) * rt_count);
memcpy(xfer.cpu + sizeof(meta), rts, rt_size * rt_count);
if (rt_size)
ralloc_free(rts);
shader_ptr = xfer.gpu;
} else {

View file

@ -195,6 +195,8 @@ struct panfrost_shader_state {
unsigned stack_size;
unsigned shared_size;
/* For Bifrost - output type for each RT */
enum bifrost_shader_type blend_types[BIFROST_MAX_RENDER_TARGET_COUNT];
unsigned int varying_count;
struct mali_attr_meta varyings[PIPE_MAX_ATTRIBS];

View file

@ -155,8 +155,9 @@ bi_emit_frag_out(bi_context *ctx, nir_intrinsic_instr *instr)
.vector_channels = 4
};
assert(blend.blend_location < 8);
assert(blend.blend_location < BIFROST_MAX_RENDER_TARGET_COUNT);
assert(ctx->blend_types);
assert(blend.src_types[0]);
ctx->blend_types[blend.blend_location] = blend.src_types[0];
bi_emit(ctx, blend);

View file

@ -275,3 +275,20 @@ panfrost_invert_swizzle(const unsigned char *in, unsigned char *out)
out[idx] = PIPE_SWIZZLE_X + c;
}
}
enum mali_format
panfrost_format_to_bifrost_blend(const struct util_format_description *desc)
{
enum mali_format format = panfrost_find_format(desc);
switch (format) {
case MALI_RGBA4_UNORM:
return MALI_RGBA4;
case MALI_RGBA8_UNORM:
return MALI_RGBA8_2;
case MALI_RGB10_A2_UNORM:
return MALI_RGB10_A2_2;
default:
return format;
}
}

View file

@ -146,4 +146,7 @@ panfrost_get_default_swizzle(unsigned components)
}
}
enum mali_format
panfrost_format_to_bifrost_blend(const struct util_format_description *desc);
#endif

View file

@ -466,6 +466,8 @@ enum bifrost_shader_type {
BIFROST_BLEND_U16 = 5,
};
#define BIFROST_MAX_RENDER_TARGET_COUNT 8
struct bifrost_blend_rt {
/* This is likely an analogue of the flags on
* midgard_blend_rt */
@ -482,51 +484,53 @@ struct bifrost_blend_rt {
* constant_hi = int(f / 255)
* constant_lo = 65535*f - (65535/255) * constant_hi
*/
u16 constant;
struct mali_blend_equation equation;
/*
* - 0x19 normally
* - 0x3 when this slot is unused (everything else is 0 except the index)
* - 0x11 when this is the fourth slot (and it's used)
+ * - 0 when there is a blend shader
* - 0 when there is a blend shader
*/
u16 unk2;
/* increments from 0 to 3 */
u16 index;
union {
struct {
/* So far, I've only seen:
* - R001 for 1-component formats
* - RG01 for 2-component formats
* - RGB1 for 3-component formats
* - RGBA for 4-component formats
*/
u32 swizzle : 12;
enum mali_format format : 8;
union {
struct {
/* So far, I've only seen:
* - R001 for 1-component formats
* - RG01 for 2-component formats
* - RGB1 for 3-component formats
* - RGBA for 4-component formats
*/
u32 swizzle : 12;
enum mali_format format : 8;
/* Type of the shader output variable. Note, this can
* be different from the format.
* enum bifrost_shader_type
*/
u32 shader_type : 3;
u32 zero : 9;
};
/* Type of the shader output variable. Note, this can
* be different from the format.
* enum bifrost_shader_type
*/
u32 zero1 : 4;
u32 shader_type : 3;
u32 zero2 : 5;
};
/* Only the low 32 bits of the blend shader are stored, the
* high 32 bits are implicitly the same as the original shader.
* According to the kernel driver, the program counter for
* shaders is actually only 24 bits, so shaders cannot cross
* the 2^24-byte boundary, and neither can the blend shader.
* The blob handles this by allocating a 2^24 byte pool for
* shaders, and making sure that any blend shaders are stored
* in the same pool as the original shader. The kernel will
* make sure this allocation is aligned to 2^24 bytes.
*/
u32 shader;
};
/* Only the low 32 bits of the blend shader are stored, the
* high 32 bits are implicitly the same as the original shader.
* According to the kernel driver, the program counter for
* shaders is actually only 24 bits, so shaders cannot cross
* the 2^24-byte boundary, and neither can the blend shader.
* The blob handles this by allocating a 2^24 byte pool for
* shaders, and making sure that any blend shaders are stored
* in the same pool as the original shader. The kernel will
* make sure this allocation is aligned to 2^24 bytes.
*/
u32 shader;
};
} __attribute__((packed));
/* Descriptor for the shader. Following this is at least one, up to four blend

View file

@ -1606,8 +1606,51 @@ pandecode_bifrost_blend(void *descs, int job_no, int rt_no)
/* TODO figure out blend shader enable bit */
pandecode_blend_equation(&b->equation);
pandecode_prop("unk2 = 0x%" PRIx16, b->unk2);
pandecode_prop("index = 0x%" PRIx16, b->index);
pandecode_log(".format = ");
pandecode_format_short(b->format, false);
pandecode_swizzle(b->swizzle, b->format);
pandecode_log_cont(",\n");
pandecode_prop("swizzle = 0x%" PRIx32, b->swizzle);
pandecode_prop("format = 0x%" PRIx32, b->format);
if (b->zero1) {
pandecode_msg("XXX: pandecode_bifrost_blend zero1 tripped\n");
pandecode_prop("zero1 = 0x%" PRIx32, b->zero1);
}
pandecode_log(".shader_type = ");
switch(b->shader_type) {
case BIFROST_BLEND_F16:
pandecode_log_cont("BIFROST_BLEND_F16");
break;
case BIFROST_BLEND_F32:
pandecode_log_cont("BIFROST_BLEND_F32");
break;
case BIFROST_BLEND_I32:
pandecode_log_cont("BIFROST_BLEND_I32");
break;
case BIFROST_BLEND_U32:
pandecode_log_cont("BIFROST_BLEND_U32");
break;
case BIFROST_BLEND_I16:
pandecode_log_cont("BIFROST_BLEND_I16");
break;
case BIFROST_BLEND_U16:
pandecode_log_cont("BIFROST_BLEND_U16");
break;
}
pandecode_log_cont(",\n");
if (b->zero2) {
pandecode_msg("XXX: pandecode_bifrost_blend zero2 tripped\n");
pandecode_prop("zero2 = 0x%" PRIx32, b->zero2);
}
pandecode_prop("shader = 0x%" PRIx32, b->shader);
pandecode_indent--;

View file

@ -87,7 +87,7 @@ typedef struct {
int uniform_cutoff;
/* For Bifrost - output type for each RT */
nir_alu_type blend_types[8];
nir_alu_type blend_types[BIFROST_MAX_RENDER_TARGET_COUNT];
/* Prepended before uniforms, mapping to SYSVAL_ names for the
* sysval */