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 <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6681>
This commit is contained in:
Erik Faye-Lund 2020-09-09 15:07:54 +02:00 committed by Marge Bot
parent 2970d388a2
commit e8a40715a8
2 changed files with 147 additions and 0 deletions

View File

@ -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);
}

View File

@ -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