util: add debug_print_bind_flags() debug helper
[mesa.git] / src / gallium / auxiliary / util / u_blitter.c
index 7b058fe2239df070f6e850ff7f5e48df47b9f2e0..9d087fe8a66fc9068b5c93a77e50d097e4635a56 100644 (file)
@@ -130,9 +130,11 @@ struct blitter_context_priv
    unsigned dst_height;
 
    boolean has_geometry_shader;
+   boolean has_layered;
    boolean has_stream_out;
    boolean has_stencil_export;
    boolean has_texture_multisample;
+   boolean cached_all_shaders;
 
    /* The Draw module overrides these functions.
     * Always create the blitter before Draw. */
@@ -288,28 +290,24 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
       }
    }
 
-   /* Fragment shaders are created on-demand, except these.
-    * The interpolation must be constant for integer texture clearing to work.
-    */
-   ctx->fs_empty = util_make_empty_fragment_shader(pipe);
-   ctx->fs_write_one_cbuf =
-      util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC,
-                                            TGSI_INTERPOLATE_CONSTANT, FALSE);
-   ctx->fs_write_all_cbufs =
-      util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC,
-                                            TGSI_INTERPOLATE_CONSTANT, TRUE);
+   ctx->has_layered =
+      pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_INSTANCEID) &&
+      pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_VS_LAYER_VIEWPORT);
 
-   /* vertex shaders */
-   {
-      const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
-                                      TGSI_SEMANTIC_GENERIC };
-      const uint semantic_indices[] = { 0, 0 };
-      ctx->vs =
-         util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
-                                             semantic_indices);
-   }
+   /* set invariant vertex coordinates */
+   for (i = 0; i < 4; i++)
+      ctx->vertices[i][0][3] = 1; /*v.w*/
 
-   if (ctx->has_stream_out) {
+   ctx->upload = u_upload_create(pipe, 65536, 4, PIPE_BIND_VERTEX_BUFFER);
+
+   return &ctx->base;
+}
+
+static void bind_vs_pos_only(struct blitter_context_priv *ctx)
+{
+   struct pipe_context *pipe = ctx->base.pipe;
+
+   if (!ctx->vs_pos_only) {
       struct pipe_stream_output_info so;
       const uint semantic_names[] = { TGSI_SEMANTIC_POSITION };
       const uint semantic_indices[] = { 0 };
@@ -321,21 +319,78 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
 
       ctx->vs_pos_only =
          util_make_vertex_passthrough_shader_with_so(pipe, 1, semantic_names,
-                                                     semantic_indices, &so);
+                                                     semantic_indices, FALSE,
+                                                     &so);
    }
 
-   if (pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_INSTANCEID) &&
-       pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_VS_LAYER)) {
+   pipe->bind_vs_state(pipe, ctx->vs_pos_only);
+}
+
+static void bind_vs_passthrough(struct blitter_context_priv *ctx)
+{
+   struct pipe_context *pipe = ctx->base.pipe;
+
+   if (!ctx->vs) {
+      const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+                                      TGSI_SEMANTIC_GENERIC };
+      const uint semantic_indices[] = { 0, 0 };
+      ctx->vs =
+         util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
+                                             semantic_indices, FALSE);
+   }
+
+   pipe->bind_vs_state(pipe, ctx->vs);
+}
+
+static void bind_vs_layered(struct blitter_context_priv *ctx)
+{
+   struct pipe_context *pipe = ctx->base.pipe;
+
+   if (!ctx->vs_layered) {
       ctx->vs_layered = util_make_layered_clear_vertex_shader(pipe);
    }
 
-   /* set invariant vertex coordinates */
-   for (i = 0; i < 4; i++)
-      ctx->vertices[i][0][3] = 1; /*v.w*/
+   pipe->bind_vs_state(pipe, ctx->vs_layered);
+}
 
-   ctx->upload = u_upload_create(pipe, 65536, 4, PIPE_BIND_VERTEX_BUFFER);
+static void bind_fs_empty(struct blitter_context_priv *ctx)
+{
+   struct pipe_context *pipe = ctx->base.pipe;
 
-   return &ctx->base;
+   if (!ctx->fs_empty) {
+      assert(!ctx->cached_all_shaders);
+      ctx->fs_empty = util_make_empty_fragment_shader(pipe);
+   }
+
+   ctx->bind_fs_state(pipe, ctx->fs_empty);
+}
+
+static void bind_fs_write_one_cbuf(struct blitter_context_priv *ctx)
+{
+   struct pipe_context *pipe = ctx->base.pipe;
+
+   if (!ctx->fs_write_one_cbuf) {
+      assert(!ctx->cached_all_shaders);
+      ctx->fs_write_one_cbuf =
+         util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC,
+                                               TGSI_INTERPOLATE_CONSTANT, FALSE);
+   }
+
+   ctx->bind_fs_state(pipe, ctx->fs_write_one_cbuf);
+}
+
+static void bind_fs_write_all_cbufs(struct blitter_context_priv *ctx)
+{
+   struct pipe_context *pipe = ctx->base.pipe;
+
+   if (!ctx->fs_write_all_cbufs) {
+      assert(!ctx->cached_all_shaders);
+      ctx->fs_write_all_cbufs =
+         util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC,
+                                               TGSI_INTERPOLATE_CONSTANT, TRUE);
+   }
+
+   ctx->bind_fs_state(pipe, ctx->fs_write_all_cbufs);
 }
 
 void util_blitter_destroy(struct blitter_context *blitter)
@@ -361,7 +416,8 @@ void util_blitter_destroy(struct blitter_context *blitter)
    pipe->delete_rasterizer_state(pipe, ctx->rs_state_scissor);
    if (ctx->rs_discard_state)
       pipe->delete_rasterizer_state(pipe, ctx->rs_discard_state);
-   pipe->delete_vs_state(pipe, ctx->vs);
+   if (ctx->vs)
+      pipe->delete_vs_state(pipe, ctx->vs);
    if (ctx->vs_pos_only)
       pipe->delete_vs_state(pipe, ctx->vs_pos_only);
    if (ctx->vs_layered)
@@ -383,6 +439,15 @@ void util_blitter_destroy(struct blitter_context *blitter)
       if (ctx->fs_texfetch_stencil[i])
          ctx->delete_fs_state(pipe, ctx->fs_texfetch_stencil[i]);
 
+      if (ctx->fs_texfetch_col_msaa[i])
+         ctx->delete_fs_state(pipe, ctx->fs_texfetch_col_msaa[i]);
+      if (ctx->fs_texfetch_depth_msaa[i])
+         ctx->delete_fs_state(pipe, ctx->fs_texfetch_depth_msaa[i]);
+      if (ctx->fs_texfetch_depthstencil_msaa[i])
+         ctx->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil_msaa[i]);
+      if (ctx->fs_texfetch_stencil_msaa[i])
+         ctx->delete_fs_state(pipe, ctx->fs_texfetch_stencil_msaa[i]);
+
       for (j = 0; j< Elements(ctx->fs_resolve[i]); j++)
          for (f = 0; f < 2; f++)
             if (ctx->fs_resolve[i][j][f])
@@ -399,9 +464,12 @@ void util_blitter_destroy(struct blitter_context *blitter)
                ctx->delete_fs_state(pipe, ctx->fs_resolve_uint[i][j][f]);
    }
 
-   ctx->delete_fs_state(pipe, ctx->fs_empty);
-   ctx->delete_fs_state(pipe, ctx->fs_write_one_cbuf);
-   ctx->delete_fs_state(pipe, ctx->fs_write_all_cbufs);
+   if (ctx->fs_empty)
+      ctx->delete_fs_state(pipe, ctx->fs_empty);
+   if (ctx->fs_write_one_cbuf)
+      ctx->delete_fs_state(pipe, ctx->fs_write_one_cbuf);
+   if (ctx->fs_write_all_cbufs)
+      ctx->delete_fs_state(pipe, ctx->fs_write_all_cbufs);
 
    pipe->delete_sampler_state(pipe, ctx->sampler_state_rect_linear);
    pipe->delete_sampler_state(pipe, ctx->sampler_state_rect);
@@ -615,11 +683,9 @@ static void blitter_set_rectangle(struct blitter_context_priv *ctx,
    ctx->viewport.scale[0] = 0.5f * ctx->dst_width;
    ctx->viewport.scale[1] = 0.5f * ctx->dst_height;
    ctx->viewport.scale[2] = 1.0f;
-   ctx->viewport.scale[3] = 1.0f;
    ctx->viewport.translate[0] = 0.5f * ctx->dst_width;
    ctx->viewport.translate[1] = 0.5f * ctx->dst_height;
    ctx->viewport.translate[2] = 0.0f;
-   ctx->viewport.translate[3] = 0.0f;
    ctx->base.pipe->set_viewport_states(ctx->base.pipe, 0, 1, &ctx->viewport);
 }
 
@@ -787,6 +853,7 @@ static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
             shader = &ctx->fs_resolve[target][index][filter];
 
          if (!*shader) {
+            assert(!ctx->cached_all_shaders);
             if (filter == PIPE_TEX_FILTER_LINEAR) {
                *shader = util_make_fs_msaa_resolve_bilinear(pipe, tgsi_tex,
                                                    src_nr_samples,
@@ -807,6 +874,7 @@ static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
 
          /* Create the fragment shader on-demand. */
          if (!*shader) {
+            assert(!ctx->cached_all_shaders);
             *shader = util_make_fs_blit_msaa_color(pipe, tgsi_tex);
          }
       }
@@ -817,6 +885,7 @@ static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
+         assert(!ctx->cached_all_shaders);
          *shader = util_make_fragment_tex_shader(pipe, tgsi_tex,
                                                  TGSI_INTERPOLATE_LINEAR);
       }
@@ -839,11 +908,10 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
-         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
-                                                       nr_samples);
-
-         *shader =
-            util_make_fs_blit_msaa_depth(pipe, tgsi_tex);
+         unsigned tgsi_tex;
+         assert(!ctx->cached_all_shaders);
+         tgsi_tex = util_pipe_tex_to_tgsi_tex(target, nr_samples);
+         *shader = util_make_fs_blit_msaa_depth(pipe, tgsi_tex);
       }
 
       return *shader;
@@ -852,8 +920,9 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
-         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
-
+         unsigned tgsi_tex;
+         assert(!ctx->cached_all_shaders);
+         tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
          *shader =
             util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex,
                                                      TGSI_INTERPOLATE_LINEAR);
@@ -877,11 +946,10 @@ void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx,
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
-         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
-                                                       nr_samples);
-
-         *shader =
-            util_make_fs_blit_msaa_depthstencil(pipe, tgsi_tex);
+         unsigned tgsi_tex;
+         assert(!ctx->cached_all_shaders);
+         tgsi_tex = util_pipe_tex_to_tgsi_tex(target, nr_samples);
+         *shader = util_make_fs_blit_msaa_depthstencil(pipe, tgsi_tex);
       }
 
       return *shader;
@@ -890,8 +958,9 @@ void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx,
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
-         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
-
+         unsigned tgsi_tex;
+         assert(!ctx->cached_all_shaders);
+         tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
          *shader =
             util_make_fragment_tex_shader_writedepthstencil(pipe, tgsi_tex,
                                                      TGSI_INTERPOLATE_LINEAR);
@@ -915,11 +984,10 @@ void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
-         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
-                                                       nr_samples);
-
-         *shader =
-            util_make_fs_blit_msaa_stencil(pipe, tgsi_tex);
+         unsigned tgsi_tex;
+         assert(!ctx->cached_all_shaders);
+         tgsi_tex = util_pipe_tex_to_tgsi_tex(target, nr_samples);
+         *shader = util_make_fs_blit_msaa_stencil(pipe, tgsi_tex);
       }
 
       return *shader;
@@ -928,8 +996,9 @@ void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
-         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
-
+         unsigned tgsi_tex;
+         assert(!ctx->cached_all_shaders);
+         tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
          *shader =
             util_make_fragment_tex_shader_writestencil(pipe, tgsi_tex,
                                                        TGSI_INTERPOLATE_LINEAR);
@@ -939,10 +1008,18 @@ void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,
    }
 }
 
+
+/**
+ * Generate and save all fragment shaders that we will ever need for
+ * blitting.  Drivers which use the 'draw' fallbacks will typically use
+ * this to make sure we generate/use shaders that don't go through the
+ * draw module's wrapper functions.
+ */
 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;
+   struct pipe_context *pipe = blitter->pipe;
+   struct pipe_screen *screen = pipe->screen;
    unsigned samples, j, f, target, max_samples;
    boolean has_arraytex, has_cubearraytex;
 
@@ -1002,6 +1079,18 @@ void util_blitter_cache_all_shaders(struct blitter_context *blitter)
          }
       }
    }
+
+   ctx->fs_empty = util_make_empty_fragment_shader(pipe);
+
+   ctx->fs_write_one_cbuf =
+      util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC,
+                                            TGSI_INTERPOLATE_CONSTANT, FALSE);
+
+   ctx->fs_write_all_cbufs =
+      util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC,
+                                            TGSI_INTERPOLATE_CONSTANT, TRUE);
+
+   ctx->cached_all_shaders = TRUE;
 }
 
 static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx,
@@ -1012,7 +1101,11 @@ static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx,
 
    pipe->bind_rasterizer_state(pipe, scissor ? ctx->rs_state_scissor
                                              : ctx->rs_state);
-   pipe->bind_vs_state(pipe, vs_layered ? ctx->vs_layered : ctx->vs);
+   if (vs_layered)
+      bind_vs_layered(ctx);
+   else
+      bind_vs_passthrough(ctx);
+
    if (ctx->has_geometry_shader)
       pipe->bind_gs_state(pipe, NULL);
    if (ctx->has_stream_out)
@@ -1109,7 +1202,7 @@ static void util_blitter_clear_custom(struct blitter_context *blitter,
    struct pipe_context *pipe = ctx->base.pipe;
    struct pipe_stencil_ref sr = { { 0 } };
 
-   assert(ctx->vs_layered || num_layers <= 1);
+   assert(ctx->has_layered || num_layers <= 1);
 
    blitter_set_running_flag(ctx);
    blitter_check_saved_vertex_states(ctx);
@@ -1139,12 +1232,12 @@ static void util_blitter_clear_custom(struct blitter_context *blitter,
    pipe->set_stencil_ref(pipe, &sr);
 
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
-   ctx->bind_fs_state(pipe, ctx->fs_write_all_cbufs);
+   bind_fs_write_all_cbufs(ctx);
    pipe->set_sample_mask(pipe, ~0);
 
    blitter_set_dst_dimensions(ctx, width, height);
 
-   if (num_layers > 1 && ctx->vs_layered) {
+   if (num_layers > 1 && ctx->has_layered) {
       blitter_set_common_draw_rect_state(ctx, FALSE, TRUE);
       blitter_set_clear_color(ctx, color);
       blitter_draw(ctx, 0, 0, width, height, depth, num_layers);
@@ -1671,7 +1764,7 @@ void util_blitter_clear_render_target(struct blitter_context *blitter,
    /* bind states */
    pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA]);
    pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
-   ctx->bind_fs_state(pipe, ctx->fs_write_one_cbuf);
+   bind_fs_write_one_cbuf(ctx);
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
 
    /* set a framebuffer state */
@@ -1739,7 +1832,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);
 
-   ctx->bind_fs_state(pipe, ctx->fs_empty);
+   bind_fs_empty(ctx);
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
 
    /* set a framebuffer state */
@@ -1790,7 +1883,10 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
    pipe->bind_blend_state(pipe, cbsurf ? ctx->blend[PIPE_MASK_RGBA] :
                                          ctx->blend[0]);
    pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage);
-   ctx->bind_fs_state(pipe, ctx->fs_empty);
+   if (cbsurf)
+      bind_fs_write_one_cbuf(ctx);
+   else
+      bind_fs_empty(ctx);
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
 
    /* set a framebuffer state */
@@ -1867,7 +1963,7 @@ void util_blitter_copy_buffer(struct blitter_context *blitter,
 
    pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, &vb);
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf[0]);
-   pipe->bind_vs_state(pipe, ctx->vs_pos_only);
+   bind_vs_pos_only(ctx);
    if (ctx->has_geometry_shader)
       pipe->bind_gs_state(pipe, NULL);
    pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state);
@@ -1927,7 +2023,7 @@ void util_blitter_clear_buffer(struct blitter_context *blitter,
    pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, &vb);
    pipe->bind_vertex_elements_state(pipe,
                                     ctx->velem_state_readbuf[num_channels-1]);
-   pipe->bind_vs_state(pipe, ctx->vs_pos_only);
+   bind_vs_pos_only(ctx);
    if (ctx->has_geometry_shader)
       pipe->bind_gs_state(pipe, NULL);
    pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state);
@@ -1969,7 +2065,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);
-   ctx->bind_fs_state(pipe, ctx->fs_write_one_cbuf);
+   bind_fs_write_one_cbuf(ctx);
    pipe->set_sample_mask(pipe, sample_mask);
 
    memset(&surf_tmpl, 0, sizeof(surf_tmpl));
@@ -2032,7 +2128,7 @@ void util_blitter_custom_color(struct blitter_context *blitter,
    pipe->bind_blend_state(pipe, custom_blend ? custom_blend
                                              : ctx->blend[PIPE_MASK_RGBA]);
    pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
-   ctx->bind_fs_state(pipe, ctx->fs_write_one_cbuf);
+   bind_fs_write_one_cbuf(ctx);
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
    pipe->set_sample_mask(pipe, (1ull << MAX2(1, dstsurf->texture->nr_samples)) - 1);