diff options
author | Kenneth Graunke <[email protected]> | 2015-11-24 21:33:01 -0800 |
---|---|---|
committer | Kenneth Graunke <[email protected]> | 2015-11-25 11:47:47 -0800 |
commit | 3810c1561401aba336765d64d1a5a3e44eb58eb3 (patch) | |
tree | 33b84bec906f0281c9e1f7732835c40fc120ecc5 /src | |
parent | 3e9003e9cf55265ab1fb6522dc5cbb2f455ea1f9 (diff) |
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" <[email protected]>
Signed-off-by: Kenneth Graunke <[email protected]>
Reviewed-by: Jason Ekstrand <[email protected]>
Reviewed-by: Matt Turner <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs.h | 2 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs_nir.cpp | 40 |
2 files changed, 34 insertions, 8 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index 621d8d59535..bca4589b076 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -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(); diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp index 8495eba084e..9b50e4ebf50 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp @@ -86,6 +86,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() { brw_wm_prog_key *key = (brw_wm_prog_key*) this->key; @@ -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); |