diff --git a/.pick_status.json b/.pick_status.json index 82a2e3eeb33..2b1fb6c2a5e 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -4045,7 +4045,7 @@ "description": "r600/sfn: Fix atomic lowering", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "56dedf052f4af1903a0d312eb9c7721c69f36c69" }, diff --git a/src/gallium/drivers/r600/sfn/sfn_nir.cpp b/src/gallium/drivers/r600/sfn/sfn_nir.cpp index 049445c8b4f..0364de4dc79 100644 --- a/src/gallium/drivers/r600/sfn/sfn_nir.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_nir.cpp @@ -443,25 +443,32 @@ 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 binding_offset; + std::map sorted_var; - 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; - var->data.index = 0; - current_offset = var->type->atomic_size() / ATOMIC_COUNTER_SIZE; + 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); } } + 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; + 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, r600_lower_deref_instr, nir_metadata_block_index | nir_metadata_dominance,