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

Marek Olšák maraeo at gmail.com
Sun Dec 16 05:40:50 PST 2012


ctx->Const.UniformBufferOffsetAlignment should be set to
PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT. I added the cap exactly for
that purpose.

The default value for UniformBufferOffsetAlignment is 1, but R600
requires the alignment to be 256 bytes.

The other 3 UBO limits in Const could also be set to match what
gallium drivers advertise, but the defaults should work for now.

Sorry for the late reply.

Marek

On Thu, Dec 6, 2012 at 7:24 AM, Dave Airlie <airlied at gmail.com> wrote:
> 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