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_vs_constants,
|
||||||
&st_update_gs_constants,
|
&st_update_gs_constants,
|
||||||
&st_update_fs_constants,
|
&st_update_fs_constants,
|
||||||
|
&st_bind_vs_ubos,
|
||||||
|
&st_bind_fs_ubos,
|
||||||
&st_update_pixel_transfer,
|
&st_update_pixel_transfer,
|
||||||
|
|
||||||
/* this must be done after the vertex program update */
|
/* 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_fs_constants;
|
||||||
extern const struct st_tracked_state st_update_gs_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_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;
|
extern const struct st_tracked_state st_update_pixel_transfer;
|
||||||
|
|
||||||
|
|
||||||
|
@@ -45,7 +45,7 @@
|
|||||||
#include "st_atom.h"
|
#include "st_atom.h"
|
||||||
#include "st_atom_constbuf.h"
|
#include "st_atom_constbuf.h"
|
||||||
#include "st_program.h"
|
#include "st_program.h"
|
||||||
|
#include "st_cb_bufferobjects.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass the given program parameters to the graphics pipe as a
|
* 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 */
|
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:
|
case GL_TRANSFORM_FEEDBACK_BUFFER:
|
||||||
bind = PIPE_BIND_STREAM_OUTPUT;
|
bind = PIPE_BIND_STREAM_OUTPUT;
|
||||||
break;
|
break;
|
||||||
|
case GL_UNIFORM_BUFFER:
|
||||||
|
bind = PIPE_BIND_CONSTANT_BUFFER;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
bind = 0;
|
bind = 0;
|
||||||
}
|
}
|
||||||
|
@@ -70,6 +70,8 @@ void st_init_limits(struct st_context *st)
|
|||||||
struct pipe_screen *screen = st->pipe->screen;
|
struct pipe_screen *screen = st->pipe->screen;
|
||||||
struct gl_constants *c = &st->ctx->Const;
|
struct gl_constants *c = &st->ctx->Const;
|
||||||
gl_shader_type sh;
|
gl_shader_type sh;
|
||||||
|
boolean can_ubo = TRUE;
|
||||||
|
int max_const_buffers;
|
||||||
|
|
||||||
c->MaxTextureLevels
|
c->MaxTextureLevels
|
||||||
= _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS),
|
= _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,
|
options->EmitNoIndirectUniform = !screen->get_shader_param(screen, sh,
|
||||||
PIPE_SHADER_CAP_INDIRECT_CONST_ADDR);
|
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)
|
if (options->EmitNoLoops)
|
||||||
options->MaxUnrollIterations = MIN2(screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_INSTRUCTIONS), 65536);
|
options->MaxUnrollIterations = MIN2(screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_INSTRUCTIONS), 65536);
|
||||||
else
|
else
|
||||||
@@ -251,6 +264,9 @@ void st_init_limits(struct st_context *st)
|
|||||||
|
|
||||||
c->GLSLSkipStrictMaxVaryingLimitCheck =
|
c->GLSLSkipStrictMaxVaryingLimitCheck =
|
||||||
screen->get_param(screen, PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS);
|
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
|
else
|
||||||
this->swizzle = SWIZZLE_XYZW;
|
this->swizzle = SWIZZLE_XYZW;
|
||||||
this->negate = 0;
|
this->negate = 0;
|
||||||
|
this->index2D = 0;
|
||||||
this->type = type ? type->base_type : GLSL_TYPE_ERROR;
|
this->type = type ? type->base_type : GLSL_TYPE_ERROR;
|
||||||
this->reladdr = NULL;
|
this->reladdr = NULL;
|
||||||
}
|
}
|
||||||
@@ -116,6 +117,18 @@ public:
|
|||||||
this->type = type;
|
this->type = type;
|
||||||
this->file = file;
|
this->file = file;
|
||||||
this->index = index;
|
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->swizzle = SWIZZLE_XYZW;
|
||||||
this->negate = 0;
|
this->negate = 0;
|
||||||
this->reladdr = NULL;
|
this->reladdr = NULL;
|
||||||
@@ -126,6 +139,7 @@ public:
|
|||||||
this->type = GLSL_TYPE_ERROR;
|
this->type = GLSL_TYPE_ERROR;
|
||||||
this->file = PROGRAM_UNDEFINED;
|
this->file = PROGRAM_UNDEFINED;
|
||||||
this->index = 0;
|
this->index = 0;
|
||||||
|
this->index2D = 0;
|
||||||
this->swizzle = 0;
|
this->swizzle = 0;
|
||||||
this->negate = 0;
|
this->negate = 0;
|
||||||
this->reladdr = NULL;
|
this->reladdr = NULL;
|
||||||
@@ -135,6 +149,7 @@ public:
|
|||||||
|
|
||||||
gl_register_file file; /**< PROGRAM_* from Mesa */
|
gl_register_file file; /**< PROGRAM_* from Mesa */
|
||||||
int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
|
int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
|
||||||
|
int index2D;
|
||||||
GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */
|
GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */
|
||||||
int negate; /**< NEGATE_XYZW mask from mesa */
|
int negate; /**< NEGATE_XYZW mask from mesa */
|
||||||
int type; /** GLSL_TYPE_* from GLSL IR (enum glsl_base_type) */
|
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->swizzle = SWIZZLE_XYZW;
|
||||||
this->negate = 0;
|
this->negate = 0;
|
||||||
this->reladdr = reg.reladdr;
|
this->reladdr = reg.reladdr;
|
||||||
|
this->index2D = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
st_dst_reg::st_dst_reg(st_src_reg reg)
|
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");
|
assert(!"GLSL 1.30 features unsupported");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ir_binop_ubo_load:
|
case ir_binop_ubo_load: {
|
||||||
assert(!"not yet supported");
|
ir_constant *uniform_block = ir->operands[0]->as_constant();
|
||||||
break;
|
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:
|
case ir_quadop_vector:
|
||||||
/* This operation should have already been handled.
|
/* This operation should have already been handled.
|
||||||
*/
|
*/
|
||||||
@@ -4061,7 +4096,7 @@ dst_register(struct st_translate *t,
|
|||||||
static struct ureg_src
|
static struct ureg_src
|
||||||
src_register(struct st_translate *t,
|
src_register(struct st_translate *t,
|
||||||
gl_register_file file,
|
gl_register_file file,
|
||||||
GLint index)
|
GLint index, GLint index2D)
|
||||||
{
|
{
|
||||||
switch(file) {
|
switch(file) {
|
||||||
case PROGRAM_UNDEFINED:
|
case PROGRAM_UNDEFINED:
|
||||||
@@ -4081,7 +4116,13 @@ src_register(struct st_translate *t,
|
|||||||
return t->constants[index];
|
return t->constants[index];
|
||||||
case PROGRAM_STATE_VAR:
|
case PROGRAM_STATE_VAR:
|
||||||
case PROGRAM_CONSTANT: /* ie, immediate */
|
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);
|
return ureg_DECL_constant(t->ureg, 0);
|
||||||
else
|
else
|
||||||
return t->constants[index];
|
return t->constants[index];
|
||||||
@@ -4160,7 +4201,7 @@ translate_dst(struct st_translate *t,
|
|||||||
static struct ureg_src
|
static struct ureg_src
|
||||||
translate_src(struct st_translate *t, const st_src_reg *src_reg)
|
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,
|
src = ureg_swizzle(src,
|
||||||
GET_SWZ(src_reg->swizzle, 0) & 0x3,
|
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.
|
/* Emit immediate values.
|
||||||
*/
|
*/
|
||||||
t->immediates = (struct ureg_src *)
|
t->immediates = (struct ureg_src *)
|
||||||
@@ -5090,6 +5139,8 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
|
|||||||
|| progress;
|
|| progress;
|
||||||
|
|
||||||
progress = do_vec_index_to_cond_assign(ir) || progress;
|
progress = do_vec_index_to_cond_assign(ir) || progress;
|
||||||
|
|
||||||
|
lower_ubo_reference(prog->_LinkedShaders[i], ir);
|
||||||
} while (progress);
|
} while (progress);
|
||||||
|
|
||||||
validate_ir_tree(ir);
|
validate_ir_tree(ir);
|
||||||
|
Reference in New Issue
Block a user