layers: PreRecord Free/Destroy calls

To avoid Destroy/Create and Free/Alloc race conditions (when a driver
returns a destroyed(freed) handle between the PreCall and PostCall
phases of a validation intercept routine, PostCallRecord functionality
has been moved to PreCall.  This affects the following calls

	FreeMemory
	DestroyFence
	DestroySemaphore
	DestroyEvent
	DestroyQueryPool
	DestroyBuffer
	DestroyBufferView
	DestroyImage
	DestroyImageView
	DestroyPipeline
	DestroySampler
	DestroyDescriptorSetLayout
	DestroyFramebuffer
	DestroyRenderPass
	FreeDescriptorSets

Did not alter the destroy functions for Instance, Device, or the Debug
or layer extensions.

Change-Id: I5133982eaa1a0c94283fa922d9c3bcc90b5a6223
diff --git a/layers/buffer_validation.cpp b/layers/buffer_validation.cpp
index ca1f57c..8d190bb 100644
--- a/layers/buffer_validation.cpp
+++ b/layers/buffer_validation.cpp
@@ -887,7 +887,7 @@
     return skip;
 }
 
-void PostCallRecordDestroyImage(layer_data *device_data, VkImage image, IMAGE_STATE *image_state, VK_OBJECT obj_struct) {
+void PreCallRecordDestroyImage(layer_data *device_data, VkImage image, IMAGE_STATE *image_state, VK_OBJECT obj_struct) {
     core_validation::invalidateCommandBuffers(device_data, image_state->cb_bindings, obj_struct);
     // Clean up memory mapping, bindings and range references for image
     for (auto mem_binding : image_state->GetBoundMemory()) {
@@ -3632,8 +3632,8 @@
     return skip;
 }
 
-void PostCallRecordDestroyImageView(layer_data *device_data, VkImageView image_view, IMAGE_VIEW_STATE *image_view_state,
-                                    VK_OBJECT obj_struct) {
+void PreCallRecordDestroyImageView(layer_data *device_data, VkImageView image_view, IMAGE_VIEW_STATE *image_view_state,
+                                   VK_OBJECT obj_struct) {
     // Any bound cmd buffers are now invalid
     invalidateCommandBuffers(device_data, image_view_state->cb_bindings, obj_struct);
     (*GetImageViewMap(device_data)).erase(image_view);
@@ -3650,7 +3650,7 @@
     return skip;
 }
 
-void PostCallRecordDestroyBuffer(layer_data *device_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VK_OBJECT obj_struct) {
+void PreCallRecordDestroyBuffer(layer_data *device_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VK_OBJECT obj_struct) {
     invalidateCommandBuffers(device_data, buffer_state->cb_bindings, obj_struct);
     for (auto mem_binding : buffer_state->GetBoundMemory()) {
         auto mem_info = GetMemObjInfo(device_data, mem_binding);
@@ -3675,8 +3675,8 @@
     return skip;
 }
 
-void PostCallRecordDestroyBufferView(layer_data *device_data, VkBufferView buffer_view, BUFFER_VIEW_STATE *buffer_view_state,
-                                     VK_OBJECT obj_struct) {
+void PreCallRecordDestroyBufferView(layer_data *device_data, VkBufferView buffer_view, BUFFER_VIEW_STATE *buffer_view_state,
+                                    VK_OBJECT obj_struct) {
     // Any bound cmd buffers are now invalid
     invalidateCommandBuffers(device_data, buffer_view_state->cb_bindings, obj_struct);
     GetBufferViewMap(device_data)->erase(buffer_view);
diff --git a/layers/buffer_validation.h b/layers/buffer_validation.h
index b8fe5ca..8cf1d83 100644
--- a/layers/buffer_validation.h
+++ b/layers/buffer_validation.h
@@ -39,7 +39,7 @@
 
 void PostCallRecordCreateImage(layer_data *device_data, const VkImageCreateInfo *pCreateInfo, VkImage *pImage);
 
-void PostCallRecordDestroyImage(layer_data *device_data, VkImage image, IMAGE_STATE *image_state, VK_OBJECT obj_struct);
+void PreCallRecordDestroyImage(layer_data *device_data, VkImage image, IMAGE_STATE *image_state, VK_OBJECT obj_struct);
 
 bool PreCallValidateDestroyImage(layer_data *device_data, VkImage image, IMAGE_STATE **image_state, VK_OBJECT *obj_struct);
 
@@ -222,18 +222,18 @@
 bool PreCallValidateDestroyImageView(layer_data *device_data, VkImageView image_view, IMAGE_VIEW_STATE **image_view_state,
                                      VK_OBJECT *obj_struct);
 
-void PostCallRecordDestroyImageView(layer_data *device_data, VkImageView image_view, IMAGE_VIEW_STATE *image_view_state,
-                                    VK_OBJECT obj_struct);
+void PreCallRecordDestroyImageView(layer_data *device_data, VkImageView image_view, IMAGE_VIEW_STATE *image_view_state,
+                                   VK_OBJECT obj_struct);
 
 bool PreCallValidateDestroyBuffer(layer_data *device_data, VkBuffer buffer, BUFFER_STATE **buffer_state, VK_OBJECT *obj_struct);
 
-void PostCallRecordDestroyBuffer(layer_data *device_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VK_OBJECT obj_struct);
+void PreCallRecordDestroyBuffer(layer_data *device_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VK_OBJECT obj_struct);
 
 bool PreCallValidateDestroyBufferView(layer_data *device_data, VkBufferView buffer_view, BUFFER_VIEW_STATE **buffer_view_state,
                                       VK_OBJECT *obj_struct);
 
-void PostCallRecordDestroyBufferView(layer_data *device_data, VkBufferView buffer_view, BUFFER_VIEW_STATE *buffer_view_state,
-                                     VK_OBJECT obj_struct);
+void PreCallRecordDestroyBufferView(layer_data *device_data, VkBufferView buffer_view, BUFFER_VIEW_STATE *buffer_view_state,
+                                    VK_OBJECT obj_struct);
 
 bool PreCallValidateCmdFillBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *buffer_state);
 
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index d1f7e6f..8af1c34 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -3046,7 +3046,7 @@
     return skip;
 }
 
-static void PostCallRecordFreeMemory(layer_data *dev_data, VkDeviceMemory mem, DEVICE_MEM_INFO *mem_info, VK_OBJECT obj_struct) {
+static void PreCallRecordFreeMemory(layer_data *dev_data, VkDeviceMemory mem, DEVICE_MEM_INFO *mem_info, VK_OBJECT obj_struct) {
     // Clear mem binding for any bound objects
     for (auto obj : mem_info->obj_bindings) {
         log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, get_debug_report_enum[obj.type], obj.handle,
@@ -3081,12 +3081,12 @@
     unique_lock_t lock(global_lock);
     bool skip = PreCallValidateFreeMemory(dev_data, mem, &mem_info, &obj_struct);
     if (!skip) {
+        if (mem != VK_NULL_HANDLE) {
+            // Avoid free/alloc race by recording state change before dispatching
+            PreCallRecordFreeMemory(dev_data, mem, mem_info, obj_struct);
+        }
         lock.unlock();
         dev_data->dispatch_table.FreeMemory(device, mem, pAllocator);
-        lock.lock();
-        if (mem != VK_NULL_HANDLE) {
-            PostCallRecordFreeMemory(dev_data, mem, mem_info, obj_struct);
-        }
     }
 }
 
@@ -3398,7 +3398,7 @@
     return skip;
 }
 
-static void PostCallRecordDestroyFence(layer_data *dev_data, VkFence fence) { dev_data->fenceMap.erase(fence); }
+static void PreCallRecordDestroyFence(layer_data *dev_data, VkFence fence) { dev_data->fenceMap.erase(fence); }
 
 VKAPI_ATTR void VKAPI_CALL DestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) {
     layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
@@ -3409,10 +3409,10 @@
     bool skip = PreCallValidateDestroyFence(dev_data, fence, &fence_node, &obj_struct);
 
     if (!skip) {
+        // Pre-record to avoid Destroy/Create race
+        PreCallRecordDestroyFence(dev_data, fence);
         lock.unlock();
         dev_data->dispatch_table.DestroyFence(device, fence, pAllocator);
-        lock.lock();
-        PostCallRecordDestroyFence(dev_data, fence);
     }
 }
 
@@ -3428,7 +3428,7 @@
     return skip;
 }
 
-static void PostCallRecordDestroySemaphore(layer_data *dev_data, VkSemaphore sema) { dev_data->semaphoreMap.erase(sema); }
+static void PreCallRecordDestroySemaphore(layer_data *dev_data, VkSemaphore sema) { dev_data->semaphoreMap.erase(sema); }
 
 VKAPI_ATTR void VKAPI_CALL DestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator) {
     layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
@@ -3437,10 +3437,10 @@
     unique_lock_t lock(global_lock);
     bool skip = PreCallValidateDestroySemaphore(dev_data, semaphore, &sema_node, &obj_struct);
     if (!skip) {
+        // Pre-record to avoid Destroy/Create race
+        PreCallRecordDestroySemaphore(dev_data, semaphore);
         lock.unlock();
         dev_data->dispatch_table.DestroySemaphore(device, semaphore, pAllocator);
-        lock.lock();
-        PostCallRecordDestroySemaphore(dev_data, semaphore);
     }
 }
 
@@ -3455,7 +3455,7 @@
     return skip;
 }
 
-static void PostCallRecordDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE *event_state, VK_OBJECT obj_struct) {
+static void PreCallRecordDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE *event_state, VK_OBJECT obj_struct) {
     invalidateCommandBuffers(dev_data, event_state->cb_bindings, obj_struct);
     dev_data->eventMap.erase(event);
 }
@@ -3467,12 +3467,12 @@
     unique_lock_t lock(global_lock);
     bool skip = PreCallValidateDestroyEvent(dev_data, event, &event_state, &obj_struct);
     if (!skip) {
+        if (event != VK_NULL_HANDLE) {
+            // Pre-record to avoid Destroy/Create race
+            PreCallRecordDestroyEvent(dev_data, event, event_state, obj_struct);
+        }
         lock.unlock();
         dev_data->dispatch_table.DestroyEvent(device, event, pAllocator);
-        lock.lock();
-        if (event != VK_NULL_HANDLE) {
-            PostCallRecordDestroyEvent(dev_data, event, event_state, obj_struct);
-        }
     }
 }
 
@@ -3488,8 +3488,8 @@
     return skip;
 }
 
-static void PostCallRecordDestroyQueryPool(layer_data *dev_data, VkQueryPool query_pool, QUERY_POOL_NODE *qp_state,
-                                           VK_OBJECT obj_struct) {
+static void PreCallRecordDestroyQueryPool(layer_data *dev_data, VkQueryPool query_pool, QUERY_POOL_NODE *qp_state,
+                                          VK_OBJECT obj_struct) {
     invalidateCommandBuffers(dev_data, qp_state->cb_bindings, obj_struct);
     dev_data->queryPoolMap.erase(query_pool);
 }
@@ -3501,12 +3501,12 @@
     unique_lock_t lock(global_lock);
     bool skip = PreCallValidateDestroyQueryPool(dev_data, queryPool, &qp_state, &obj_struct);
     if (!skip) {
+        if (queryPool != VK_NULL_HANDLE) {
+            // Pre-record to avoid Destroy/Create race
+            PreCallRecordDestroyQueryPool(dev_data, queryPool, qp_state, obj_struct);
+        }
         lock.unlock();
         dev_data->dispatch_table.DestroyQueryPool(device, queryPool, pAllocator);
-        lock.lock();
-        if (queryPool != VK_NULL_HANDLE) {
-            PostCallRecordDestroyQueryPool(dev_data, queryPool, qp_state, obj_struct);
-        }
     }
 }
 static bool PreCallValidateGetQueryPoolResults(layer_data *dev_data, VkQueryPool query_pool, uint32_t first_query,
@@ -3807,12 +3807,12 @@
     unique_lock_t lock(global_lock);
     bool skip = PreCallValidateDestroyBuffer(dev_data, buffer, &buffer_state, &obj_struct);
     if (!skip) {
+        if (buffer != VK_NULL_HANDLE) {
+            // Pre-record to avoid Destroy/Create race
+            PreCallRecordDestroyBuffer(dev_data, buffer, buffer_state, obj_struct);
+        }
         lock.unlock();
         dev_data->dispatch_table.DestroyBuffer(device, buffer, pAllocator);
-        lock.lock();
-        if (buffer != VK_NULL_HANDLE) {
-            PostCallRecordDestroyBuffer(dev_data, buffer, buffer_state, obj_struct);
-        }
     }
 }
 
@@ -3825,12 +3825,12 @@
     // Validate state before calling down chain, update common data if we'll be calling down chain
     bool skip = PreCallValidateDestroyBufferView(dev_data, bufferView, &buffer_view_state, &obj_struct);
     if (!skip) {
+        if (bufferView != VK_NULL_HANDLE) {
+            // Pre-record to avoid Destroy/Create race
+            PreCallRecordDestroyBufferView(dev_data, bufferView, buffer_view_state, obj_struct);
+        }
         lock.unlock();
         dev_data->dispatch_table.DestroyBufferView(device, bufferView, pAllocator);
-        lock.lock();
-        if (bufferView != VK_NULL_HANDLE) {
-            PostCallRecordDestroyBufferView(dev_data, bufferView, buffer_view_state, obj_struct);
-        }
     }
 }
 
@@ -3841,12 +3841,12 @@
     unique_lock_t lock(global_lock);
     bool skip = PreCallValidateDestroyImage(dev_data, image, &image_state, &obj_struct);
     if (!skip) {
+        if (image != VK_NULL_HANDLE) {
+            // Pre-record to avoid Destroy/Create race
+            PreCallRecordDestroyImage(dev_data, image, image_state, obj_struct);
+        }
         lock.unlock();
         dev_data->dispatch_table.DestroyImage(device, image, pAllocator);
-        lock.lock();
-        if (image != VK_NULL_HANDLE) {
-            PostCallRecordDestroyImage(dev_data, image, image_state, obj_struct);
-        }
     }
 }
 
@@ -4225,12 +4225,12 @@
     unique_lock_t lock(global_lock);
     bool skip = PreCallValidateDestroyImageView(dev_data, imageView, &image_view_state, &obj_struct);
     if (!skip) {
+        if (imageView != VK_NULL_HANDLE) {
+            // Pre-record to avoid Destroy/Create race
+            PreCallRecordDestroyImageView(dev_data, imageView, image_view_state, obj_struct);
+        }
         lock.unlock();
         dev_data->dispatch_table.DestroyImageView(device, imageView, pAllocator);
-        lock.lock();
-        if (imageView != VK_NULL_HANDLE) {
-            PostCallRecordDestroyImageView(dev_data, imageView, image_view_state, obj_struct);
-        }
     }
 }
 
@@ -4239,6 +4239,7 @@
     layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
 
     unique_lock_t lock(global_lock);
+    // Pre-record to avoid Destroy/Create race
     dev_data->shaderModuleMap.erase(shaderModule);
     lock.unlock();
 
@@ -4257,8 +4258,8 @@
     return skip;
 }
 
-static void PostCallRecordDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE *pipeline_state,
-                                          VK_OBJECT obj_struct) {
+static void PreCallRecordDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE *pipeline_state,
+                                         VK_OBJECT obj_struct) {
     // Any bound cmd buffers are now invalid
     invalidateCommandBuffers(dev_data, pipeline_state->cb_bindings, obj_struct);
     dev_data->pipelineMap.erase(pipeline);
@@ -4271,12 +4272,12 @@
     unique_lock_t lock(global_lock);
     bool skip = PreCallValidateDestroyPipeline(dev_data, pipeline, &pipeline_state, &obj_struct);
     if (!skip) {
+        if (pipeline != VK_NULL_HANDLE) {
+            // Pre-record to avoid Destroy/Create race
+            PreCallRecordDestroyPipeline(dev_data, pipeline, pipeline_state, obj_struct);
+        }
         lock.unlock();
         dev_data->dispatch_table.DestroyPipeline(device, pipeline, pAllocator);
-        lock.lock();
-        if (pipeline != VK_NULL_HANDLE) {
-            PostCallRecordDestroyPipeline(dev_data, pipeline, pipeline_state, obj_struct);
-        }
     }
 }
 
@@ -4284,6 +4285,7 @@
                                                  const VkAllocationCallbacks *pAllocator) {
     layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
     unique_lock_t lock(global_lock);
+    // Pre-record to avoid Destroy/Create race
     dev_data->pipelineLayoutMap.erase(pipelineLayout);
     lock.unlock();
 
@@ -4302,8 +4304,8 @@
     return skip;
 }
 
-static void PostCallRecordDestroySampler(layer_data *dev_data, VkSampler sampler, SAMPLER_STATE *sampler_state,
-                                         VK_OBJECT obj_struct) {
+static void PreCallRecordDestroySampler(layer_data *dev_data, VkSampler sampler, SAMPLER_STATE *sampler_state,
+                                        VK_OBJECT obj_struct) {
     // Any bound cmd buffers are now invalid
     if (sampler_state) invalidateCommandBuffers(dev_data, sampler_state->cb_bindings, obj_struct);
     dev_data->samplerMap.erase(sampler);
@@ -4316,16 +4318,16 @@
     unique_lock_t lock(global_lock);
     bool skip = PreCallValidateDestroySampler(dev_data, sampler, &sampler_state, &obj_struct);
     if (!skip) {
+        if (sampler != VK_NULL_HANDLE) {
+            // Pre-record to avoid Destroy/Create race
+            PreCallRecordDestroySampler(dev_data, sampler, sampler_state, obj_struct);
+        }
         lock.unlock();
         dev_data->dispatch_table.DestroySampler(device, sampler, pAllocator);
-        lock.lock();
-        if (sampler != VK_NULL_HANDLE) {
-            PostCallRecordDestroySampler(dev_data, sampler, sampler_state, obj_struct);
-        }
     }
 }
 
-static void PostCallRecordDestroyDescriptorSetLayout(layer_data *dev_data, VkDescriptorSetLayout ds_layout) {
+static void PreCallRecordDestroyDescriptorSetLayout(layer_data *dev_data, VkDescriptorSetLayout ds_layout) {
     auto layout_it = dev_data->descriptorSetLayoutMap.find(ds_layout);
     if (layout_it != dev_data->descriptorSetLayoutMap.end()) {
         layout_it->second.get()->MarkDestroyed();
@@ -4336,9 +4338,12 @@
 VKAPI_ATTR void VKAPI_CALL DestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout,
                                                       const VkAllocationCallbacks *pAllocator) {
     layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
+    {
+        lock_guard_t lock(global_lock);
+        // Pre-record to avoid Destroy/Create race
+        PreCallRecordDestroyDescriptorSetLayout(dev_data, descriptorSetLayout);
+    }
     dev_data->dispatch_table.DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator);
-    unique_lock_t lock(global_lock);
-    PostCallRecordDestroyDescriptorSetLayout(dev_data, descriptorSetLayout);
 }
 
 static bool PreCallValidateDestroyDescriptorPool(layer_data *dev_data, VkDescriptorPool pool,
@@ -4376,6 +4381,7 @@
     unique_lock_t lock(global_lock);
     bool skip = PreCallValidateDestroyDescriptorPool(dev_data, descriptorPool, &desc_pool_state, &obj_struct);
     if (!skip) {
+        // Pre-record to avoid Destroy/Create race
         PreCallRecordDestroyDescriptorPool(dev_data, descriptorPool, desc_pool_state, obj_struct);
         lock.unlock();
         dev_data->dispatch_table.DestroyDescriptorPool(device, descriptorPool, pAllocator);
@@ -4517,6 +4523,7 @@
     unique_lock_t lock(global_lock);
     bool skip = PreCallValidateDestroyCommandPool(dev_data, commandPool);
     if (!skip) {
+        // Pre-record to avoid Destroy/Create race
         PreCallRecordDestroyCommandPool(dev_data, commandPool);
         lock.unlock();
         dev_data->dispatch_table.DestroyCommandPool(device, commandPool, pAllocator);
@@ -4617,8 +4624,8 @@
     return skip;
 }
 
-static void PostCallRecordDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer, FRAMEBUFFER_STATE *framebuffer_state,
-                                             VK_OBJECT obj_struct) {
+static void PreCallRecordDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer, FRAMEBUFFER_STATE *framebuffer_state,
+                                            VK_OBJECT obj_struct) {
     invalidateCommandBuffers(dev_data, framebuffer_state->cb_bindings, obj_struct);
     dev_data->frameBufferMap.erase(framebuffer);
 }
@@ -4630,12 +4637,12 @@
     unique_lock_t lock(global_lock);
     bool skip = PreCallValidateDestroyFramebuffer(dev_data, framebuffer, &framebuffer_state, &obj_struct);
     if (!skip) {
+        if (framebuffer != VK_NULL_HANDLE) {
+            // Pre-record to avoid Destroy/Create race
+            PreCallRecordDestroyFramebuffer(dev_data, framebuffer, framebuffer_state, obj_struct);
+        }
         lock.unlock();
         dev_data->dispatch_table.DestroyFramebuffer(device, framebuffer, pAllocator);
-        lock.lock();
-        if (framebuffer != VK_NULL_HANDLE) {
-            PostCallRecordDestroyFramebuffer(dev_data, framebuffer, framebuffer_state, obj_struct);
-        }
     }
 }
 
@@ -4651,8 +4658,8 @@
     return skip;
 }
 
-static void PostCallRecordDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE *rp_state,
-                                            VK_OBJECT obj_struct) {
+static void PreCallRecordDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE *rp_state,
+                                           VK_OBJECT obj_struct) {
     invalidateCommandBuffers(dev_data, rp_state->cb_bindings, obj_struct);
     dev_data->renderPassMap.erase(render_pass);
 }
@@ -4664,12 +4671,12 @@
     unique_lock_t lock(global_lock);
     bool skip = PreCallValidateDestroyRenderPass(dev_data, renderPass, &rp_state, &obj_struct);
     if (!skip) {
+        if (renderPass != VK_NULL_HANDLE) {
+            // Pre-record to avoid Destroy/Create race
+            PreCallRecordDestroyRenderPass(dev_data, renderPass, rp_state, obj_struct);
+        }
         lock.unlock();
         dev_data->dispatch_table.DestroyRenderPass(device, renderPass, pAllocator);
-        lock.lock();
-        if (renderPass != VK_NULL_HANDLE) {
-            PostCallRecordDestroyRenderPass(dev_data, renderPass, rp_state, obj_struct);
-        }
     }
 }
 
@@ -4828,6 +4835,7 @@
 VKAPI_ATTR void VKAPI_CALL DestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache,
                                                 const VkAllocationCallbacks *pAllocator) {
     layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
+    // Pre-record to avoid Destroy/Create race (if/when implemented)
     dev_data->dispatch_table.DestroyPipelineCache(device, pipelineCache, pAllocator);
 }
 
@@ -5838,9 +5846,9 @@
     }
     return skip;
 }
-// Sets have been removed from the pool so update underlying state
-static void PostCallRecordFreeDescriptorSets(layer_data *dev_data, VkDescriptorPool pool, uint32_t count,
-                                             const VkDescriptorSet *descriptor_sets) {
+// Sets are being returned to the pool so update the pool state
+static void PreCallRecordFreeDescriptorSets(layer_data *dev_data, VkDescriptorPool pool, uint32_t count,
+                                            const VkDescriptorSet *descriptor_sets) {
     DESCRIPTOR_POOL_STATE *pool_state = GetDescriptorPoolState(dev_data, pool);
     // Update available descriptor sets in pool
     pool_state->availableSets += count;
@@ -5867,14 +5875,15 @@
     // Make sure that no sets being destroyed are in-flight
     unique_lock_t lock(global_lock);
     bool skip = PreCallValidateFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets);
-    lock.unlock();
 
-    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
-    VkResult result = dev_data->dispatch_table.FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets);
-    if (VK_SUCCESS == result) {
-        lock.lock();
-        PostCallRecordFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets);
+    VkResult result;
+    if (skip) {
+        result = VK_ERROR_VALIDATION_FAILED_EXT;
+    } else {
+        // A race here is invalid (descriptorPool should be externally sync'd), but code defensively against an invalid race
+        PreCallRecordFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets);
         lock.unlock();
+        result = dev_data->dispatch_table.FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets);
     }
     return result;
 }
@@ -10832,6 +10841,7 @@
     unique_lock_t lock(global_lock);
     auto swapchain_data = GetSwapchainNode(dev_data, swapchain);
     if (swapchain_data) {
+        // Pre-record to avoid Destroy/Create race
         if (swapchain_data->images.size() > 0) {
             for (auto swapchain_image : swapchain_data->images) {
                 auto image_sub = dev_data->imageSubresourceMap.find(swapchain_image);
@@ -11517,7 +11527,10 @@
                         HandleToUint64(instance), VALIDATION_ERROR_26c009e4,
                         "vkDestroySurfaceKHR() called before its associated VkSwapchainKHR was destroyed.");
     }
+
+    // Pre-record to avoid Destroy/Create race
     instance_data->surface_map.erase(surface);
+
     lock.unlock();
     if (!skip) {
         instance_data->dispatch_table.DestroySurfaceKHR(instance, surface, pAllocator);
@@ -12315,6 +12328,7 @@
                                                            const VkAllocationCallbacks *pAllocator) {
     layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
     unique_lock_t lock(global_lock);
+    // Pre-record to avoid Destroy/Create race
     PreCallRecordDestroyDescriptorUpdateTemplate(device_data, descriptorUpdateTemplate);
     lock.unlock();
     device_data->dispatch_table.DestroyDescriptorUpdateTemplate(device, descriptorUpdateTemplate, pAllocator);
@@ -12325,6 +12339,7 @@
                                                               const VkAllocationCallbacks *pAllocator) {
     layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
     unique_lock_t lock(global_lock);
+    // Pre-record to avoid Destroy/Create race
     PreCallRecordDestroyDescriptorUpdateTemplate(device_data, descriptorUpdateTemplate);
     lock.unlock();
     device_data->dispatch_table.DestroyDescriptorUpdateTemplateKHR(device, descriptorUpdateTemplate, pAllocator);