From: Erik Faye-Lund Date: Wed, 9 Sep 2020 13:07:54 +0000 (+0200) Subject: gallium/util: add blitter-support for stencil-fallback X-Git-Tag: upstream/21.0.0~5165 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e8a40715a8bcd479c0c33eab411d276777153a0e;p=platform%2Fupstream%2Fmesa.git gallium/util: add blitter-support for stencil-fallback This wires up the shader in the previous commit so we can blit without having to reimplement the blitter in the D3D12 driver. This isn't optimal, but it's reasonable enough, and this behavior is rare. Reviewed-by: Marek Olšák Part-of: --- diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index d5b886c..e21076c 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -107,6 +107,9 @@ struct blitter_context_priv */ void *fs_pack_color_zs[TGSI_TEXTURE_COUNT][10]; + /* FS which is meant for replicating indevidual stencil-buffer bits */ + void *fs_stencil_blit_fallback[2]; + /* Blend state. */ void *blend[PIPE_MASK_RGBA+1][2]; /**< blend state with writemask */ void *blend_clear[GET_CLEAR_BLEND_STATE_IDX(PIPE_CLEAR_COLOR)+1]; @@ -116,6 +119,7 @@ struct blitter_context_priv void *dsa_write_depth_keep_stencil; void *dsa_keep_depth_stencil; void *dsa_keep_depth_write_stencil; + void *dsa_replicate_stencil_bit[8]; /* Vertex elements states. */ void *velem_state; @@ -494,6 +498,11 @@ void util_blitter_destroy(struct blitter_context *blitter) pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); + for (i = 0; i < ARRAY_SIZE(ctx->dsa_replicate_stencil_bit); i++) { + if (ctx->dsa_replicate_stencil_bit[i]) + pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_replicate_stencil_bit[i]); + } + unsigned scissor, msaa; for (scissor = 0; scissor < 2; scissor++) { for (msaa = 0; msaa < 2; msaa++) { @@ -565,6 +574,10 @@ void util_blitter_destroy(struct blitter_context *blitter) if (ctx->fs_write_all_cbufs) ctx->delete_fs_state(pipe, ctx->fs_write_all_cbufs); + for (i = 0; i < ARRAY_SIZE(ctx->fs_stencil_blit_fallback); ++i) + if (ctx->fs_stencil_blit_fallback[i]) + ctx->delete_fs_state(pipe, ctx->fs_stencil_blit_fallback[i]); + pipe->delete_sampler_state(pipe, ctx->sampler_state_rect_linear); pipe->delete_sampler_state(pipe, ctx->sampler_state_rect); pipe->delete_sampler_state(pipe, ctx->sampler_state_linear); @@ -2764,3 +2777,127 @@ void util_blitter_custom_shader(struct blitter_context *blitter, util_blitter_restore_render_cond(blitter); util_blitter_unset_running_flag(blitter); } + +static void * +get_stencil_blit_fallback_fs(struct blitter_context_priv *ctx, bool msaa_src) +{ + if (!ctx->fs_stencil_blit_fallback[msaa_src]) { + ctx->fs_stencil_blit_fallback[msaa_src] = + util_make_fs_stencil_blit(ctx->base.pipe, msaa_src); + } + + return ctx->fs_stencil_blit_fallback[msaa_src]; +} + +static void * +get_stencil_blit_fallback_dsa(struct blitter_context_priv *ctx, unsigned i) +{ + assert(i < ARRAY_SIZE(ctx->dsa_replicate_stencil_bit)); + if (!ctx->dsa_replicate_stencil_bit[i]) { + struct pipe_depth_stencil_alpha_state dsa = { 0 }; + dsa.depth.func = PIPE_FUNC_ALWAYS; + dsa.stencil[0].enabled = 1; + dsa.stencil[0].func = PIPE_FUNC_ALWAYS; + dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; + dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; + dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; + dsa.stencil[0].valuemask = 0xff; + dsa.stencil[0].writemask = 1u << i; + + ctx->dsa_replicate_stencil_bit[i] = + ctx->base.pipe->create_depth_stencil_alpha_state(ctx->base.pipe, &dsa); + } + return ctx->dsa_replicate_stencil_bit[i]; +} + +/** + * Performs a series of draws to implement stencil blits texture without + * requiring stencil writes, updating a single bit per pixel at the time. + */ +void +util_blitter_stencil_fallback(struct blitter_context *blitter, + struct pipe_resource *dst, + unsigned dst_level, + unsigned dstx, unsigned dsty, unsigned dstz, + struct pipe_resource *src, + unsigned src_level, + const struct pipe_box *srcbox) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv *)blitter; + struct pipe_context *pipe = ctx->base.pipe; + + /* check the saved state */ + util_blitter_set_running_flag(blitter); + blitter_check_saved_vertex_states(ctx); + blitter_check_saved_fragment_states(ctx); + blitter_check_saved_fb_state(ctx); + blitter_disable_render_cond(ctx); + + /* Initialize the surface. */ + struct pipe_surface *dst_view, dst_templ; + util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz); + dst_view = pipe->create_surface(pipe, dst, &dst_templ); + + /* Initialize the sampler view. */ + struct pipe_sampler_view src_templ, *src_view; + util_blitter_default_src_texture(blitter, &src_templ, src, src_level); + src_templ.format = util_format_stencil_only(src_templ.format); + src_view = pipe->create_sampler_view(pipe, src, &src_templ); + + /* bind states */ + pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA][0]); + pipe->bind_fs_state(pipe, + get_stencil_blit_fallback_fs(ctx, src->nr_samples > 1)); + + /* set a framebuffer state */ + struct pipe_framebuffer_state fb_state = { 0 }; + fb_state.width = srcbox->width; + fb_state.height = srcbox->height; + fb_state.zsbuf = dst_view; + pipe->set_framebuffer_state(pipe, &fb_state); + pipe->set_sample_mask(pipe, ~0); + + blitter_set_common_draw_rect_state(ctx, false, + util_framebuffer_get_num_samples(&fb_state) > 1); + blitter_set_dst_dimensions(ctx, srcbox->width, srcbox->height); + + pipe->clear_depth_stencil(pipe, dst_view, PIPE_CLEAR_STENCIL, 0.0, 0, + dstx, dsty, srcbox->width, srcbox->height, + true); + + pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 1, &src_view); + pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0, 1, &ctx->sampler_state); + + unsigned stencil_bits = + util_format_get_component_bits(dst->format, + UTIL_FORMAT_COLORSPACE_ZS, 1); + + struct pipe_stencil_ref sr = { { (1u << stencil_bits) - 1 } }; + pipe->set_stencil_ref(pipe, &sr); + + for (int i = 0; i < stencil_bits; ++i) { + uint32_t mask = 1 << i; + struct pipe_constant_buffer cb = { + .user_buffer = &mask, + .buffer_size = sizeof(mask), + }; + pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, blitter->cb_slot, + &cb); + + pipe->bind_depth_stencil_alpha_state(pipe, + get_stencil_blit_fallback_dsa(ctx, i)); + + blitter->draw_rectangle(blitter, ctx->velem_state, get_vs_passthrough_pos, + dstx, dsty, + dstx + srcbox->width, dsty + srcbox->height, + 0, stencil_bits, UTIL_BLITTER_ATTRIB_NONE, NULL); + } + + util_blitter_restore_vertex_states(blitter); + util_blitter_restore_fragment_states(blitter); + util_blitter_restore_textures(blitter); + util_blitter_restore_fb_state(blitter); + util_blitter_restore_render_cond(blitter); + util_blitter_restore_constant_buffer_state(blitter); + util_blitter_unset_running_flag(blitter); +} diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h index 72130ad..b82609a 100644 --- a/src/gallium/auxiliary/util/u_blitter.h +++ b/src/gallium/auxiliary/util/u_blitter.h @@ -400,6 +400,16 @@ void util_blitter_custom_shader(struct blitter_context *blitter, struct pipe_surface *dstsurf, void *custom_vs, void *custom_fs); +/* Used by D3D12 for non-MSAA -> MSAA stencil blits */ +void util_blitter_stencil_fallback(struct blitter_context *blitter, + struct pipe_resource *dst, + unsigned dst_level, + unsigned dstx, unsigned dsty, + unsigned dstz, + struct pipe_resource *src, + unsigned src_level, + const struct pipe_box *srcbox); + /* The functions below should be used to save currently bound constant state * objects inside a driver. The objects are automatically restored at the end * of the util_blitter_{clear, copy_region, fill_region} functions and then