[Mesa-dev] [PATCH] r600g: add polygon stipple support

Marek Olšák maraeo at gmail.com
Fri Jan 30 16:42:35 PST 2015


Hi Dave,

R600 supports 18 samplers per shader, so you can use a fixed slot
outside of the API range (16 or 17) and bind the stipple texture
statically there. The motivation is that you won't have to read the
shader to get the slot number, so it will be completely independent.
You don't have to unbind it (except for r600_destroy_context) and you
don't even have to store the texture in r600_context, because nothing
else needs it. The texture can be created and bound in
set_polygon_stipple directly, which can moved to r600_state_common.c.

It doesn't look like any code can be shared with radeonsi, but it
looks a lot simpler than I expected.

Marek


On Tue, Jan 27, 2015 at 9:04 AM, Dave Airlie <airlied at gmail.com> wrote:
> From: Dave Airlie <airlied at redhat.com>
>
> This use the gallium poly stipple helper to modify
> the fragment shader and sets up the appropriate state
> around it.
>
> This renders the polys test from mesa demos properly.
> Fixes:
> https://bugs.freedesktop.org/show_bug.cgi?id=25280
>
> TODO:
> should this be in radeon common code? (radeonsi)
>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
>  src/gallium/drivers/r600/evergreen_state.c   |  5 ++++-
>  src/gallium/drivers/r600/r600_pipe.c         |  6 ++++++
>  src/gallium/drivers/r600/r600_pipe.h         |  8 ++++++++
>  src/gallium/drivers/r600/r600_shader.c       | 11 +++++++++++
>  src/gallium/drivers/r600/r600_shader.h       |  2 ++
>  src/gallium/drivers/r600/r600_state_common.c | 27 +++++++++++++++++++++++++++
>  6 files changed, 58 insertions(+), 1 deletion(-)
>
> diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
> index ea58aea..7a0ba7e 100644
> --- a/src/gallium/drivers/r600/evergreen_state.c
> +++ b/src/gallium/drivers/r600/evergreen_state.c
> @@ -482,7 +482,7 @@ static void *evergreen_create_rs_state(struct pipe_context *ctx,
>                 S_028810_DX_LINEAR_ATTR_CLIP_ENA(1) |
>                 S_028810_DX_RASTERIZATION_KILL(state->rasterizer_discard);
>         rs->multisample_enable = state->multisample;
> -
> +       rs->poly_stipple_enable = state->poly_stipple_enable;
>         /* offset */
>         rs->offset_units = state->offset_units;
>         rs->offset_scale = state->offset_scale * 12.0f;
> @@ -864,6 +864,9 @@ static void evergreen_emit_clip_state(struct r600_context *rctx, struct r600_ato
>  static void evergreen_set_polygon_stipple(struct pipe_context *ctx,
>                                          const struct pipe_poly_stipple *state)
>  {
> +       struct r600_context *rctx = (struct r600_context *)ctx;
> +       rctx->poly_stipple = *state;
> +       rctx->pstipple_update = true;
>  }
>
>  static void evergreen_get_scissor_rect(struct r600_context *rctx,
> diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
> index b6f7859..20cfc25 100644
> --- a/src/gallium/drivers/r600/r600_pipe.c
> +++ b/src/gallium/drivers/r600/r600_pipe.c
> @@ -35,6 +35,7 @@
>  #include "util/u_simple_shaders.h"
>  #include "util/u_upload_mgr.h"
>  #include "util/u_math.h"
> +#include "util/u_pstipple.h"
>  #include "vl/vl_decoder.h"
>  #include "vl/vl_video_buffer.h"
>  #include "radeon/radeon_video.h"
> @@ -100,6 +101,10 @@ static void r600_destroy_context(struct pipe_context *context)
>                 u_suballocator_destroy(rctx->allocator_fetch_shader);
>         }
>
> +       if (rctx->pstipple.sampler)
> +               rctx->b.b.delete_sampler_state(&rctx->b.b, rctx->pstipple.sampler);
> +       pipe_resource_reference(&rctx->pstipple.texture, NULL);
> +       pipe_sampler_view_reference(&rctx->pstipple.sampler_view, NULL);
>         r600_release_command_buffer(&rctx->start_cs_cmd);
>
>         FREE(rctx->start_compute_cs_cmd.buf);
> @@ -200,6 +205,7 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
>         util_blitter_set_texture_multisample(rctx->blitter, rscreen->has_msaa);
>         rctx->blitter->draw_rectangle = r600_draw_rectangle;
>
> +       rctx->pstipple.sampler = util_pstipple_create_sampler(&rctx->b.b);
>         r600_begin_new_cs(rctx);
>         r600_query_init_backend_mask(&rctx->b); /* this emits commands and must be last */
>
> diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
> index e110efe..cb910e9 100644
> --- a/src/gallium/drivers/r600/r600_pipe.h
> +++ b/src/gallium/drivers/r600/r600_pipe.h
> @@ -264,6 +264,7 @@ struct r600_rasterizer_state {
>         bool                            offset_enable;
>         bool                            scissor_enable;
>         bool                            multisample_enable;
> +       bool                            poly_stipple_enable;
>  };
>
>  struct r600_poly_offset_state {
> @@ -485,6 +486,13 @@ struct r600_context {
>
>         void                            *sb_context;
>         struct r600_isa         *isa;
> +       struct pipe_poly_stipple poly_stipple;
> +       bool pstipple_update;
> +       struct {
> +               struct pipe_resource *texture;
> +               struct pipe_sampler_state *sampler;
> +               struct pipe_sampler_view *sampler_view;
> +       } pstipple;
>  };
>
>  static INLINE void r600_emit_command_buffer(struct radeon_winsys_cs *cs,
> diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
> index 16e820e..0bbfe52 100644
> --- a/src/gallium/drivers/r600/r600_shader.c
> +++ b/src/gallium/drivers/r600/r600_shader.c
> @@ -36,6 +36,7 @@
>  #include "tgsi/tgsi_dump.h"
>  #include "util/u_memory.h"
>  #include "util/u_math.h"
> +#include "util/u_pstipple.h"
>  #include <stdio.h>
>  #include <errno.h>
>
> @@ -1824,7 +1825,13 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
>
>         r600_bytecode_init(ctx.bc, rscreen->b.chip_class, rscreen->b.family,
>                            rscreen->has_compressed_msaa_texturing);
> +
> +       if (key.polygon_stipple)
> +               tokens = util_pstipple_create_fragment_shader(
> +                       tokens, &ctx.shader->poly_stipple_unit);
> +
>         ctx.tokens = tokens;
> +
>         tgsi_scan_shader(tokens, &ctx.info);
>         shader->indirect_files = ctx.info.indirect_files;
>         indirect_gprs = ctx.info.indirect_files & ~(1 << TGSI_FILE_CONSTANT);
> @@ -2533,10 +2540,14 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
>         }
>
>         free(ctx.literals);
> +       if (key.polygon_stipple)
> +               tgsi_free_tokens(tokens);
>         tgsi_parse_free(&ctx.parse);
>         return 0;
>  out_err:
>         free(ctx.literals);
> +       if (key.polygon_stipple)
> +               tgsi_free_tokens(tokens);
>         tgsi_parse_free(&ctx.parse);
>         return r;
>  }
> diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h
> index b2559e9..7bcc987 100644
> --- a/src/gallium/drivers/r600/r600_shader.h
> +++ b/src/gallium/drivers/r600/r600_shader.h
> @@ -86,6 +86,7 @@ struct r600_shader {
>         unsigned                vs_as_es;
>         unsigned                vs_as_gs_a;
>         unsigned                ps_prim_id_input;
> +       unsigned                poly_stipple_unit;
>         struct r600_shader_array * arrays;
>  };
>
> @@ -96,6 +97,7 @@ struct r600_shader_key {
>         unsigned vs_as_es:1;
>         unsigned vs_as_gs_a:1;
>         unsigned vs_prim_id_out:8;
> +       unsigned polygon_stipple:1;
>  };
>
>  struct r600_shader_array {
> diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
> index b498d00..a737e1b 100644
> --- a/src/gallium/drivers/r600/r600_state_common.c
> +++ b/src/gallium/drivers/r600/r600_state_common.c
> @@ -34,6 +34,7 @@
>  #include "util/u_upload_mgr.h"
>  #include "util/u_math.h"
>  #include "tgsi/tgsi_parse.h"
> +#include "util/u_pstipple.h"
>
>  void r600_init_command_buffer(struct r600_command_buffer *cb, unsigned num_dw)
>  {
> @@ -705,6 +706,7 @@ static INLINE struct r600_shader_key r600_shader_selector_key(struct pipe_contex
>                 /* Dual-source blending only makes sense with nr_cbufs == 1. */
>                 if (key.nr_cbufs == 1 && rctx->dual_src_blend)
>                         key.nr_cbufs = 2;
> +               key.polygon_stipple = rctx->rasterizer && rctx->rasterizer->poly_stipple_enable;
>         } else if (sel->type == PIPE_SHADER_VERTEX) {
>                 key.vs_as_es = (rctx->gs_shader != NULL);
>                 if (rctx->ps_shader->current->shader.gs_prim_id_input && !rctx->gs_shader) {
> @@ -1153,12 +1155,32 @@ static void update_gs_block_state(struct r600_context *rctx, unsigned enable)
>         }
>  }
>
> +static void r600_poly_stipple_update(struct r600_context *rctx)
> +{
> +       struct pipe_resource *tex;
> +       struct pipe_sampler_view *view;
> +
> +       tex = util_pstipple_create_stipple_texture(&rctx->b.b,
> +                               rctx->poly_stipple.stipple);
> +       pipe_resource_reference(&rctx->pstipple.texture, tex);
> +       pipe_resource_reference(&tex, NULL);
> +
> +       view = util_pstipple_create_sampler_view(&rctx->b.b,
> +                               rctx->pstipple.texture);
> +       pipe_sampler_view_reference(&rctx->pstipple.sampler_view,view);
> +       pipe_sampler_view_reference(&view, NULL);
> +}
> +
>  static bool r600_update_derived_state(struct r600_context *rctx)
>  {
>         struct pipe_context * ctx = (struct pipe_context*)rctx;
>         bool ps_dirty = false, vs_dirty = false, gs_dirty = false;
>         bool blend_disable;
>         bool need_buf_const;
> +
> +       if (rctx->pstipple_update && !rctx->blitter->running)
> +               r600_poly_stipple_update(rctx);
> +
>         if (!rctx->blitter->running) {
>                 unsigned i;
>
> @@ -1282,6 +1304,11 @@ static bool r600_update_derived_state(struct r600_context *rctx)
>         /* on R600 we stuff masks + txq info into one constant buffer */
>         /* on evergreen we only need a txq info one */
>         if (rctx->ps_shader) {
> +               if (rctx->ps_shader->current->key.polygon_stipple) {
> +                       rctx->b.b.set_sampler_views(&rctx->b.b, PIPE_SHADER_FRAGMENT, rctx->ps_shader->current->shader.poly_stipple_unit, 1, &rctx->pstipple.sampler_view);
> +                       rctx->b.b.bind_sampler_states(&rctx->b.b, PIPE_SHADER_FRAGMENT, rctx->ps_shader->current->shader.poly_stipple_unit, 1, &rctx->pstipple.sampler);
> +               }
> +
>                 need_buf_const = rctx->ps_shader->current->shader.uses_tex_buffers || rctx->ps_shader->current->shader.has_txq_cube_array_z_comp;
>                 if (need_buf_const) {
>                         if (rctx->b.chip_class < EVERGREEN)
> --
> 1.9.3
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list