glsl: Calcluate Mesa state slots in front-end instead of back-end
This should be the last bit of infrastructure changes before generating GLSL IR for assembly shaders. This commit leaves some odd code formatting in ir_to_mesa and brw_fs. This was done to minimize whitespace changes / reindentation in some loops. The following commit will restore formatting sanity. Reviewed-by: Eric Anholt <eric@anholt.net> Reviewed-by: Chad Versace <chad.versace@intel.com>
This commit is contained in:
@@ -253,6 +253,16 @@ enum ir_depth_layout {
|
|||||||
const char*
|
const char*
|
||||||
depth_layout_string(ir_depth_layout layout);
|
depth_layout_string(ir_depth_layout layout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of built-in state associated with a uniform
|
||||||
|
*
|
||||||
|
* \sa ir_variable::state_slots
|
||||||
|
*/
|
||||||
|
struct ir_state_slot {
|
||||||
|
int tokens[5];
|
||||||
|
int swizzle;
|
||||||
|
};
|
||||||
|
|
||||||
class ir_variable : public ir_instruction {
|
class ir_variable : public ir_instruction {
|
||||||
public:
|
public:
|
||||||
ir_variable(const struct glsl_type *, const char *, ir_variable_mode);
|
ir_variable(const struct glsl_type *, const char *, ir_variable_mode);
|
||||||
@@ -385,6 +395,22 @@ public:
|
|||||||
*/
|
*/
|
||||||
int location;
|
int location;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Built-in state that backs this uniform
|
||||||
|
*
|
||||||
|
* Once set at variable creation, \c state_slots must remain invariant.
|
||||||
|
* This is because, ideally, this array would be shared by all clones of
|
||||||
|
* this variable in the IR tree. In other words, we'd really like for it
|
||||||
|
* to be a fly-weight.
|
||||||
|
*
|
||||||
|
* If the variable is not a uniform, \c num_state_slots will be zero and
|
||||||
|
* \c state_slots will be \c NULL.
|
||||||
|
*/
|
||||||
|
/*@{*/
|
||||||
|
unsigned num_state_slots; /**< Number of state slots used */
|
||||||
|
ir_state_slot *state_slots; /**< State descriptors. */
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emit a warning if this variable is accessed.
|
* Emit a warning if this variable is accessed.
|
||||||
*/
|
*/
|
||||||
|
@@ -53,6 +53,18 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
|
|||||||
var->origin_upper_left = this->origin_upper_left;
|
var->origin_upper_left = this->origin_upper_left;
|
||||||
var->pixel_center_integer = this->pixel_center_integer;
|
var->pixel_center_integer = this->pixel_center_integer;
|
||||||
var->explicit_location = this->explicit_location;
|
var->explicit_location = this->explicit_location;
|
||||||
|
|
||||||
|
var->num_state_slots = this->num_state_slots;
|
||||||
|
if (this->state_slots) {
|
||||||
|
/* FINISHME: This really wants to use something like talloc_reference, but
|
||||||
|
* FINISHME: ralloc doesn't have any similar function.
|
||||||
|
*/
|
||||||
|
var->state_slots = ralloc_array(var, ir_state_slot,
|
||||||
|
this->num_state_slots);
|
||||||
|
memcpy(var->state_slots, this->state_slots,
|
||||||
|
sizeof(this->state_slots[0]) * var->num_state_slots);
|
||||||
|
}
|
||||||
|
|
||||||
if (this->explicit_location)
|
if (this->explicit_location)
|
||||||
var->location = this->location;
|
var->location = this->location;
|
||||||
|
|
||||||
|
@@ -327,7 +327,43 @@ static ir_variable *
|
|||||||
add_uniform(exec_list *instructions, glsl_symbol_table *symtab,
|
add_uniform(exec_list *instructions, glsl_symbol_table *symtab,
|
||||||
const char *name, const glsl_type *type)
|
const char *name, const glsl_type *type)
|
||||||
{
|
{
|
||||||
return add_variable(instructions, symtab, name, type, ir_var_uniform, -1);
|
ir_variable *const uni =
|
||||||
|
add_variable(instructions, symtab, name, type, ir_var_uniform, -1);
|
||||||
|
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; _mesa_builtin_uniform_desc[i].name != NULL; i++) {
|
||||||
|
if (strcmp(_mesa_builtin_uniform_desc[i].name, name) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(_mesa_builtin_uniform_desc[i].name != NULL);
|
||||||
|
const struct gl_builtin_uniform_desc* const statevar =
|
||||||
|
&_mesa_builtin_uniform_desc[i];
|
||||||
|
|
||||||
|
const unsigned array_count = type->is_array() ? type->length : 1;
|
||||||
|
uni->num_state_slots = array_count * statevar->num_elements;
|
||||||
|
|
||||||
|
ir_state_slot *slots =
|
||||||
|
ralloc_array(uni, ir_state_slot, uni->num_state_slots);
|
||||||
|
|
||||||
|
uni->state_slots = slots;
|
||||||
|
|
||||||
|
for (unsigned a = 0; a < array_count; a++) {
|
||||||
|
for (unsigned j = 0; j < statevar->num_elements; j++) {
|
||||||
|
struct gl_builtin_uniform_element *element = &statevar->elements[j];
|
||||||
|
|
||||||
|
memcpy(slots->tokens, element->tokens, sizeof(element->tokens));
|
||||||
|
if (type->is_array()) {
|
||||||
|
slots->tokens[1] = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
slots->swizzle = element->swizzle;
|
||||||
|
slots++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return uni;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -341,8 +377,12 @@ add_builtin_variable(exec_list *instructions, glsl_symbol_table *symtab,
|
|||||||
|
|
||||||
assert(type != NULL);
|
assert(type != NULL);
|
||||||
|
|
||||||
add_variable(instructions, symtab, proto->name, type, proto->mode,
|
if (proto->mode == ir_var_uniform) {
|
||||||
proto->slot);
|
add_uniform(instructions, symtab, proto->name, type);
|
||||||
|
} else {
|
||||||
|
add_variable(instructions, symtab, proto->name, type, proto->mode,
|
||||||
|
proto->slot);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -994,6 +994,19 @@ update_array_sizes(struct gl_shader_program *prog)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (size + 1 != var->type->fields.array->length) {
|
if (size + 1 != var->type->fields.array->length) {
|
||||||
|
/* If this is a built-in uniform (i.e., it's backed by some
|
||||||
|
* fixed-function state), adjust the number of state slots to
|
||||||
|
* match the new array size. The number of slots per array entry
|
||||||
|
* is not known. It seems saft to assume that the total number of
|
||||||
|
* slots is an integer multiple of the number of array elements.
|
||||||
|
* Determine the number of slots per array element by dividing by
|
||||||
|
* the old (total) size.
|
||||||
|
*/
|
||||||
|
if (var->num_state_slots > 0) {
|
||||||
|
var->num_state_slots = (size + 1)
|
||||||
|
* (var->num_state_slots / var->type->length);
|
||||||
|
}
|
||||||
|
|
||||||
var->type = glsl_type::get_array_instance(var->type->fields.array,
|
var->type = glsl_type::get_array_instance(var->type->fields.array,
|
||||||
size + 1);
|
size + 1);
|
||||||
/* FINISHME: We should update the types of array
|
/* FINISHME: We should update the types of array
|
||||||
|
@@ -399,41 +399,16 @@ fs_visitor::setup_uniform_values(int loc, const glsl_type *type)
|
|||||||
void
|
void
|
||||||
fs_visitor::setup_builtin_uniform_values(ir_variable *ir)
|
fs_visitor::setup_builtin_uniform_values(ir_variable *ir)
|
||||||
{
|
{
|
||||||
const struct gl_builtin_uniform_desc *statevar = NULL;
|
const ir_state_slot *const slots = ir->state_slots;
|
||||||
|
assert(ir->state_slots != NULL);
|
||||||
for (unsigned int i = 0; _mesa_builtin_uniform_desc[i].name; i++) {
|
|
||||||
statevar = &_mesa_builtin_uniform_desc[i];
|
|
||||||
if (strcmp(ir->name, _mesa_builtin_uniform_desc[i].name) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!statevar->name) {
|
|
||||||
fail("Failed to find builtin uniform `%s'\n", ir->name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int array_count;
|
|
||||||
if (ir->type->is_array()) {
|
|
||||||
array_count = ir->type->length;
|
|
||||||
} else {
|
|
||||||
array_count = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int a = 0; a < array_count; a++) {
|
|
||||||
for (unsigned int i = 0; i < statevar->num_elements; i++) {
|
|
||||||
struct gl_builtin_uniform_element *element = &statevar->elements[i];
|
|
||||||
int tokens[STATE_LENGTH];
|
|
||||||
|
|
||||||
memcpy(tokens, element->tokens, sizeof(element->tokens));
|
|
||||||
if (ir->type->is_array()) {
|
|
||||||
tokens[1] = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < ir->num_state_slots; i++) {
|
||||||
/* This state reference has already been setup by ir_to_mesa,
|
/* This state reference has already been setup by ir_to_mesa,
|
||||||
* but we'll get the same index back here.
|
* but we'll get the same index back here.
|
||||||
*/
|
*/
|
||||||
int index = _mesa_add_state_reference(this->fp->Base.Parameters,
|
int index = _mesa_add_state_reference(this->fp->Base.Parameters,
|
||||||
(gl_state_index *)tokens);
|
(gl_state_index *)slots[i].tokens);
|
||||||
|
|
||||||
/* Add each of the unique swizzles of the element as a
|
/* Add each of the unique swizzles of the element as a
|
||||||
* parameter. This'll end up matching the expected layout of
|
* parameter. This'll end up matching the expected layout of
|
||||||
@@ -441,7 +416,7 @@ fs_visitor::setup_builtin_uniform_values(ir_variable *ir)
|
|||||||
*/
|
*/
|
||||||
int last_swiz = -1;
|
int last_swiz = -1;
|
||||||
for (unsigned int j = 0; j < 4; j++) {
|
for (unsigned int j = 0; j < 4; j++) {
|
||||||
int swiz = GET_SWZ(element->swizzle, j);
|
int swiz = GET_SWZ(slots[i].swizzle, j);
|
||||||
if (swiz == last_swiz)
|
if (swiz == last_swiz)
|
||||||
break;
|
break;
|
||||||
last_swiz = swiz;
|
last_swiz = swiz;
|
||||||
|
@@ -754,27 +754,8 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
|
|||||||
|
|
||||||
if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) {
|
if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) {
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
const struct gl_builtin_uniform_desc *statevar;
|
const ir_state_slot *const slots = ir->state_slots;
|
||||||
|
assert(ir->state_slots != NULL);
|
||||||
for (i = 0; _mesa_builtin_uniform_desc[i].name; i++) {
|
|
||||||
if (strcmp(ir->name, _mesa_builtin_uniform_desc[i].name) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_mesa_builtin_uniform_desc[i].name) {
|
|
||||||
fail_link(this->shader_program,
|
|
||||||
"Failed to find builtin uniform `%s'\n", ir->name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
statevar = &_mesa_builtin_uniform_desc[i];
|
|
||||||
|
|
||||||
int array_count;
|
|
||||||
if (ir->type->is_array()) {
|
|
||||||
array_count = ir->type->length;
|
|
||||||
} else {
|
|
||||||
array_count = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if this statevar's setup in the STATE file exactly
|
/* Check if this statevar's setup in the STATE file exactly
|
||||||
* matches how we'll want to reference it as a
|
* matches how we'll want to reference it as a
|
||||||
@@ -782,21 +763,27 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
|
|||||||
* temporary storage and hope that it'll get copy-propagated
|
* temporary storage and hope that it'll get copy-propagated
|
||||||
* out.
|
* out.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < statevar->num_elements; i++) {
|
for (i = 0; i < ir->num_state_slots; i++) {
|
||||||
if (statevar->elements[i].swizzle != SWIZZLE_XYZW) {
|
if (slots[i].swizzle != SWIZZLE_XYZW) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct variable_storage *storage;
|
struct variable_storage *storage;
|
||||||
ir_to_mesa_dst_reg dst;
|
ir_to_mesa_dst_reg dst;
|
||||||
if (i == statevar->num_elements) {
|
if (i == ir->num_state_slots) {
|
||||||
/* We'll set the index later. */
|
/* We'll set the index later. */
|
||||||
storage = new(mem_ctx) variable_storage(ir, PROGRAM_STATE_VAR, -1);
|
storage = new(mem_ctx) variable_storage(ir, PROGRAM_STATE_VAR, -1);
|
||||||
this->variables.push_tail(storage);
|
this->variables.push_tail(storage);
|
||||||
|
|
||||||
dst = ir_to_mesa_undef_dst;
|
dst = ir_to_mesa_undef_dst;
|
||||||
} else {
|
} else {
|
||||||
|
/* The variable_storage constructor allocates slots based on the size
|
||||||
|
* of the type. However, this had better match the number of state
|
||||||
|
* elements that we're going to copy into the new temporary.
|
||||||
|
*/
|
||||||
|
assert(ir->num_state_slots == type_size(ir->type));
|
||||||
|
|
||||||
storage = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY,
|
storage = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY,
|
||||||
this->next_temp);
|
this->next_temp);
|
||||||
this->variables.push_tail(storage);
|
this->variables.push_tail(storage);
|
||||||
@@ -808,29 +795,20 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (int a = 0; a < array_count; a++) {
|
{
|
||||||
for (unsigned int i = 0; i < statevar->num_elements; i++) {
|
for (unsigned int i = 0; i < ir->num_state_slots; i++) {
|
||||||
struct gl_builtin_uniform_element *element = &statevar->elements[i];
|
|
||||||
int tokens[STATE_LENGTH];
|
|
||||||
|
|
||||||
memcpy(tokens, element->tokens, sizeof(element->tokens));
|
|
||||||
if (ir->type->is_array()) {
|
|
||||||
tokens[1] = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
int index = _mesa_add_state_reference(this->prog->Parameters,
|
int index = _mesa_add_state_reference(this->prog->Parameters,
|
||||||
(gl_state_index *)tokens);
|
(gl_state_index *)slots[i].tokens);
|
||||||
|
|
||||||
if (storage->file == PROGRAM_STATE_VAR) {
|
if (storage->file == PROGRAM_STATE_VAR) {
|
||||||
if (storage->index == -1) {
|
if (storage->index == -1) {
|
||||||
storage->index = index;
|
storage->index = index;
|
||||||
} else {
|
} else {
|
||||||
assert(index ==
|
assert(index == storage->index + (int)i);
|
||||||
(int)(storage->index + a * statevar->num_elements + i));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ir_to_mesa_src_reg src(PROGRAM_STATE_VAR, index, NULL);
|
ir_to_mesa_src_reg src(PROGRAM_STATE_VAR, index, NULL);
|
||||||
src.swizzle = element->swizzle;
|
src.swizzle = slots[i].swizzle;
|
||||||
ir_to_mesa_emit_op1(ir, OPCODE_MOV, dst, src);
|
ir_to_mesa_emit_op1(ir, OPCODE_MOV, dst, src);
|
||||||
/* even a float takes up a whole vec4 reg in a struct/array. */
|
/* even a float takes up a whole vec4 reg in a struct/array. */
|
||||||
dst.index++;
|
dst.index++;
|
||||||
@@ -838,7 +816,7 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (storage->file == PROGRAM_TEMPORARY &&
|
if (storage->file == PROGRAM_TEMPORARY &&
|
||||||
dst.index != storage->index + type_size(ir->type)) {
|
dst.index != storage->index + ir->num_state_slots) {
|
||||||
fail_link(this->shader_program,
|
fail_link(this->shader_program,
|
||||||
"failed to load builtin uniform `%s' (%d/%d regs loaded)\n",
|
"failed to load builtin uniform `%s' (%d/%d regs loaded)\n",
|
||||||
ir->name, dst.index - storage->index,
|
ir->name, dst.index - storage->index,
|
||||||
|
Reference in New Issue
Block a user