[Mesa-dev] [PATCH 6/6] mesa/st: add ARB_uniform_buffer_object support

Jose Fonseca jfonseca at vmware.com
Thu Dec 6 05:41:36 PST 2012


Series looks good AFAICT.

Jose

----- Original Message -----
> From: Dave Airlie <airlied at redhat.com>
> 
> this adds UBO support to the state tracker, it works with softpipe
> as-is.
> 
> It uses UARL + CONST[x][ADDR[0].x] type constructs.
> 
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
>  src/mesa/state_tracker/st_atom.c             |  2 +
>  src/mesa/state_tracker/st_atom.h             |  2 +
>  src/mesa/state_tracker/st_atom_constbuf.c    | 70
>  +++++++++++++++++++++++++++-
>  src/mesa/state_tracker/st_cb_bufferobjects.c |  3 ++
>  src/mesa/state_tracker/st_extensions.c       | 13 ++++++
>  src/mesa/state_tracker/st_glsl_to_tgsi.cpp   | 63
>  ++++++++++++++++++++++---
>  6 files changed, 146 insertions(+), 7 deletions(-)
> 
> diff --git a/src/mesa/state_tracker/st_atom.c
> b/src/mesa/state_tracker/st_atom.c
> index 102fee9..091bd55 100644
> --- a/src/mesa/state_tracker/st_atom.c
> +++ b/src/mesa/state_tracker/st_atom.c
> @@ -64,6 +64,8 @@ static const struct st_tracked_state *atoms[] =
>     &st_update_vs_constants,
>     &st_update_gs_constants,
>     &st_update_fs_constants,
> +   &st_upload_vs_ubos,
> +   &st_upload_fs_ubos,
>     &st_update_pixel_transfer,
>  
>     /* this must be done after the vertex program update */
> diff --git a/src/mesa/state_tracker/st_atom.h
> b/src/mesa/state_tracker/st_atom.h
> index 6c7d09f..ca79b44 100644
> --- a/src/mesa/state_tracker/st_atom.h
> +++ b/src/mesa/state_tracker/st_atom.h
> @@ -67,6 +67,8 @@ extern const struct st_tracked_state
> st_finalize_textures;
>  extern const struct st_tracked_state st_update_fs_constants;
>  extern const struct st_tracked_state st_update_gs_constants;
>  extern const struct st_tracked_state st_update_vs_constants;
> +extern const struct st_tracked_state st_upload_fs_ubos;
> +extern const struct st_tracked_state st_upload_vs_ubos;
>  extern const struct st_tracked_state st_update_pixel_transfer;
>  
>  
> diff --git a/src/mesa/state_tracker/st_atom_constbuf.c
> b/src/mesa/state_tracker/st_atom_constbuf.c
> index 580393e..ea0cf0e 100644
> --- a/src/mesa/state_tracker/st_atom_constbuf.c
> +++ b/src/mesa/state_tracker/st_atom_constbuf.c
> @@ -45,7 +45,7 @@
>  #include "st_atom.h"
>  #include "st_atom_constbuf.h"
>  #include "st_program.h"
> -
> +#include "st_cb_bufferobjects.h"
>  
>  /**
>   * Pass the given program parameters to the graphics pipe as a
> @@ -175,3 +175,71 @@ const struct st_tracked_state
> st_update_gs_constants = {
>     },
>     update_gs_constants					/* update */
>  };
> +
> +static void st_upload_ubos(struct st_context *st,
> +                           struct gl_shader *shader,
> +                           unsigned shader_type)
> +{
> +   int i;
> +   struct pipe_constant_buffer cb = { 0 };
> +   assert(shader_type == PIPE_SHADER_VERTEX ||
> +          shader_type == PIPE_SHADER_FRAGMENT);
> +
> +   if (!shader)
> +      return;
> +
> +   for (i = 0; i < shader->NumUniformBlocks; i++) {
> +      struct gl_uniform_buffer_binding *binding;
> +      struct st_buffer_object *st_obj;
> +
> +      binding =
> &st->ctx->UniformBufferBindings[shader->UniformBlocks[i].Binding];
> +      st_obj = st_buffer_object(binding->BufferObject);
> +      pipe_resource_reference(&cb.buffer, st_obj->buffer);
> +
> +      cb.buffer_size = st_obj->buffer->width0 - binding->Offset;
> +
> +      st->pipe->set_constant_buffer(st->pipe, shader_type, 1 + i,
> &cb);
> +      pipe_resource_reference(&cb.buffer, NULL);
> +   }
> +}
> +
> +static void upload_vs_ubos(struct st_context *st)
> +{
> +   struct gl_shader_program *prog =
> st->ctx->Shader.CurrentVertexProgram;
> +
> +   if (!prog)
> +      return;
> +
> +   st_upload_ubos(st, prog->_LinkedShaders[MESA_SHADER_VERTEX],
> PIPE_SHADER_VERTEX);
> +}
> +
> +const struct st_tracked_state st_upload_vs_ubos = {
> +   "st_upload_vs_ubos",
> +   {
> +      (_NEW_PROGRAM | _NEW_BUFFER_OBJECT),
> +      ST_NEW_VERTEX_PROGRAM,
> +   },
> +   upload_vs_ubos
> +};
> +
> +static void upload_fs_ubos(struct st_context *st)
> +{
> +   struct gl_shader_program *prog =
> st->ctx->Shader.CurrentFragmentProgram;
> +
> +   if (!prog)
> +      return;
> +
> +   st_upload_ubos(st, prog->_LinkedShaders[MESA_SHADER_FRAGMENT],
> PIPE_SHADER_FRAGMENT);
> +
> +}
> +
> +const struct st_tracked_state st_upload_fs_ubos = {
> +   "st_upload_fs_ubos",
> +   {
> +      (_NEW_PROGRAM | _NEW_BUFFER_OBJECT),
> +      ST_NEW_FRAGMENT_PROGRAM,
> +   },
> +   upload_fs_ubos
> +};
> +
> +
> diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.c
> b/src/mesa/state_tracker/st_cb_bufferobjects.c
> index ac38128..7d1c05a 100644
> --- a/src/mesa/state_tracker/st_cb_bufferobjects.c
> +++ b/src/mesa/state_tracker/st_cb_bufferobjects.c
> @@ -198,6 +198,9 @@ st_bufferobj_data(struct gl_context *ctx,
>     case GL_TRANSFORM_FEEDBACK_BUFFER:
>        bind = PIPE_BIND_STREAM_OUTPUT;
>        break;
> +   case GL_UNIFORM_BUFFER:
> +      bind = PIPE_BIND_CONSTANT_BUFFER;
> +      break;
>     default:
>        bind = 0;
>     }
> diff --git a/src/mesa/state_tracker/st_extensions.c
> b/src/mesa/state_tracker/st_extensions.c
> index ccb1f36..d76cfdb 100644
> --- a/src/mesa/state_tracker/st_extensions.c
> +++ b/src/mesa/state_tracker/st_extensions.c
> @@ -70,6 +70,8 @@ void st_init_limits(struct st_context *st)
>     struct pipe_screen *screen = st->pipe->screen;
>     struct gl_constants *c = &st->ctx->Const;
>     gl_shader_type sh;
> +   boolean can_ubo = TRUE;
> +   int max_const_buffers;
>  
>     c->MaxTextureLevels
>        = _min(screen->get_param(screen,
>        PIPE_CAP_MAX_TEXTURE_2D_LEVELS),
> @@ -218,6 +220,14 @@ void st_init_limits(struct st_context *st)
>        options->EmitNoIndirectUniform =
>        !screen->get_shader_param(screen, sh,
>                                          PIPE_SHADER_CAP_INDIRECT_CONST_ADDR);
>  
> +      if (options->EmitNoIndirectUniform)
> +         can_ubo = FALSE;
> +
> +      max_const_buffers = screen->get_shader_param(screen, sh,
> +
>                                                   PIPE_SHADER_CAP_MAX_CONST_BUFFERS);
> +      if (max_const_buffers < 12)
> +         can_ubo = FALSE;
> +
>        if (options->EmitNoLoops)
>           options->MaxUnrollIterations =
>           MIN2(screen->get_shader_param(screen, sh,
>           PIPE_SHADER_CAP_MAX_INSTRUCTIONS), 65536);
>        else
> @@ -251,6 +261,9 @@ void st_init_limits(struct st_context *st)
>  
>     c->GLSLSkipStrictMaxVaryingLimitCheck =
>        screen->get_param(screen, PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS);
> +
> +   if (can_ubo)
> +      st->ctx->Extensions.ARB_uniform_buffer_object = GL_TRUE;
>  }
>  
>  
> diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> index ae3b8b2..e8a174c 100644
> --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> @@ -107,6 +107,7 @@ public:
>        else
>           this->swizzle = SWIZZLE_XYZW;
>        this->negate = 0;
> +      this->index2D = 0;
>        this->type = type ? type->base_type : GLSL_TYPE_ERROR;
>        this->reladdr = NULL;
>     }
> @@ -116,6 +117,18 @@ public:
>        this->type = type;
>        this->file = file;
>        this->index = index;
> +      this->index2D = 0;
> +      this->swizzle = SWIZZLE_XYZW;
> +      this->negate = 0;
> +      this->reladdr = NULL;
> +   }
> +
> +   st_src_reg(gl_register_file file, int index, int type, int
> index2D)
> +   {
> +      this->type = type;
> +      this->file = file;
> +      this->index = index;
> +      this->index2D = index2D;
>        this->swizzle = SWIZZLE_XYZW;
>        this->negate = 0;
>        this->reladdr = NULL;
> @@ -126,6 +139,7 @@ public:
>        this->type = GLSL_TYPE_ERROR;
>        this->file = PROGRAM_UNDEFINED;
>        this->index = 0;
> +      this->index2D = 0;
>        this->swizzle = 0;
>        this->negate = 0;
>        this->reladdr = NULL;
> @@ -135,6 +149,7 @@ public:
>  
>     gl_register_file file; /**< PROGRAM_* from Mesa */
>     int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*,
>     etc. */
> +   int index2D;
>     GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */
>     int negate; /**< NEGATE_XYZW mask from mesa */
>     int type; /** GLSL_TYPE_* from GLSL IR (enum glsl_base_type) */
> @@ -183,6 +198,7 @@ st_src_reg::st_src_reg(st_dst_reg reg)
>     this->swizzle = SWIZZLE_XYZW;
>     this->negate = 0;
>     this->reladdr = reg.reladdr;
> +   this->index2D = 0;
>  }
>  
>  st_dst_reg::st_dst_reg(st_src_reg reg)
> @@ -1873,10 +1889,29 @@ glsl_to_tgsi_visitor::visit(ir_expression
> *ir)
>        assert(!"GLSL 1.30 features unsupported");
>        break;
>  
> -   case ir_binop_ubo_load:
> -      assert(!"not yet supported");
> -      break;
> +   case ir_binop_ubo_load: {
> +      ir_constant *uniform_block = ir->operands[0]->as_constant();
> +      st_src_reg index_reg = get_temp(glsl_type::uint_type);
> +      st_src_reg cbuf;
> +
> +      cbuf.type = glsl_type::vec4_type->base_type;
> +      cbuf.file = PROGRAM_CONSTANT;
> +      cbuf.index = 0;
> +      cbuf.index2D = uniform_block->value.u[0] + 1;
> +      cbuf.reladdr = NULL;
> +      cbuf.negate = 0;
> +
> +      assert(ir->type->is_vector() || ir->type->is_scalar());
>  
> +      emit(ir, TGSI_OPCODE_USHR, st_dst_reg(index_reg), op[1],
> st_src_reg_for_int(4));
> +
> +      cbuf.swizzle = swizzle_for_size(ir->type->vector_elements);
> +      cbuf.reladdr = ralloc(mem_ctx, st_src_reg);
> +      memcpy(cbuf.reladdr, &index_reg, sizeof(index_reg));
> +
> +      emit(ir, TGSI_OPCODE_MOV, result_dst, cbuf);
> +      break;
> +   }
>     case ir_quadop_vector:
>        /* This operation should have already been handled.
>         */
> @@ -4061,7 +4096,7 @@ dst_register(struct st_translate *t,
>  static struct ureg_src
>  src_register(struct st_translate *t,
>               gl_register_file file,
> -             GLint index)
> +             GLint index, GLint index2D)
>  {
>     switch(file) {
>     case PROGRAM_UNDEFINED:
> @@ -4081,7 +4116,13 @@ src_register(struct st_translate *t,
>        return t->constants[index];
>     case PROGRAM_STATE_VAR:
>     case PROGRAM_CONSTANT:       /* ie, immediate */
> -      if (index < 0)
> +      if (index2D) {
> +         struct ureg_src src;
> +         src = ureg_src_register(TGSI_FILE_CONSTANT, 0);
> +         src.Dimension = 1;
> +         src.DimensionIndex = index2D;
> +         return src;
> +      } else if (index < 0)
>           return ureg_DECL_constant(t->ureg, 0);
>        else
>           return t->constants[index];
> @@ -4160,7 +4201,7 @@ translate_dst(struct st_translate *t,
>  static struct ureg_src
>  translate_src(struct st_translate *t, const st_src_reg *src_reg)
>  {
> -   struct ureg_src src = src_register(t, src_reg->file,
> src_reg->index);
> +   struct ureg_src src = src_register(t, src_reg->file,
> src_reg->index, src_reg->index2D);
>  
>     src = ureg_swizzle(src,
>                        GET_SWZ(src_reg->swizzle, 0) & 0x3,
> @@ -4754,6 +4795,14 @@ st_translate_program(
>           }
>        }
>     }
> +
> +   if (program->shader_program) {
> +      unsigned num_ubos = program->shader_program->NumUniformBlocks;
> +
> +      for (i = 0; i < num_ubos; i++) {
> +         ureg_DECL_constant2D(t->ureg, 0,
> program->shader_program->UniformBlocks[i].UniformBufferSize / 4, i +
> 1);
> +      }
> +   }
>     
>     /* Emit immediate values.
>      */
> @@ -5090,6 +5139,8 @@ st_link_shader(struct gl_context *ctx, struct
> gl_shader_program *prog)
>               || progress;
>  
>           progress = do_vec_index_to_cond_assign(ir) || progress;
> +
> +         lower_ubo_reference(prog->_LinkedShaders[i], ir);
>        } while (progress);
>  
>        validate_ir_tree(ir);
> --
> 1.8.0.1
> 
> _______________________________________________
> 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