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 <brianp@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
@@ -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,
|
||||
@@ -4755,6 +4796,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.
|
||||
*/
|
||||
t->immediates = (struct ureg_src *)
|
||||
@@ -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);
|
||||
|
Reference in New Issue
Block a user