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

Dave Airlie airlied at gmail.com
Wed Dec 5 22:24:34 PST 2012


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



More information about the mesa-dev mailing list