diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c index 049b83f0466..63ff8bdba04 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.c +++ b/src/gallium/drivers/panfrost/pan_cmdstream.c @@ -517,12 +517,7 @@ panfrost_prepare_midgard_fs_state(struct panfrost_context *ctx, /* Reasons to disable early-Z from a shader perspective */ bool late_z = fs->info.fs.can_discard || fs->info.writes_global || fs->info.fs.writes_depth || fs->info.fs.writes_stencil || - (zsa->alpha_func != MALI_FUNC_ALWAYS); - - /* If either depth or stencil is enabled, discard matters */ - bool zs_enabled = - (zsa->base.depth_enabled && zsa->base.depth_func != PIPE_FUNC_ALWAYS) || - zsa->base.stencil[0].enabled; + ((enum mali_func) zsa->base.alpha_func != MALI_FUNC_ALWAYS); bool has_blend_shader = false; @@ -543,9 +538,9 @@ panfrost_prepare_midgard_fs_state(struct panfrost_context *ctx, * reads tilebuffer? flag to compensate */ state->properties.midgard.shader_reads_tilebuffer = fs->info.fs.outputs_read || - (!zs_enabled && fs->info.fs.can_discard); + (!zsa->enabled && fs->info.fs.can_discard); state->properties.midgard.shader_contains_discard = - zs_enabled && fs->info.fs.can_discard; + zsa->enabled && fs->info.fs.can_discard; } if (dev->quirks & MIDGARD_SFBD && ctx->pipe_framebuffer.nr_cbufs > 0) { @@ -611,19 +606,11 @@ panfrost_prepare_fs_state(struct panfrost_context *ctx, state->multisample_misc.evaluate_per_sample = msaa && (ctx->min_samples > 1 || fs->info.fs.sample_shading); - state->multisample_misc.depth_function = zsa->base.depth_enabled ? - (enum mali_func) zsa->base.depth_func : MALI_FUNC_ALWAYS; - - state->multisample_misc.depth_write_mask = zsa->base.depth_writemask; state->multisample_misc.fixed_function_near_discard = rast->depth_clip_near; state->multisample_misc.fixed_function_far_discard = rast->depth_clip_far; state->multisample_misc.shader_depth_range_fixed = true; - state->stencil_mask_misc.stencil_mask_front = zsa->stencil_mask_front; - state->stencil_mask_misc.stencil_mask_back = zsa->stencil_mask_back; - state->stencil_mask_misc.stencil_enable = zsa->base.stencil[0].enabled; state->stencil_mask_misc.alpha_to_coverage = alpha_to_coverage; - state->stencil_mask_misc.alpha_test_compare_function = zsa->alpha_func; state->stencil_mask_misc.depth_range_1 = rast->offset_tri; state->stencil_mask_misc.depth_range_2 = rast->offset_tri; state->stencil_mask_misc.single_sampled_lines = !rast->multisample; @@ -631,8 +618,6 @@ panfrost_prepare_fs_state(struct panfrost_context *ctx, state->depth_factor = rast->offset_scale; bool back_enab = zsa->base.stencil[1].enabled; - state->stencil_front = zsa->stencil_front; - state->stencil_back = zsa->stencil_back; state->stencil_front.reference_value = ctx->stencil_ref.ref_value[0]; state->stencil_back.reference_value = ctx->stencil_ref.ref_value[back_enab ? 1 : 0]; @@ -648,6 +633,7 @@ panfrost_emit_frag_shader(struct panfrost_context *ctx, mali_ptr *blend_shaders) { struct panfrost_device *dev = pan_device(ctx->base.screen); + const struct panfrost_zsa_state *zsa = ctx->depth_stencil; struct panfrost_shader_state *fs = panfrost_get_shader_state(ctx, PIPE_SHADER_FRAGMENT); @@ -673,6 +659,14 @@ panfrost_emit_frag_shader(struct panfrost_context *ctx, if (panfrost_fs_required(fs, ctx->blend, &ctx->pipe_framebuffer)) pan_merge(rsd, fs->partial_rsd, RENDERER_STATE); + /* Word 8, 9 Misc state */ + rsd.opaque[8] |= zsa->rsd_depth.opaque[0]; + rsd.opaque[9] |= zsa->rsd_stencil.opaque[0]; + + /* Word 10, 11 Stencil Front and Back */ + rsd.opaque[10] |= zsa->stencil_front.opaque[0]; + rsd.opaque[11] |= zsa->stencil_back.opaque[0]; + memcpy(fragmeta, &rsd, sizeof(rsd)); } diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c index 49378b968e6..8b07a7120df 100644 --- a/src/gallium/drivers/panfrost/pan_context.c +++ b/src/gallium/drivers/panfrost/pan_context.c @@ -1392,36 +1392,62 @@ pan_pipe_to_stencil_op(enum pipe_stencil_op in) } static inline void -pan_pipe_to_stencil(const struct pipe_stencil_state *in, struct MALI_STENCIL *out) +pan_pipe_to_stencil(const struct pipe_stencil_state *in, + struct mali_stencil_packed *out) { - pan_prepare(out, STENCIL); - out->mask = in->valuemask; - out->compare_function = (enum mali_func) in->func; - out->stencil_fail = pan_pipe_to_stencil_op(in->fail_op); - out->depth_fail = pan_pipe_to_stencil_op(in->zfail_op); - out->depth_pass = pan_pipe_to_stencil_op(in->zpass_op); + pan_pack(out, STENCIL, s) { + s.mask = in->valuemask; + s.compare_function = (enum mali_func) in->func; + s.stencil_fail = pan_pipe_to_stencil_op(in->fail_op); + s.depth_fail = pan_pipe_to_stencil_op(in->zfail_op); + s.depth_pass = pan_pipe_to_stencil_op(in->zpass_op); + } } static void * panfrost_create_depth_stencil_state(struct pipe_context *pipe, const struct pipe_depth_stencil_alpha_state *zsa) { + struct panfrost_device *dev = pan_device(pipe->screen); struct panfrost_zsa_state *so = CALLOC_STRUCT(panfrost_zsa_state); so->base = *zsa; - pan_pipe_to_stencil(&zsa->stencil[0], &so->stencil_front); - so->stencil_mask_front = zsa->stencil[0].writemask; + /* Normalize (there's no separate enable) */ + if (!zsa->alpha_enabled) + so->base.alpha_func = MALI_FUNC_ALWAYS; - if (zsa->stencil[1].enabled) { - pan_pipe_to_stencil(&zsa->stencil[1], &so->stencil_back); - so->stencil_mask_back = zsa->stencil[1].writemask; - } else { - so->stencil_back = so->stencil_front; - so->stencil_mask_back = so->stencil_mask_front; + /* Prepack relevant parts of the Renderer State Descriptor. They will + * be ORed in at draw-time */ + pan_pack(&so->rsd_depth, MULTISAMPLE_MISC, cfg) { + cfg.depth_function = zsa->depth_enabled ? + (enum mali_func) zsa->depth_func : MALI_FUNC_ALWAYS; + + cfg.depth_write_mask = zsa->depth_writemask; } - so->alpha_func = zsa->alpha_enabled ? - (enum mali_func) zsa->alpha_func : MALI_FUNC_ALWAYS; + pan_pack(&so->rsd_stencil, STENCIL_MASK_MISC, cfg) { + cfg.stencil_enable = zsa->stencil[0].enabled; + + cfg.stencil_mask_front = zsa->stencil[0].writemask; + cfg.stencil_mask_back = zsa->stencil[1].enabled ? + zsa->stencil[1].writemask : zsa->stencil[0].writemask; + + if (dev->arch < 6) { + cfg.alpha_test_compare_function = + (enum mali_func) so->base.alpha_func; + } + } + + /* Stencil tests have their own words in the RSD */ + pan_pipe_to_stencil(&zsa->stencil[0], &so->stencil_front); + + if (zsa->stencil[1].enabled) + pan_pipe_to_stencil(&zsa->stencil[1], &so->stencil_back); + else + so->stencil_back = so->stencil_front; + + so->enabled = zsa->stencil[0].enabled || + (zsa->depth_enabled && zsa->depth_func != PIPE_FUNC_ALWAYS); /* TODO: Bounds test should be easy */ assert(!zsa->depth_bounds_test); diff --git a/src/gallium/drivers/panfrost/pan_context.h b/src/gallium/drivers/panfrost/pan_context.h index 5208c8ddadc..e7105f03371 100644 --- a/src/gallium/drivers/panfrost/pan_context.h +++ b/src/gallium/drivers/panfrost/pan_context.h @@ -257,13 +257,14 @@ struct panfrost_vertex_state { struct panfrost_zsa_state { struct pipe_depth_stencil_alpha_state base; - enum mali_func alpha_func; - /* Precomputed stencil state */ - struct MALI_STENCIL stencil_front; - struct MALI_STENCIL stencil_back; - u8 stencil_mask_front; - u8 stencil_mask_back; + /* Is any depth, stencil, or alpha testing enabled? */ + bool enabled; + + /* Prepacked words from the RSD */ + struct mali_multisample_misc_packed rsd_depth; + struct mali_stencil_mask_misc_packed rsd_stencil; + struct mali_stencil_packed stencil_front, stencil_back; }; struct panfrost_sampler_state {