i965: Fix scalar vertex shader struct outputs.
While we correctly set output[] for composite varyings, we set completely bogus values for output_components[], making emit_urb_writes() output zeros instead of the actual values. Unfortunately, our simple approach goes out the window, and we need to recurse into structs to get the proper value of vector_elements for each field. Together with the previous patch, this fixes rendering in an upcoming game from Feral Interactive. v2: Use pointers instead of pass-by-mutable-reference (Jason, Matt). Cc: "11.1 11.0" <mesa-stable@lists.freedesktop.org> Signed-off-by: Kenneth Graunke <kenneth@whitecape.org> Reviewed-by: Jason Ekstrand <jason.ekstrand@intel.com> Reviewed-by: Matt Turner <mattst88@gmail.com>
This commit is contained in:
@@ -223,6 +223,8 @@ public:
|
||||
|
||||
void emit_nir_code();
|
||||
void nir_setup_inputs();
|
||||
void nir_setup_single_output_varying(fs_reg *reg, const glsl_type *type,
|
||||
unsigned *location);
|
||||
void nir_setup_outputs();
|
||||
void nir_setup_uniforms();
|
||||
void nir_emit_system_values();
|
||||
|
@@ -85,6 +85,32 @@ fs_visitor::nir_setup_inputs()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fs_visitor::nir_setup_single_output_varying(fs_reg *reg,
|
||||
const glsl_type *type,
|
||||
unsigned *location)
|
||||
{
|
||||
if (type->is_array() || type->is_matrix()) {
|
||||
const struct glsl_type *elem_type = glsl_get_array_element(type);
|
||||
const unsigned length = glsl_get_length(type);
|
||||
|
||||
for (unsigned i = 0; i < length; i++) {
|
||||
nir_setup_single_output_varying(reg, elem_type, location);
|
||||
}
|
||||
} else if (type->is_record()) {
|
||||
for (unsigned i = 0; i < type->length; i++) {
|
||||
const struct glsl_type *field_type = type->fields.structure[i].type;
|
||||
nir_setup_single_output_varying(reg, field_type, location);
|
||||
}
|
||||
} else {
|
||||
assert(type->is_scalar() || type->is_vector());
|
||||
this->outputs[*location] = *reg;
|
||||
this->output_components[*location] = type->vector_elements;
|
||||
*reg = offset(*reg, bld, 4);
|
||||
(*location)++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fs_visitor::nir_setup_outputs()
|
||||
{
|
||||
@@ -95,17 +121,13 @@ fs_visitor::nir_setup_outputs()
|
||||
nir_foreach_variable(var, &nir->outputs) {
|
||||
fs_reg reg = offset(nir_outputs, bld, var->data.driver_location);
|
||||
|
||||
int vector_elements = var->type->without_array()->vector_elements;
|
||||
|
||||
switch (stage) {
|
||||
case MESA_SHADER_VERTEX:
|
||||
case MESA_SHADER_GEOMETRY:
|
||||
for (int i = 0; i < type_size_vec4(var->type); i++) {
|
||||
int output = var->data.location + i;
|
||||
this->outputs[output] = offset(reg, bld, 4 * i);
|
||||
this->output_components[output] = vector_elements;
|
||||
}
|
||||
case MESA_SHADER_GEOMETRY: {
|
||||
unsigned location = var->data.location;
|
||||
nir_setup_single_output_varying(®, var->type, &location);
|
||||
break;
|
||||
}
|
||||
case MESA_SHADER_FRAGMENT:
|
||||
if (var->data.index > 0) {
|
||||
assert(var->data.location == FRAG_RESULT_DATA0);
|
||||
@@ -125,6 +147,8 @@ fs_visitor::nir_setup_outputs()
|
||||
} else if (var->data.location == FRAG_RESULT_SAMPLE_MASK) {
|
||||
this->sample_mask = reg;
|
||||
} else {
|
||||
int vector_elements = var->type->without_array()->vector_elements;
|
||||
|
||||
/* gl_FragData or a user-defined FS output */
|
||||
assert(var->data.location >= FRAG_RESULT_DATA0 &&
|
||||
var->data.location < FRAG_RESULT_DATA0+BRW_MAX_DRAW_BUFFERS);
|
||||
|
Reference in New Issue
Block a user