diff options
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.cpp | 35 |
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, |