panfrost_vt_attach_framebuffer(struct panfrost_context *ctx,
struct mali_vertex_tiler_postfix *postfix)
{
- struct panfrost_device *dev = pan_device(ctx->base.screen);
struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx);
-
- /* If we haven't, reserve space for the framebuffer */
-
- if (!batch->framebuffer.gpu) {
- unsigned size = (dev->quirks & MIDGARD_SFBD) ?
- sizeof(struct mali_single_framebuffer) :
- sizeof(struct mali_framebuffer);
-
- batch->framebuffer = panfrost_pool_alloc(&batch->pool, size);
-
- /* Tag the pointer */
- if (!(dev->quirks & MIDGARD_SFBD))
- batch->framebuffer.gpu |= MALI_MFBD;
- }
-
- postfix->shared_memory = batch->framebuffer.gpu;
+ postfix->shared_memory = panfrost_batch_reserve_framebuffer(batch);
}
static void
struct panfrost_rasterizer *rasterizer = ctx->rasterizer;
if (!panfrost_writes_point_size(ctx)) {
- bool points = prefix->draw_mode == MALI_POINTS;
+ bool points = prefix->draw_mode == MALI_DRAW_MODE_POINTS;
float val = 0.0f;
if (rasterizer)
return MALI_FUNC_GREATER;
case PIPE_FUNC_NOTEQUAL:
- return MALI_FUNC_NOTEQUAL;
+ return MALI_FUNC_NOT_EQUAL;
case PIPE_FUNC_GEQUAL:
return MALI_FUNC_GEQUAL;
{
switch (in) {
case PIPE_STENCIL_OP_KEEP:
- return MALI_STENCIL_KEEP;
+ return MALI_STENCIL_OP_KEEP;
case PIPE_STENCIL_OP_ZERO:
- return MALI_STENCIL_ZERO;
+ return MALI_STENCIL_OP_ZERO;
case PIPE_STENCIL_OP_REPLACE:
- return MALI_STENCIL_REPLACE;
+ return MALI_STENCIL_OP_REPLACE;
case PIPE_STENCIL_OP_INCR:
- return MALI_STENCIL_INCR;
+ return MALI_STENCIL_OP_INCR_SAT;
case PIPE_STENCIL_OP_DECR:
- return MALI_STENCIL_DECR;
+ return MALI_STENCIL_OP_DECR_SAT;
case PIPE_STENCIL_OP_INCR_WRAP:
- return MALI_STENCIL_INCR_WRAP;
+ return MALI_STENCIL_OP_INCR_WRAP;
case PIPE_STENCIL_OP_DECR_WRAP:
- return MALI_STENCIL_DECR_WRAP;
+ return MALI_STENCIL_OP_DECR_WRAP;
case PIPE_STENCIL_OP_INVERT:
- return MALI_STENCIL_INVERT;
+ return MALI_STENCIL_OP_INVERT;
default:
unreachable("Invalid stencil op");
{
switch (w) {
case PIPE_TEX_WRAP_REPEAT:
- return MALI_WRAP_REPEAT;
+ return MALI_WRAP_MODE_REPEAT;
case PIPE_TEX_WRAP_CLAMP:
- return MALI_WRAP_CLAMP;
+ return MALI_WRAP_MODE_CLAMP;
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
- return MALI_WRAP_CLAMP_TO_EDGE;
+ return MALI_WRAP_MODE_CLAMP_TO_EDGE;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
- return MALI_WRAP_CLAMP_TO_BORDER;
+ return MALI_WRAP_MODE_CLAMP_TO_BORDER;
case PIPE_TEX_WRAP_MIRROR_REPEAT:
- return MALI_WRAP_MIRRORED_REPEAT;
+ return MALI_WRAP_MODE_MIRRORED_REPEAT;
case PIPE_TEX_WRAP_MIRROR_CLAMP:
- return MALI_WRAP_MIRRORED_CLAMP;
+ return MALI_WRAP_MODE_MIRRORED_CLAMP;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
- return MALI_WRAP_MIRRORED_CLAMP_TO_EDGE;
+ return MALI_WRAP_MODE_MIRRORED_CLAMP_TO_EDGE;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
- return MALI_WRAP_MIRRORED_CLAMP_TO_BORDER;
+ return MALI_WRAP_MODE_MIRRORED_CLAMP_TO_BORDER;
default:
unreachable("Invalid wrap");
.wrap_s = translate_tex_wrap(cso->wrap_s),
.wrap_t = translate_tex_wrap(cso->wrap_t),
.wrap_r = translate_tex_wrap(cso->wrap_r),
- .compare_func = panfrost_flip_compare_func(func),
+ .compare_func = cso->compare_mode ?
+ panfrost_flip_compare_func(func) :
+ MALI_FUNC_NEVER,
.border_color = {
cso->border_color.f[0],
cso->border_color.f[1],
static void
panfrost_make_stencil_state(const struct pipe_stencil_state *in,
- struct mali_stencil_test *out)
+ void *out)
{
- out->ref = 0; /* Gallium gets it from elsewhere */
-
- out->mask = in->valuemask;
- out->func = panfrost_translate_compare_func(in->func);
- out->sfail = panfrost_translate_stencil_op(in->fail_op);
- out->dpfail = panfrost_translate_stencil_op(in->zfail_op);
- out->dppass = panfrost_translate_stencil_op(in->zpass_op);
+ pan_pack(out, STENCIL, cfg) {
+ cfg.mask = in->valuemask;
+ cfg.compare_function = panfrost_translate_compare_func(in->func);
+ cfg.stencil_fail = panfrost_translate_stencil_op(in->fail_op);
+ cfg.depth_fail = panfrost_translate_stencil_op(in->zfail_op);
+ cfg.depth_pass = panfrost_translate_stencil_op(in->zpass_op);
+ }
}
static void
/* TODO: Sample size */
SET_BIT(fragmeta->unknown2_3, MALI_HAS_MSAA, msaa);
SET_BIT(fragmeta->unknown2_4, MALI_NO_MSAA, !msaa);
+
+ struct panfrost_shader_state *fs;
+ fs = panfrost_get_shader_state(ctx, PIPE_SHADER_FRAGMENT);
+
+ /* EXT_shader_framebuffer_fetch requires the shader to be run
+ * per-sample when outputs are read. */
+ bool per_sample = ctx->min_samples > 1 || fs->outputs_read;
+ SET_BIT(fragmeta->unknown2_3, MALI_PER_SAMPLE, msaa && per_sample);
+
fragmeta->depth_units = rast->offset_units * 2.0f;
fragmeta->depth_factor = rast->offset_scale;
struct pipe_stencil_state default_stencil = {
.enabled = 0,
.func = PIPE_FUNC_ALWAYS,
- .fail_op = MALI_STENCIL_KEEP,
- .zfail_op = MALI_STENCIL_KEEP,
- .zpass_op = MALI_STENCIL_KEEP,
+ .fail_op = PIPE_STENCIL_OP_KEEP,
+ .zfail_op = PIPE_STENCIL_OP_KEEP,
+ .zpass_op = PIPE_STENCIL_OP_KEEP,
.writemask = 0xFF,
.valuemask = 0xFF
};
panfrost_make_stencil_state(&zsa->stencil[0],
&fragmeta->stencil_front);
fragmeta->stencil_mask_front = zsa->stencil[0].writemask;
- fragmeta->stencil_front.ref = ctx->stencil_ref.ref_value[0];
+
+ /* Bottom 8-bits of stencil state is the stencil ref, ref is no
+ * more than 8-bits. Be extra careful. */
+ fragmeta->stencil_front.opaque[0] |= ctx->stencil_ref.ref_value[0];
/* If back-stencil is not enabled, use the front values */
panfrost_make_stencil_state(&zsa->stencil[1],
&fragmeta->stencil_back);
fragmeta->stencil_mask_back = zsa->stencil[1].writemask;
- fragmeta->stencil_back.ref = ctx->stencil_ref.ref_value[1];
+ fragmeta->stencil_back.opaque[0] |= ctx->stencil_ref.ref_value[1];
} else {
fragmeta->stencil_back = fragmeta->stencil_front;
fragmeta->stencil_mask_back = fragmeta->stencil_mask_front;
- fragmeta->stencil_back.ref = fragmeta->stencil_front.ref;
}
if (zsa->depth.enabled)
struct mali_shader_meta *fragmeta,
void *rts)
{
+ struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx);
const struct panfrost_device *dev = pan_device(ctx->base.screen);
struct panfrost_shader_state *fs;
fs = panfrost_get_shader_state(ctx, PIPE_SHADER_FRAGMENT);
SET_BIT(fragmeta->unknown2_3, MALI_CAN_DISCARD,
!blend[0].no_blending || fs->can_discard);
+
+ batch->draws |= PIPE_CLEAR_COLOR0;
return;
}
if (ctx->pipe_framebuffer.nr_cbufs > i && !blend[i].no_colour) {
flags = 0x200;
+ batch->draws |= (PIPE_CLEAR_COLOR0 << i);
bool is_srgb = (ctx->pipe_framebuffer.nr_cbufs > i) &&
(ctx->pipe_framebuffer.cbufs[i]) &&
SET_BIT(fragmeta->midgard1.flags_lo, MALI_HELPER_INVOCATIONS,
fs->helper_invocations);
+ /* If discard is enabled, which bit we set to convey this
+ * depends on if depth/stencil is used for the draw or not.
+ * Just one of depth OR stencil is enough to trigger this. */
+
const struct pipe_depth_stencil_alpha_state *zsa = ctx->depth_stencil;
+ bool zs_enabled = fs->writes_depth || fs->writes_stencil;
- bool depth_enabled = fs->writes_depth ||
- (zsa && zsa->depth.enabled && zsa->depth.func != PIPE_FUNC_ALWAYS);
+ if (zsa) {
+ zs_enabled |= (zsa->depth.enabled && zsa->depth.func != PIPE_FUNC_ALWAYS);
+ zs_enabled |= zsa->stencil[0].enabled;
+ }
SET_BIT(fragmeta->midgard1.flags_lo, MALI_READS_TILEBUFFER,
- fs->outputs_read || (!depth_enabled && fs->can_discard));
- SET_BIT(fragmeta->midgard1.flags_lo, MALI_READS_ZS, depth_enabled && fs->can_discard);
+ fs->outputs_read || (!zs_enabled && fs->can_discard));
+ SET_BIT(fragmeta->midgard1.flags_lo, MALI_READS_ZS, zs_enabled && fs->can_discard);
}
panfrost_frag_meta_rasterizer_update(ctx, fragmeta);
postfix->shader = shader_ptr;
}
-static void
-panfrost_mali_viewport_init(struct panfrost_context *ctx,
- struct mali_viewport *mvp)
+void
+panfrost_emit_viewport(struct panfrost_batch *batch,
+ struct mali_vertex_tiler_postfix *tiler_postfix)
{
+ struct panfrost_context *ctx = batch->ctx;
const struct pipe_viewport_state *vp = &ctx->pipe_viewport;
-
- /* Clip bounds are encoded as floats. The viewport itself is encoded as
- * (somewhat) asymmetric ints. */
-
const struct pipe_scissor_state *ss = &ctx->scissor;
+ const struct pipe_rasterizer_state *rast = &ctx->rasterizer->base;
+ const struct pipe_framebuffer_state *fb = &ctx->pipe_framebuffer;
- memset(mvp, 0, sizeof(*mvp));
-
- /* By default, do no viewport clipping, i.e. clip to (-inf, inf) in
- * each direction. Clipping to the viewport in theory should work, but
- * in practice causes issues when we're not explicitly trying to
- * scissor */
-
- *mvp = (struct mali_viewport) {
- .clip_minx = -INFINITY,
- .clip_miny = -INFINITY,
- .clip_maxx = INFINITY,
- .clip_maxy = INFINITY,
- };
-
- /* Always scissor to the viewport by default. */
+ /* Derive min/max from translate/scale. Note since |x| >= 0 by
+ * definition, we have that -|x| <= |x| hence translate - |scale| <=
+ * translate + |scale|, so the ordering is correct here. */
float vp_minx = (int) (vp->translate[0] - fabsf(vp->scale[0]));
float vp_maxx = (int) (vp->translate[0] + fabsf(vp->scale[0]));
-
float vp_miny = (int) (vp->translate[1] - fabsf(vp->scale[1]));
float vp_maxy = (int) (vp->translate[1] + fabsf(vp->scale[1]));
-
float minz = (vp->translate[2] - fabsf(vp->scale[2]));
float maxz = (vp->translate[2] + fabsf(vp->scale[2]));
- /* Apply the scissor test */
-
- unsigned minx, miny, maxx, maxy;
-
- if (ss && ctx->rasterizer && ctx->rasterizer->base.scissor) {
- minx = MAX2(ss->minx, vp_minx);
- miny = MAX2(ss->miny, vp_miny);
- maxx = MIN2(ss->maxx, vp_maxx);
- maxy = MIN2(ss->maxy, vp_maxy);
- } else {
- minx = vp_minx;
- miny = vp_miny;
- maxx = vp_maxx;
- maxy = vp_maxy;
- }
-
- /* Hardware needs the min/max to be strictly ordered, so flip if we
- * need to. The viewport transformation in the vertex shader will
- * handle the negatives if we don't */
-
- if (miny > maxy) {
- unsigned temp = miny;
- miny = maxy;
- maxy = temp;
- }
+ /* Scissor to the intersection of viewport and to the scissor, clamped
+ * to the framebuffer */
- if (minx > maxx) {
- unsigned temp = minx;
- minx = maxx;
- maxx = temp;
- }
+ unsigned minx = MIN2(fb->width, vp_minx);
+ unsigned maxx = MIN2(fb->width, vp_maxx);
+ unsigned miny = MIN2(fb->height, vp_miny);
+ unsigned maxy = MIN2(fb->height, vp_maxy);
- if (minz > maxz) {
- float temp = minz;
- minz = maxz;
- maxz = temp;
+ if (ss && rast && rast->scissor) {
+ minx = MAX2(ss->minx, minx);
+ miny = MAX2(ss->miny, miny);
+ maxx = MIN2(ss->maxx, maxx);
+ maxy = MIN2(ss->maxy, maxy);
}
- /* Clamp to the framebuffer size as a last check */
-
- minx = MIN2(ctx->pipe_framebuffer.width, minx);
- maxx = MIN2(ctx->pipe_framebuffer.width, maxx);
-
- miny = MIN2(ctx->pipe_framebuffer.height, miny);
- maxy = MIN2(ctx->pipe_framebuffer.height, maxy);
-
- /* Upload */
+ struct panfrost_transfer T = panfrost_pool_alloc(&batch->pool, MALI_VIEWPORT_LENGTH);
- mvp->viewport0[0] = minx;
- mvp->viewport1[0] = MALI_POSITIVE(maxx);
+ pan_pack(T.cpu, VIEWPORT, cfg) {
+ cfg.scissor_minimum_x = minx;
+ cfg.scissor_minimum_y = miny;
+ cfg.scissor_maximum_x = maxx - 1;
+ cfg.scissor_maximum_y = maxy - 1;
- mvp->viewport0[1] = miny;
- mvp->viewport1[1] = MALI_POSITIVE(maxy);
-
- bool clip_near = true;
- bool clip_far = true;
-
- if (ctx->rasterizer) {
- clip_near = ctx->rasterizer->base.depth_clip_near;
- clip_far = ctx->rasterizer->base.depth_clip_far;
+ cfg.minimum_z = rast->depth_clip_near ? minz : -INFINITY;
+ cfg.maximum_z = rast->depth_clip_far ? maxz : INFINITY;
}
- mvp->clip_minz = clip_near ? minz : -INFINITY;
- mvp->clip_maxz = clip_far ? maxz : INFINITY;
-}
-
-void
-panfrost_emit_viewport(struct panfrost_batch *batch,
- struct mali_vertex_tiler_postfix *tiler_postfix)
-{
- struct panfrost_context *ctx = batch->ctx;
- struct mali_viewport mvp;
-
- panfrost_mali_viewport_init(batch->ctx, &mvp);
-
- /* Update the job, unless we're doing wallpapering (whose lack of
- * scissor we can ignore, since if we "miss" a tile of wallpaper, it'll
- * just... be faster :) */
-
- if (!ctx->wallpaper_batch)
- panfrost_batch_union_scissor(batch, mvp.viewport0[0],
- mvp.viewport0[1],
- mvp.viewport1[0] + 1,
- mvp.viewport1[1] + 1);
-
- tiler_postfix->viewport = panfrost_pool_upload(&batch->pool, &mvp,
- sizeof(mvp));
+ tiler_postfix->viewport = T.gpu;
+ panfrost_batch_union_scissor(batch, minx, miny, maxx, maxy);
}
static mali_ptr
unsigned ubo_count = panfrost_ubo_count(ctx, stage);
assert(ubo_count >= 1);
- size_t sz = sizeof(uint64_t) * ubo_count;
- uint64_t ubos[PAN_MAX_CONST_BUFFERS];
- int uniform_count = ss->uniform_count;
+ size_t sz = MALI_UNIFORM_BUFFER_LENGTH * ubo_count;
+ struct panfrost_transfer ubos = panfrost_pool_alloc(&batch->pool, sz);
+ uint64_t *ubo_ptr = (uint64_t *) ubos.cpu;
/* Upload uniforms as a UBO */
- ubos[0] = MALI_MAKE_UBO(2 + uniform_count, transfer.gpu);
+
+ if (ss->uniform_count) {
+ pan_pack(ubo_ptr, UNIFORM_BUFFER, cfg) {
+ cfg.entries = ss->uniform_count;
+ cfg.pointer = transfer.gpu;
+ }
+ } else {
+ *ubo_ptr = 0;
+ }
/* The rest are honest-to-goodness UBOs */
bool empty = usz == 0;
if (!enabled || empty) {
- /* Stub out disabled UBOs to catch accesses */
- ubos[ubo] = MALI_MAKE_UBO(0, 0xDEAD0000);
+ ubo_ptr[ubo] = 0;
continue;
}
- mali_ptr gpu = panfrost_map_constant_buffer_gpu(batch, stage,
- buf, ubo);
-
- unsigned bytes_per_field = 16;
- unsigned aligned = ALIGN_POT(usz, bytes_per_field);
- ubos[ubo] = MALI_MAKE_UBO(aligned / bytes_per_field, gpu);
+ pan_pack(ubo_ptr + ubo, UNIFORM_BUFFER, cfg) {
+ cfg.entries = DIV_ROUND_UP(usz, 16);
+ cfg.pointer = panfrost_map_constant_buffer_gpu(batch,
+ stage, buf, ubo);
+ }
}
- mali_ptr ubufs = panfrost_pool_upload(&batch->pool, ubos, sz);
postfix->uniforms = transfer.gpu;
- postfix->uniform_buffers = ubufs;
+ postfix->uniform_buffers = ubos.gpu;
buf->dirty_mask = 0;
}
{
struct panfrost_resource *rsrc = pan_resource(view->base.texture);
if (view->texture_bo != rsrc->bo->gpu ||
- view->layout != rsrc->layout) {
+ view->modifier != rsrc->modifier) {
panfrost_bo_unreference(view->bo);
panfrost_create_sampler_view_bo(view, pctx, &rsrc->base);
}
if (wallpapering) {
/* Inject in reverse order, with "predicted" job indices.
* THIS IS A HACK XXX */
- panfrost_new_job(&batch->pool, &batch->scoreboard, JOB_TYPE_TILER, false,
+ panfrost_new_job(&batch->pool, &batch->scoreboard, MALI_JOB_TYPE_TILER, false,
batch->scoreboard.job_index + 2, tp, tp_size, true);
- panfrost_new_job(&batch->pool, &batch->scoreboard, JOB_TYPE_VERTEX, false, 0,
+ panfrost_new_job(&batch->pool, &batch->scoreboard, MALI_JOB_TYPE_VERTEX, false, 0,
vp, vp_size, true);
return;
}
bool rasterizer_discard = ctx->rasterizer &&
ctx->rasterizer->base.rasterizer_discard;
- unsigned vertex = panfrost_new_job(&batch->pool, &batch->scoreboard, JOB_TYPE_VERTEX, false, 0,
+ unsigned vertex = panfrost_new_job(&batch->pool, &batch->scoreboard, MALI_JOB_TYPE_VERTEX, false, 0,
vp, vp_size, false);
if (rasterizer_discard)
return;
- panfrost_new_job(&batch->pool, &batch->scoreboard, JOB_TYPE_TILER, false, vertex, tp, tp_size,
+ panfrost_new_job(&batch->pool, &batch->scoreboard, MALI_JOB_TYPE_TILER, false, vertex, tp, tp_size,
false);
}