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:
parent
2970d388a2
commit
e8a40715a8
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue