- int interaction = get_barrier_interaction(current);
- interaction |= moving_interaction;
-
- switch (instr->opcode) {
- case aco_opcode::p_memory_barrier_atomic:
- return !(interaction & barrier_atomic);
- /* For now, buffer and image barriers are treated the same. this is because of
- * dEQP-VK.memory_model.message_passing.core11.u32.coherent.fence_fence.atomicwrite.device.payload_nonlocal.buffer.guard_nonlocal.image.comp
- * which seems to use an image load to determine if the result of a buffer load is valid. So the ordering of the two loads is important.
- * I /think/ we should probably eventually expand the meaning of a buffer barrier so that all buffer operations before it, must stay before it
- * and that both image and buffer operations after it, must stay after it. We should also do the same for image barriers.
- * Or perhaps the problem is that we don't have a combined barrier instruction for both buffers and images, but the CTS test expects us to?
- * Either way, this solution should work. */
- case aco_opcode::p_memory_barrier_buffer:
- case aco_opcode::p_memory_barrier_image:
- return !(interaction & (barrier_image | barrier_buffer));
- case aco_opcode::p_memory_barrier_shared:
- return !(interaction & barrier_shared);
- case aco_opcode::p_memory_barrier_common:
- return !(interaction & (barrier_image | barrier_buffer | barrier_shared | barrier_atomic));
- case aco_opcode::p_memory_barrier_gs_data:
- return !(interaction & barrier_gs_data);
- case aco_opcode::p_memory_barrier_gs_sendmsg:
- return !(interaction & barrier_gs_sendmsg);
- default:
- return false;
+ /* don't move exports so that they stay closer together */
+ if (instr->format == Format::EXP)
+ return hazard_fail_export;
+
+ /* don't move non-reorderable instructions */
+ if (instr->opcode == aco_opcode::s_memtime ||
+ instr->opcode == aco_opcode::s_memrealtime ||
+ instr->opcode == aco_opcode::s_setprio ||
+ instr->opcode == aco_opcode::s_getreg_b32)
+ return hazard_fail_unreorderable;
+
+ memory_event_set instr_set;
+ memset(&instr_set, 0, sizeof(instr_set));
+ memory_sync_info sync = get_sync_info_with_hack(instr);
+ add_memory_event(&instr_set, instr, &sync);
+
+ memory_event_set *first = &instr_set;
+ memory_event_set *second = &query->mem_events;
+ if (upwards)
+ std::swap(first, second);
+
+ /* everything after barrier(acquire) happens after the atomics/control_barriers before
+ * everything after load(acquire) happens after the load
+ */
+ if ((first->has_control_barrier || first->access_atomic) && second->bar_acquire)
+ return hazard_fail_barrier;
+ if (((first->access_acquire || first->bar_acquire) && second->bar_classes) ||
+ ((first->access_acquire | first->bar_acquire) & (second->access_relaxed | second->access_atomic)))
+ return hazard_fail_barrier;
+
+ /* everything before barrier(release) happens before the atomics/control_barriers after *
+ * everything before store(release) happens before the store
+ */
+ if (first->bar_release && (second->has_control_barrier || second->access_atomic))
+ return hazard_fail_barrier;
+ if ((first->bar_classes && (second->bar_release || second->access_release)) ||
+ ((first->access_relaxed | first->access_atomic) & (second->bar_release | second->access_release)))
+ return hazard_fail_barrier;
+
+ /* don't move memory barriers around other memory barriers */
+ if (first->bar_classes && second->bar_classes)
+ return hazard_fail_barrier;
+
+ /* Don't move memory accesses to before control barriers. I don't think
+ * this is necessary for the Vulkan memory model, but it might be for GLSL450. */
+ unsigned control_classes = storage_buffer | storage_atomic_counter | storage_image | storage_shared;
+ if (first->has_control_barrier && ((second->access_atomic | second->access_relaxed) & control_classes))
+ return hazard_fail_barrier;
+
+ /* don't move memory loads/stores past potentially aliasing loads/stores */
+ unsigned aliasing_storage = instr->format == Format::SMEM ?
+ query->aliasing_storage_smem :
+ query->aliasing_storage;
+ if ((sync.storage & aliasing_storage) && !(sync.semantics & semantic_can_reorder)) {
+ unsigned intersect = sync.storage & aliasing_storage;
+ if (intersect & storage_shared)
+ return hazard_fail_reorder_ds;
+ return hazard_fail_reorder_vmem_smem;