[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