summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <[email protected]>2012-12-06 16:16:10 +1000
committerDave Airlie <[email protected]>2012-12-08 13:32:38 +1000
commit73ae865af8794c053812cbb5fe9532b1b6113515 (patch)
tree5a0f70c6af0628bb97b02f5779b11740c9d8b1a2
parent535e248c5fc88fb3fa56d0ce9204e6a6427802f6 (diff)
mesa/st: add ARB_uniform_buffer_object support (v2)
this adds UBO support to the state tracker, it works with softpipe as-is. It uses UARL + CONST[x][ADDR[0].x] type constructs. v2: don't disable UBOs if geom shaders don't exist (me) rename upload to bind (calim) fix 12 -> 13 comparison as comment (calim + brianp) fix signed->unsigned (Brian) remove assert (Brian) Reviewed-by: Brian Paul <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
-rw-r--r--src/mesa/state_tracker/st_atom.c2
-rw-r--r--src/mesa/state_tracker/st_atom.h2
-rw-r--r--src/mesa/state_tracker/st_atom_constbuf.c68
-rw-r--r--src/mesa/state_tracker/st_cb_bufferobjects.c3
-rw-r--r--src/mesa/state_tracker/st_extensions.c16
-rw-r--r--src/mesa/state_tracker/st_glsl_to_tgsi.cpp63
6 files changed, 147 insertions, 7 deletions
diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c
index 102fee93b36..32bcc266a34 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_bind_vs_ubos,
+ &st_bind_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 6c7d09fbae3..101a3a6bd9d 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_bind_fs_ubos;
+extern const struct st_tracked_state st_bind_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 580393e60bf..961fb28a967 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,69 @@ const struct st_tracked_state st_update_gs_constants = {
},
update_gs_constants /* update */
};
+
+static void st_bind_ubos(struct st_context *st,
+ struct gl_shader *shader,
+ unsigned shader_type)
+{
+ unsigned i;
+ struct pipe_constant_buffer cb = { 0 };
+
+ 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 bind_vs_ubos(struct st_context *st)
+{
+ struct gl_shader_program *prog = st->ctx->Shader.CurrentVertexProgram;
+
+ if (!prog)
+ return;
+
+ st_bind_ubos(st, prog->_LinkedShaders[MESA_SHADER_VERTEX], PIPE_SHADER_VERTEX);
+}
+
+const struct st_tracked_state st_bind_vs_ubos = {
+ "st_bind_vs_ubos",
+ {
+ (_NEW_PROGRAM | _NEW_BUFFER_OBJECT),
+ ST_NEW_VERTEX_PROGRAM,
+ },
+ bind_vs_ubos
+};
+
+static void bind_fs_ubos(struct st_context *st)
+{
+ struct gl_shader_program *prog = st->ctx->Shader.CurrentFragmentProgram;
+
+ if (!prog)
+ return;
+
+ st_bind_ubos(st, prog->_LinkedShaders[MESA_SHADER_FRAGMENT], PIPE_SHADER_FRAGMENT);
+
+}
+
+const struct st_tracked_state st_bind_fs_ubos = {
+ "st_bind_fs_ubos",
+ {
+ (_NEW_PROGRAM | _NEW_BUFFER_OBJECT),
+ ST_NEW_FRAGMENT_PROGRAM,
+ },
+ bind_fs_ubos
+};
+
+
diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.c b/src/mesa/state_tracker/st_cb_bufferobjects.c
index ac38128dfd9..7d1c05a33f7 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 ca762cab4b2..93ef7a91cf7 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,17 @@ void st_init_limits(struct st_context *st)
options->EmitNoIndirectUniform = !screen->get_shader_param(screen, sh,
PIPE_SHADER_CAP_INDIRECT_CONST_ADDR);
+ if (pc->MaxNativeInstructions) {
+ if (options->EmitNoIndirectUniform)
+ can_ubo = FALSE;
+
+ max_const_buffers = screen->get_shader_param(screen, sh,
+ PIPE_SHADER_CAP_MAX_CONST_BUFFERS);
+ /* we need 13 buffers - 1 constant, 12 UBO */
+ if (max_const_buffers < 13)
+ can_ubo = FALSE;
+ }
+
if (options->EmitNoLoops)
options->MaxUnrollIterations = MIN2(screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_INSTRUCTIONS), 65536);
else
@@ -251,6 +264,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 ae3b8b2c0d1..e8a174c5a0d 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);