On 12/05/2012 11:24 PM, Dave Airlie wrote:
From: Dave Airlie<airl...@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<airl...@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);

Is that assertion is really needed? Will this function need changes for GS?


+
+   if (!shader)
+      return;
+
+   for (i = 0; i<  shader->NumUniformBlocks; i++) {

'i' should be declared unsigned above to match the type of NumUniformBlocks, otherwise we'll get a signed/unsigned comparison warning with MSVC.


+      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);

Maybe add a comment describing where 12 comes from?


+      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);

Otherwise the series looks great.  Thanks!

Reviewed-by: Brian Paul <bri...@vmware.com>
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to