glsl/linker: Fix xfb with explicit locations and 64bit types
1) Per GL_ARB_enhanced_layouts if explicit location is set for varying, each struct member, array element and matrix row will take separate location. With GL_ARB_gpu_shader_fp64/GL_ARB_gpu_shader_int64 they may take two locations. Examples: | layout(location=0) dvec3[2] a; | layout(location=4) vec2[4] b; | | | | | 32b 32b 32b 32b | 32b 32b 32b 32b | | 0 X X Y Y | 4 X Y 0 0 | | 1 Z Z 0 0 | 5 X Y 0 0 | | 2 X X Y Y | 6 X Y 0 0 | | 3 Z Z 0 0 | 7 X Y 0 0 | Previously it wasn't taken into account. 2) Captured double-precision variables should be aligned to 8 bytes per GL_ARB_gpu_shader_fp64: "If any variable captured in transform feedback has double-precision components, the practical requirements for defined behavior are: ... (c) each double-precision variable captured must be aligned to a multiple of eight bytes relative to the beginning of a vertex." v2: fix `output_size` calculations ( Andrii Simiklit <andrii.simiklit@globallogic.com> ) Closes: https://gitlab.freedesktop.org/mesa/mesa/issues/1667 Reviewed-by: Tapani Pälli <tapani.palli@intel.com> Signed-off-by: Danylo Piliaiev <danylo.piliaiev@globallogic.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/2333>
This commit is contained in:

committed by
Marge Bot

parent
c432cb672a
commit
67e33db4a6
@@ -65,6 +65,13 @@ get_varying_type(const ir_variable *var, gl_shader_stage stage)
|
||||
return type;
|
||||
}
|
||||
|
||||
static bool
|
||||
varying_has_user_specified_location(const ir_variable *var)
|
||||
{
|
||||
return var->data.explicit_location &&
|
||||
var->data.location >= VARYING_SLOT_VAR0;
|
||||
}
|
||||
|
||||
static void
|
||||
create_xfb_varying_names(void *mem_ctx, const glsl_type *t, char **name,
|
||||
size_t name_length, unsigned *count,
|
||||
@@ -1081,7 +1088,7 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
|
||||
unsigned fine_location
|
||||
= this->matched_candidate->toplevel_var->data.location * 4
|
||||
+ this->matched_candidate->toplevel_var->data.location_frac
|
||||
+ this->matched_candidate->offset;
|
||||
+ this->matched_candidate->struct_offset_floats;
|
||||
const unsigned dmul =
|
||||
this->matched_candidate->type->without_array()->is_64bit() ? 2 : 1;
|
||||
|
||||
@@ -1174,7 +1181,7 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
|
||||
this->stream_id = this->matched_candidate->toplevel_var->data.stream;
|
||||
|
||||
unsigned array_offset = this->array_subscript * 4 * dmul;
|
||||
unsigned struct_offset = this->matched_candidate->offset * 4 * dmul;
|
||||
unsigned struct_offset = this->matched_candidate->xfb_offset_floats * 4;
|
||||
this->buffer = this->matched_candidate->toplevel_var->data.xfb_buffer;
|
||||
this->offset = this->matched_candidate->toplevel_var->data.offset +
|
||||
array_offset + struct_offset;
|
||||
@@ -1189,7 +1196,14 @@ tfeedback_decl::get_num_outputs() const
|
||||
if (!this->is_varying()) {
|
||||
return 0;
|
||||
}
|
||||
return (this->num_components() + this->location_frac + 3)/4;
|
||||
|
||||
if (varying_has_user_specified_location(this->matched_candidate->toplevel_var)) {
|
||||
unsigned dmul = this->is_64bit() ? 2 : 1;
|
||||
unsigned rows_per_element = DIV_ROUND_UP(this->vector_elements * dmul, 4);
|
||||
return this->size * this->matrix_columns * rows_per_element;
|
||||
} else {
|
||||
return (this->num_components() + this->location_frac + 3) / 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1299,8 +1313,50 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,
|
||||
used[word] |= BITSET_RANGE(start_range, end_range);
|
||||
}
|
||||
|
||||
const unsigned type_num_components =
|
||||
this->vector_elements * (this->is_64bit() ? 2 : 1);
|
||||
unsigned current_type_components_left = type_num_components;
|
||||
|
||||
while (num_components > 0) {
|
||||
unsigned output_size = MIN2(num_components, 4 - location_frac);
|
||||
unsigned output_size = 0;
|
||||
|
||||
/* From GL_ARB_enhanced_layouts:
|
||||
*
|
||||
* "When an attribute variable declared using an array type is bound to
|
||||
* generic attribute index <i>, the active array elements are assigned to
|
||||
* consecutive generic attributes beginning with generic attribute <i>. The
|
||||
* number of attributes and components assigned to each element are
|
||||
* determined according to the data type of array elements and "component"
|
||||
* layout qualifier (if any) specified in the declaration of the array."
|
||||
*
|
||||
* "When an attribute variable declared using a matrix type is bound to a
|
||||
* generic attribute index <i>, its values are taken from consecutive generic
|
||||
* attributes beginning with generic attribute <i>. Such matrices are
|
||||
* treated as an array of column vectors with values taken from the generic
|
||||
* attributes.
|
||||
* This means there may be gaps in the varyings we are taking values from."
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* | layout(location=0) dvec3[2] a; | layout(location=4) vec2[4] b; |
|
||||
* | | |
|
||||
* | 32b 32b 32b 32b | 32b 32b 32b 32b |
|
||||
* | 0 X X Y Y | 4 X Y 0 0 |
|
||||
* | 1 Z Z 0 0 | 5 X Y 0 0 |
|
||||
* | 2 X X Y Y | 6 X Y 0 0 |
|
||||
* | 3 Z Z 0 0 | 7 X Y 0 0 |
|
||||
*
|
||||
*/
|
||||
if (varying_has_user_specified_location(this->matched_candidate->toplevel_var)) {
|
||||
output_size = MIN3(num_components, current_type_components_left, 4);
|
||||
current_type_components_left -= output_size;
|
||||
if (current_type_components_left == 0) {
|
||||
current_type_components_left = type_num_components;
|
||||
}
|
||||
} else {
|
||||
output_size = MIN2(num_components, 4 - location_frac);
|
||||
}
|
||||
|
||||
assert((info->NumOutputs == 0 && max_outputs == 0) ||
|
||||
info->NumOutputs < max_outputs);
|
||||
|
||||
@@ -2352,7 +2408,8 @@ public:
|
||||
tfeedback_candidates(tfeedback_candidates),
|
||||
stage(stage),
|
||||
toplevel_var(NULL),
|
||||
varying_floats(0)
|
||||
varying_floats(0),
|
||||
xfb_offset_floats(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -2364,6 +2421,7 @@ public:
|
||||
|
||||
this->toplevel_var = var;
|
||||
this->varying_floats = 0;
|
||||
this->xfb_offset_floats = 0;
|
||||
const glsl_type *t =
|
||||
var->data.from_named_ifc_block ? var->get_interface_type() : var->type;
|
||||
if (!var->data.patch && stage == MESA_SHADER_TESS_CTRL) {
|
||||
@@ -2387,11 +2445,37 @@ private:
|
||||
= rzalloc(this->mem_ctx, tfeedback_candidate);
|
||||
candidate->toplevel_var = this->toplevel_var;
|
||||
candidate->type = type;
|
||||
candidate->offset = this->varying_floats;
|
||||
_mesa_hash_table_insert(this->tfeedback_candidates,
|
||||
ralloc_strdup(this->mem_ctx, name),
|
||||
candidate);
|
||||
this->varying_floats += type->component_slots();
|
||||
|
||||
if (type->without_array()->is_64bit()) {
|
||||
/* From ARB_gpu_shader_fp64:
|
||||
*
|
||||
* If any variable captured in transform feedback has double-precision
|
||||
* components, the practical requirements for defined behavior are:
|
||||
* ...
|
||||
* (c) each double-precision variable captured must be aligned to a
|
||||
* multiple of eight bytes relative to the beginning of a vertex.
|
||||
*/
|
||||
this->xfb_offset_floats = ALIGN(this->xfb_offset_floats, 2);
|
||||
/* 64-bit members of structs are also aligned. */
|
||||
this->varying_floats = ALIGN(this->varying_floats, 2);
|
||||
}
|
||||
|
||||
candidate->xfb_offset_floats = this->xfb_offset_floats;
|
||||
candidate->struct_offset_floats = this->varying_floats;
|
||||
|
||||
_mesa_hash_table_insert(this->tfeedback_candidates,
|
||||
ralloc_strdup(this->mem_ctx, name),
|
||||
candidate);
|
||||
|
||||
const unsigned component_slots = type->component_slots();
|
||||
|
||||
if (varying_has_user_specified_location(this->toplevel_var)) {
|
||||
this->varying_floats += type->count_attribute_slots(false) * 4;
|
||||
} else {
|
||||
this->varying_floats += component_slots;
|
||||
}
|
||||
|
||||
this->xfb_offset_floats += component_slots;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2417,6 +2501,11 @@ private:
|
||||
* variable.
|
||||
*/
|
||||
unsigned varying_floats;
|
||||
|
||||
/**
|
||||
* Offset within the xfb. Counted in floats.
|
||||
*/
|
||||
unsigned xfb_offset_floats;
|
||||
};
|
||||
|
||||
|
||||
@@ -2835,7 +2924,7 @@ assign_varying_locations(struct gl_context *ctx,
|
||||
matched_candidate->type->without_array()->is_64bit() ? 2 : 1;
|
||||
const bool lowered =
|
||||
(disable_xfb_packing &&
|
||||
!tfeedback_decls[i].is_aligned(dmul, matched_candidate->offset)) ||
|
||||
!tfeedback_decls[i].is_aligned(dmul, matched_candidate->struct_offset_floats)) ||
|
||||
(matched_candidate->toplevel_var->data.explicit_location &&
|
||||
matched_candidate->toplevel_var->data.location < VARYING_SLOT_VAR0 &&
|
||||
(!consumer || consumer->Stage == MESA_SHADER_FRAGMENT) &&
|
||||
@@ -2857,7 +2946,8 @@ assign_varying_locations(struct gl_context *ctx,
|
||||
new_candidate->toplevel_var = new_var;
|
||||
new_candidate->toplevel_var->data.is_unmatched_generic_inout = 1;
|
||||
new_candidate->type = new_var->type;
|
||||
new_candidate->offset = 0;
|
||||
new_candidate->struct_offset_floats = 0;
|
||||
new_candidate->xfb_offset_floats = 0;
|
||||
_mesa_hash_table_insert(tfeedback_candidates,
|
||||
ralloc_strdup(mem_ctx, new_var->name),
|
||||
new_candidate);
|
||||
|
@@ -77,10 +77,16 @@ struct tfeedback_candidate
|
||||
const glsl_type *type;
|
||||
|
||||
/**
|
||||
* Offset within the toplevel variable where this varying occurs (counted
|
||||
* in multiples of the size of a float).
|
||||
* Offset within the toplevel variable where this varying occurs.
|
||||
* Counted in floats.
|
||||
*/
|
||||
unsigned offset;
|
||||
unsigned struct_offset_floats;
|
||||
|
||||
/**
|
||||
* Offset within the xfb with respect to alignment requirements.
|
||||
* Counted in floats.
|
||||
*/
|
||||
unsigned xfb_offset_floats;
|
||||
};
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user