summaryrefslogtreecommitdiff
path: root/lib/mesa/src/gallium/drivers/r600/sfn/sfn_nir.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mesa/src/gallium/drivers/r600/sfn/sfn_nir.cpp')
-rw-r--r--lib/mesa/src/gallium/drivers/r600/sfn/sfn_nir.cpp35
1 files changed, 21 insertions, 14 deletions
diff --git a/lib/mesa/src/gallium/drivers/r600/sfn/sfn_nir.cpp b/lib/mesa/src/gallium/drivers/r600/sfn/sfn_nir.cpp
index fa5a45dec..be959f350 100644
--- a/lib/mesa/src/gallium/drivers/r600/sfn/sfn_nir.cpp
+++ b/lib/mesa/src/gallium/drivers/r600/sfn/sfn_nir.cpp
@@ -443,23 +443,30 @@ r600_lower_clipvertex_to_clipdist(nir_shader *sh, pipe_stream_output_info& so_in
static bool
r600_nir_lower_atomics(nir_shader *shader)
{
- /* First re-do the offsets, in Hardware we start at zero for each new
- * binding, and we use an offset of one per counter */
- int current_binding = -1;
- int current_offset = 0;
- nir_foreach_variable_with_modes(var, shader, nir_var_uniform)
- {
- if (!var->type->contains_atomic())
- continue;
+ /* In Hardware we start at a zero index for each new
+ * binding, and we use an offset of one per counter. We also
+ * need to sort the atomics according to binding and offset. */
+ std::map<unsigned, unsigned> binding_offset;
+ std::map<unsigned, nir_variable *> sorted_var;
+
+ nir_foreach_variable_with_modes_safe(var, shader, nir_var_uniform) {
+ if (var->type->contains_atomic()) {
+ sorted_var[(var->data.binding << 16) | var->data.offset] = var;
+ exec_node_remove(&var->node);
+ }
+ }
- if (current_binding == (int)var->data.binding) {
- var->data.index = current_offset;
- current_offset += var->type->atomic_size() / ATOMIC_COUNTER_SIZE;
- } else {
- current_binding = var->data.binding;
+ for (auto& [dummy, var] : sorted_var) {
+ auto iindex = binding_offset.find(var->data.binding);
+ unsigned offset_update = var->type->atomic_size() / ATOMIC_COUNTER_SIZE;
+ if (iindex == binding_offset.end()) {
var->data.index = 0;
- current_offset = var->type->atomic_size() / ATOMIC_COUNTER_SIZE;
+ binding_offset[var->data.binding] = offset_update;
+ } else {
+ var->data.index = iindex->second;
+ iindex->second += offset_update;
}
+ shader->variables.push_tail(&var->node);
}
return nir_shader_instructions_pass(shader,