Commit 73ae865a authored by Dave Airlie's avatar Dave Airlie

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's avatarBrian Paul <brianp@vmware.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 535e248c
......@@ -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 */
......
......@@ -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;
......
......@@ -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
};
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment