Name the hazard before the barrier
Imagine compute writing seed positions followed by a vertex shader reading them as a storage buffer. Submission order alone does not describe all necessary memory visibility. Write four facts: producer stage, producer access, consumer stage, consumer access. Here they are compute shader, shader storage write, vertex shader, shader storage read. Those facts determine a synchronization2 memory dependency. If the same bytes are fetched as vertex attributes instead, the consumer is vertex attribute input with vertex attribute read access; the correct barrier changes with the actual use.
An execution dependency orders work; a memory dependency additionally handles availability and visibility of the relevant accesses. Keep ranges narrow enough to explain, then optimize only after correctness is established. ALL_COMMANDS everywhere can conceal an incomplete mental model and unnecessarily serialize work. A narrow mask chosen by guesswork is worse. Start from the resource-use graph and include every real consumer.
The fragment below assumes one queue family and a storage-buffer consumer in the vertex shader, with synchronization2 enabled. Record it after the producing dispatch and before vkCmdBeginRendering, outside any render-pass instance. This compute-to-graphics dependency is not a barrier to insert inside the dynamic rendering region. Queue-family ownership is explicitly ignored because there is no transfer. Cross-family use needs a separate release/acquire and semaphore plan; changing the family fields alone is not that plan.
