diff options
-rw-r--r-- | src/gallium/auxiliary/util/u_blitter.c | 168 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/u_blitter.h | 2 |
2 files changed, 111 insertions, 59 deletions
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index b94366b998d..3f0d1b17d01 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -122,8 +122,12 @@ struct blitter_context_priv boolean has_stream_out; boolean has_stencil_export; boolean has_texture_multisample; -}; + /* The Draw module overrides these functions. + * Always create the blitter before Draw. */ + void (*bind_fs_state)(struct pipe_context *, void *); + void (*delete_fs_state)(struct pipe_context *, void *); +}; struct blitter_context *util_blitter_create(struct pipe_context *pipe) { @@ -142,6 +146,9 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) ctx->base.pipe = pipe; ctx->base.draw_rectangle = util_blitter_draw_rectangle; + ctx->bind_fs_state = pipe->bind_fs_state; + ctx->delete_fs_state = pipe->delete_fs_state; + /* init state objects for them to be considered invalid */ ctx->base.saved_blend_state = INVALID_PTR; ctx->base.saved_dsa_state = INVALID_PTR; @@ -321,20 +328,20 @@ void util_blitter_destroy(struct blitter_context *blitter) for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) { if (ctx->fs_texfetch_col[i]) - pipe->delete_fs_state(pipe, ctx->fs_texfetch_col[i]); + ctx->delete_fs_state(pipe, ctx->fs_texfetch_col[i]); if (ctx->fs_texfetch_depth[i]) - pipe->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]); + ctx->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]); if (ctx->fs_texfetch_depthstencil[i]) - pipe->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil[i]); + ctx->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil[i]); if (ctx->fs_texfetch_stencil[i]) - pipe->delete_fs_state(pipe, ctx->fs_texfetch_stencil[i]); + ctx->delete_fs_state(pipe, ctx->fs_texfetch_stencil[i]); } for (i = 0; i <= PIPE_MAX_COLOR_BUFS; i++) { if (ctx->fs_col[i]) - pipe->delete_fs_state(pipe, ctx->fs_col[i]); + ctx->delete_fs_state(pipe, ctx->fs_col[i]); if (ctx->fs_col_int[i]) - pipe->delete_fs_state(pipe, ctx->fs_col_int[i]); + ctx->delete_fs_state(pipe, ctx->fs_col_int[i]); } pipe->delete_sampler_state(pipe, ctx->sampler_state); @@ -431,7 +438,7 @@ static void blitter_restore_fragment_states(struct blitter_context_priv *ctx) struct pipe_context *pipe = ctx->base.pipe; /* Fragment shader. */ - pipe->bind_fs_state(pipe, ctx->base.saved_fs); + ctx->bind_fs_state(pipe, ctx->base.saved_fs); ctx->base.saved_fs = INVALID_PTR; /* Depth, stencil, alpha. */ @@ -657,9 +664,8 @@ static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx, ctx->dst_height = height; } -static INLINE -void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs, - boolean int_format) +static void *blitter_get_fs_col(struct blitter_context_priv *ctx, + unsigned num_cbufs, boolean int_format) { struct pipe_context *pipe = ctx->base.pipe; @@ -682,32 +688,32 @@ void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs, } } -static INLINE -void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx, - struct pipe_resource *tex) +static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx, + enum pipe_texture_target target, + unsigned nr_samples) { struct pipe_context *pipe = ctx->base.pipe; - assert(tex->target < PIPE_MAX_TEXTURE_TYPES); + assert(target < PIPE_MAX_TEXTURE_TYPES); - if (tex->nr_samples > 1) { - void **shader = &ctx->fs_texfetch_col_msaa[tex->target]; + if (nr_samples > 1) { + void **shader = &ctx->fs_texfetch_col_msaa[target]; /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, - tex->nr_samples); + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, + nr_samples); *shader = util_make_fs_blit_msaa_color(pipe, tgsi_tex); } return *shader; } else { - void **shader = &ctx->fs_texfetch_col[tex->target]; + void **shader = &ctx->fs_texfetch_col[target]; /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, 0); + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0); *shader = util_make_fragment_tex_shader(pipe, tgsi_tex, @@ -720,19 +726,20 @@ void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx, static INLINE void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx, - struct pipe_resource *tex) + enum pipe_texture_target target, + unsigned nr_samples) { struct pipe_context *pipe = ctx->base.pipe; - assert(tex->target < PIPE_MAX_TEXTURE_TYPES); + assert(target < PIPE_MAX_TEXTURE_TYPES); - if (tex->nr_samples > 1) { - void **shader = &ctx->fs_texfetch_depth_msaa[tex->target]; + if (nr_samples > 1) { + void **shader = &ctx->fs_texfetch_depth_msaa[target]; /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, - tex->nr_samples); + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, + nr_samples); *shader = util_make_fs_blit_msaa_depth(pipe, tgsi_tex); @@ -740,11 +747,11 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx, return *shader; } else { - void **shader = &ctx->fs_texfetch_depth[tex->target]; + void **shader = &ctx->fs_texfetch_depth[target]; /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, 0); + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0); *shader = util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex, @@ -757,19 +764,20 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx, static INLINE void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx, - struct pipe_resource *tex) + enum pipe_texture_target target, + unsigned nr_samples) { struct pipe_context *pipe = ctx->base.pipe; - assert(tex->target < PIPE_MAX_TEXTURE_TYPES); + assert(target < PIPE_MAX_TEXTURE_TYPES); - if (tex->nr_samples > 1) { - void **shader = &ctx->fs_texfetch_depthstencil_msaa[tex->target]; + if (nr_samples > 1) { + void **shader = &ctx->fs_texfetch_depthstencil_msaa[target]; /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, - tex->nr_samples); + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, + nr_samples); *shader = util_make_fs_blit_msaa_depthstencil(pipe, tgsi_tex); @@ -777,11 +785,11 @@ void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx, return *shader; } else { - void **shader = &ctx->fs_texfetch_depthstencil[tex->target]; + void **shader = &ctx->fs_texfetch_depthstencil[target]; /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, 0); + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0); *shader = util_make_fragment_tex_shader_writedepthstencil(pipe, tgsi_tex, @@ -794,19 +802,20 @@ void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx, static INLINE void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx, - struct pipe_resource *tex) + enum pipe_texture_target target, + unsigned nr_samples) { struct pipe_context *pipe = ctx->base.pipe; - assert(tex->target < PIPE_MAX_TEXTURE_TYPES); + assert(target < PIPE_MAX_TEXTURE_TYPES); - if (tex->nr_samples > 1) { - void **shader = &ctx->fs_texfetch_stencil_msaa[tex->target]; + if (nr_samples > 1) { + void **shader = &ctx->fs_texfetch_stencil_msaa[target]; /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, - tex->nr_samples); + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, + nr_samples); *shader = util_make_fs_blit_msaa_stencil(pipe, tgsi_tex); @@ -814,11 +823,11 @@ void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx, return *shader; } else { - void **shader = &ctx->fs_texfetch_stencil[tex->target]; + void **shader = &ctx->fs_texfetch_stencil[target]; /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, 0); + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0); *shader = util_make_fragment_tex_shader_writestencil(pipe, tgsi_tex, @@ -829,6 +838,43 @@ void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx, } } +void util_blitter_cache_all_shaders(struct blitter_context *blitter) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + struct pipe_screen *screen = blitter->pipe->screen; + unsigned num_cbufs, i, target, max_samples; + boolean has_arraytex; + + num_cbufs = MAX2(screen->get_param(screen, + PIPE_CAP_MAX_RENDER_TARGETS), 1); + max_samples = ctx->has_texture_multisample ? 2 : 1; + has_arraytex = screen->get_param(screen, + PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS) != 0; + + for (i = 0; i < num_cbufs; i++) { + blitter_get_fs_col(ctx, i, FALSE); + blitter_get_fs_col(ctx, i, TRUE); + } + + /* It only matters if i <= 1 or > 1. */ + for (i = 1; i <= max_samples; i++) { + for (target = PIPE_TEXTURE_1D; target < PIPE_MAX_TEXTURE_TYPES; target++) { + if (!has_arraytex && + (target == PIPE_TEXTURE_1D_ARRAY || + target == PIPE_TEXTURE_2D_ARRAY)) { + continue; + } + + blitter_get_fs_texfetch_col(ctx, target, i); + blitter_get_fs_texfetch_depth(ctx, target, i); + if (ctx->has_stencil_export) { + blitter_get_fs_texfetch_depthstencil(ctx, target, i); + blitter_get_fs_texfetch_stencil(ctx, target, i); + } + } + } +} + static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx) { struct pipe_context *pipe = ctx->base.pipe; @@ -933,7 +979,7 @@ static void util_blitter_clear_custom(struct blitter_context *blitter, } else { pipe->bind_vertex_elements_state(pipe, ctx->velem_state); } - pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs, int_format)); + ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs, int_format)); pipe->set_sample_mask(pipe, ~0); blitter_set_common_draw_rect_state(ctx); @@ -1177,18 +1223,21 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter, if (blit_depth && blit_stencil) { pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); - pipe->bind_fs_state(pipe, - blitter_get_fs_texfetch_depthstencil(ctx, src->texture)); + ctx->bind_fs_state(pipe, + blitter_get_fs_texfetch_depthstencil(ctx, src->texture->target, + src->texture->nr_samples)); } else if (blit_depth) { pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); - pipe->bind_fs_state(pipe, - blitter_get_fs_texfetch_depth(ctx, src->texture)); + ctx->bind_fs_state(pipe, + blitter_get_fs_texfetch_depth(ctx, src->texture->target, + src->texture->nr_samples)); } else { /* is_stencil */ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); - pipe->bind_fs_state(pipe, - blitter_get_fs_texfetch_stencil(ctx, src->texture)); + ctx->bind_fs_state(pipe, + blitter_get_fs_texfetch_stencil(ctx, src->texture->target, + src->texture->nr_samples)); } fb_state.nr_cbufs = 0; @@ -1196,8 +1245,9 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter, } else { pipe->bind_blend_state(pipe, ctx->blend_write_color); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); - pipe->bind_fs_state(pipe, - blitter_get_fs_texfetch_col(ctx, src->texture)); + ctx->bind_fs_state(pipe, + blitter_get_fs_texfetch_col(ctx, src->texture->target, + src->texture->nr_samples)); fb_state.nr_cbufs = 1; fb_state.cbufs[0] = dst; @@ -1306,7 +1356,7 @@ void util_blitter_clear_render_target(struct blitter_context *blitter, /* bind states */ pipe->bind_blend_state(pipe, ctx->blend_write_color); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); - pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE)); + ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE)); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); /* set a framebuffer state */ @@ -1372,7 +1422,7 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter, /* hmm that should be illegal probably, or make it a no-op somewhere */ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); - pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE)); + ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE)); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); /* set a framebuffer state */ @@ -1419,7 +1469,7 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter, /* bind states */ pipe->bind_blend_state(pipe, ctx->blend_write_color); pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage); - pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE)); + ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE)); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); /* set a framebuffer state */ @@ -1531,7 +1581,7 @@ void util_blitter_custom_resolve_color(struct blitter_context *blitter, pipe->bind_blend_state(pipe, custom_blend); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); - pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE)); + ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE)); pipe->set_sample_mask(pipe, sample_mask); memset(&surf_tmpl, 0, sizeof(surf_tmpl)); @@ -1592,7 +1642,7 @@ void util_blitter_custom_color(struct blitter_context *blitter, /* bind states */ pipe->bind_blend_state(pipe, custom_blend); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); - pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE)); + ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE)); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); pipe->set_sample_mask(pipe, (1ull << MAX2(1, dstsurf->texture->nr_samples)) - 1); diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h index 680407381a6..d458f692702 100644 --- a/src/gallium/auxiliary/util/u_blitter.h +++ b/src/gallium/auxiliary/util/u_blitter.h @@ -120,6 +120,8 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe); */ void util_blitter_destroy(struct blitter_context *blitter); +void util_blitter_cache_all_shaders(struct blitter_context *blitter); + /** * Return the pipe context associated with a blitter context. */ |