From 73ae865af8794c053812cbb5fe9532b1b6113515 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 6 Dec 2012 16:16:10 +1000 Subject: [PATCH] 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 Signed-off-by: Dave Airlie --- src/mesa/state_tracker/st_atom.c | 2 + src/mesa/state_tracker/st_atom.h | 2 + src/mesa/state_tracker/st_atom_constbuf.c | 68 +++++++++++++++++++- src/mesa/state_tracker/st_cb_bufferobjects.c | 3 + src/mesa/state_tracker/st_extensions.c | 16 +++++ src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 63 ++++++++++++++++-- 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); -- 2.30.2