layers: Skip layout transition in release op
diff --git a/layers/buffer_validation.cpp b/layers/buffer_validation.cpp
index 77be373..48212e1 100644
--- a/layers/buffer_validation.cpp
+++ b/layers/buffer_validation.cpp
@@ -572,12 +572,31 @@
     return skip;
 }
 
+static bool IsReleaseOp(layer_data *device_data, GLOBAL_CB_NODE *cb_state, VkImageMemoryBarrier const *barrier) {
+    if (barrier->srcQueueFamilyIndex == barrier->dstQueueFamilyIndex)
+        return false;
+
+    auto pool = GetCommandPoolNode(device_data, cb_state->createInfo.commandPool);
+    return pool->queueFamilyIndex == barrier->srcQueueFamilyIndex;
+}
+
 void TransitionImageLayouts(layer_data *device_data, GLOBAL_CB_NODE *cb_state, uint32_t memBarrierCount,
                             const VkImageMemoryBarrier *pImgMemBarriers) {
     for (uint32_t i = 0; i < memBarrierCount; ++i) {
         auto mem_barrier = &pImgMemBarriers[i];
         if (!mem_barrier) continue;
 
+        // For ownership transfers, the barrier is specified twice; as a release
+        // operation on the yielding queue family, and as an acquire operation
+        // on the acquiring queue family. This barrier may also include a layout
+        // transition, which occurs 'between' the two operations. For validation
+        // purposes it doesn't seem important which side performs the layout
+        // transition, but it must not be performed twice. We'll arbitrarily
+        // choose to perform it as part of the acquire operation.
+        if (IsReleaseOp(device_data, cb_state, mem_barrier)) {
+            continue;
+        }
+
         VkImageCreateInfo *image_create_info = &(GetImageState(device_data, mem_barrier->image)->createInfo);
         uint32_t level_count = ResolveRemainingLevels(&mem_barrier->subresourceRange, image_create_info->mipLevels);
         uint32_t layer_count = ResolveRemainingLayers(&mem_barrier->subresourceRange, image_create_info->arrayLayers);