Merge pull request #528 from cdavis5e/host-query-reset

Support the VK_EXT_host_query_reset extension.
diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md
index 26ff91e..3b104de 100644
--- a/Docs/MoltenVK_Runtime_UserGuide.md
+++ b/Docs/MoltenVK_Runtime_UserGuide.md
@@ -247,6 +247,7 @@
 - `VK_KHR_swapchain`
 - `VK_KHR_swapchain_mutable_format`
 - `VK_KHR_variable_pointers`
+- `VK_EXT_host_query_reset`
 - `VK_EXT_memory_budget`
 - `VK_EXT_shader_viewport_index_layer`
 - `VK_EXT_vertex_attribute_divisor`
diff --git a/ExternalRevisions/Vulkan-Headers_repo_revision b/ExternalRevisions/Vulkan-Headers_repo_revision
index 577e8de..927e18d 100644
--- a/ExternalRevisions/Vulkan-Headers_repo_revision
+++ b/ExternalRevisions/Vulkan-Headers_repo_revision
@@ -1 +1 @@
-8e2c4cd554b644592a6d904f2c8000ebbd4aa77f
+ebcf66aa429eceb3360008878fe2881c7f5b2b20
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index 08ea5f0..2163b84 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -63,61 +63,60 @@
     if (features) {
         features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
         features->features = _features;
-        auto* next = (MVKVkAPIStructHeader*)features->pNext;
+        auto* next = (VkBaseOutStructure*)features->pNext;
         while (next) {
             switch ((uint32_t)next->sType) {
-            case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {
-                auto* storageFeatures = (VkPhysicalDevice16BitStorageFeatures*)next;
-                storageFeatures->storageBuffer16BitAccess = true;
-                storageFeatures->uniformAndStorageBuffer16BitAccess = true;
-                storageFeatures->storagePushConstant16 = true;
-                storageFeatures->storageInputOutput16 = true;
-                next = (MVKVkAPIStructHeader*)storageFeatures->pNext;
-                break;
+                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {
+                    auto* storageFeatures = (VkPhysicalDevice16BitStorageFeatures*)next;
+                    storageFeatures->storageBuffer16BitAccess = true;
+                    storageFeatures->uniformAndStorageBuffer16BitAccess = true;
+                    storageFeatures->storagePushConstant16 = true;
+                    storageFeatures->storageInputOutput16 = true;
+                    break;
+                }
+                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR: {
+                    auto* storageFeatures = (VkPhysicalDevice8BitStorageFeaturesKHR*)next;
+                    storageFeatures->storageBuffer8BitAccess = true;
+                    storageFeatures->uniformAndStorageBuffer8BitAccess = true;
+                    storageFeatures->storagePushConstant8 = true;
+                    break;
+                }
+                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR: {
+                    auto* f16Features = (VkPhysicalDeviceFloat16Int8FeaturesKHR*)next;
+                    f16Features->shaderFloat16 = true;
+                    f16Features->shaderInt8 = true;
+                    break;
+                }
+                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES: {
+                    auto* varPtrFeatures = (VkPhysicalDeviceVariablePointerFeatures*)next;
+                    varPtrFeatures->variablePointersStorageBuffer = true;
+                    varPtrFeatures->variablePointers = true;
+                    break;
+                }
+                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT: {
+                    auto* hostQueryResetFeatures = (VkPhysicalDeviceHostQueryResetFeaturesEXT*)next;
+                    hostQueryResetFeatures->hostQueryReset = true;
+                    break;
+                }
+                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
+                    auto* divisorFeatures = (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT*)next;
+                    divisorFeatures->vertexAttributeInstanceRateDivisor = true;
+                    divisorFeatures->vertexAttributeInstanceRateZeroDivisor = true;
+                    break;
+                }
+                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_EXTX: {
+                    auto* portabilityFeatures = (VkPhysicalDevicePortabilitySubsetFeaturesEXTX*)next;
+                    portabilityFeatures->triangleFans = false;
+                    portabilityFeatures->separateStencilMaskRef = true;
+                    portabilityFeatures->events = false;
+                    portabilityFeatures->standardImageViews = _mvkInstance->getMoltenVKConfiguration()->fullImageViewSwizzle;
+                    portabilityFeatures->samplerMipLodBias = false;
+                    break;
+                }
+                default:
+                    break;
             }
-            case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR: {
-                auto* storageFeatures = (VkPhysicalDevice8BitStorageFeaturesKHR*)next;
-                storageFeatures->storageBuffer8BitAccess = true;
-                storageFeatures->uniformAndStorageBuffer8BitAccess = true;
-                storageFeatures->storagePushConstant8 = true;
-                next = (MVKVkAPIStructHeader*)storageFeatures->pNext;
-                break;
-            }
-            case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR: {
-                auto* f16Features = (VkPhysicalDeviceFloat16Int8FeaturesKHR*)next;
-                f16Features->shaderFloat16 = true;
-                f16Features->shaderInt8 = true;
-                next = (MVKVkAPIStructHeader*)f16Features->pNext;
-                break;
-            }
-            case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES: {
-                auto* varPtrFeatures = (VkPhysicalDeviceVariablePointerFeatures*)next;
-                varPtrFeatures->variablePointersStorageBuffer = true;
-                varPtrFeatures->variablePointers = true;
-                next = (MVKVkAPIStructHeader*)varPtrFeatures->pNext;
-                break;
-            }
-            case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
-                auto* divisorFeatures = (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT*)next;
-                divisorFeatures->vertexAttributeInstanceRateDivisor = true;
-                divisorFeatures->vertexAttributeInstanceRateZeroDivisor = true;
-                next = (MVKVkAPIStructHeader*)divisorFeatures->pNext;
-                break;
-            }
-			case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_EXTX: {
-				auto* portabilityFeatures = (VkPhysicalDevicePortabilitySubsetFeaturesEXTX*)next;
-				portabilityFeatures->triangleFans = false;
-				portabilityFeatures->separateStencilMaskRef = true;
-				portabilityFeatures->events = false;
-				portabilityFeatures->standardImageViews = _mvkInstance->getMoltenVKConfiguration()->fullImageViewSwizzle;
-				portabilityFeatures->samplerMipLodBias = false;
-				next = (MVKVkAPIStructHeader*)portabilityFeatures->pNext;
-				break;
-			}
-            default:
-                next = (MVKVkAPIStructHeader*)next->pNext;
-                break;
-            }
+            next = next->pNext;
         }
     }
 }
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
index d3214c3..45ad862 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
@@ -325,6 +325,7 @@
 	ADD_PROC_ADDR(vkGetSwapchainImagesKHR);
 	ADD_PROC_ADDR(vkAcquireNextImageKHR);
 	ADD_PROC_ADDR(vkQueuePresentKHR);
+	ADD_PROC_ADDR(vkResetQueryPoolEXT);
 	ADD_PROC_ADDR(vkGetMoltenVKConfigurationMVK);
 	ADD_PROC_ADDR(vkSetMoltenVKConfigurationMVK);
     ADD_PROC_ADDR(vkGetPhysicalDeviceMetalFeaturesMVK);
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.mm b/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.mm
index b48cdd5..d81e7ef 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.mm
@@ -166,13 +166,19 @@
 void MVKOcclusionQueryPool::resetResults(uint32_t firstQuery, uint32_t queryCount, MVKCommandEncoder* cmdEncoder) {
     MVKQueryPool::resetResults(firstQuery, queryCount, cmdEncoder);
 
-    id<MTLBlitCommandEncoder> blitEncoder = cmdEncoder->getMTLBlitEncoder(kMVKCommandUseResetQueryPool);
     NSUInteger firstOffset = getVisibilityResultOffset(firstQuery);
     NSUInteger lastOffset = getVisibilityResultOffset(firstQuery + queryCount);
+    if (cmdEncoder) {
+        id<MTLBlitCommandEncoder> blitEncoder = cmdEncoder->getMTLBlitEncoder(kMVKCommandUseResetQueryPool);
 
-    [blitEncoder fillBuffer: getVisibilityResultMTLBuffer()
-                      range: NSMakeRange(firstOffset, lastOffset - firstOffset)
-                      value: 0];
+        [blitEncoder fillBuffer: getVisibilityResultMTLBuffer()
+                          range: NSMakeRange(firstOffset, lastOffset - firstOffset)
+                          value: 0];
+    } else {  // Host-side reset
+        id<MTLBuffer> vizBuff = getVisibilityResultMTLBuffer();
+        size_t size = std::min(lastOffset, vizBuff.length) - firstOffset;
+        memset((char *)[vizBuff contents] + firstOffset, 0, size);
+    }
 }
 
 void MVKOcclusionQueryPool::getResult(uint32_t query, void* pQryData, bool shouldOutput64Bit) {
diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def
index 74b4c29..a0f1c45 100644
--- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def
+++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def
@@ -51,6 +51,7 @@
 MVK_EXTENSION(KHR_swapchain, KHR_SWAPCHAIN)
 MVK_EXTENSION(KHR_swapchain_mutable_format, KHR_SWAPCHAIN_MUTABLE_FORMAT)
 MVK_EXTENSION(KHR_variable_pointers, KHR_VARIABLE_POINTERS)
+MVK_EXTENSION(EXT_host_query_reset, EXT_HOST_QUERY_RESET)
 MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET)
 MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER)
 MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR)
diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
index 9a02d8d..314b364 100644
--- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm
+++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
@@ -1806,6 +1806,20 @@
 
 
 #pragma mark -
+#pragma mark VK_EXT_host_query_reset extension
+
+MVK_PUBLIC_SYMBOL void vkResetQueryPoolEXT(
+    VkDevice                                    device,
+    VkQueryPool                                 queryPool,
+    uint32_t                                    firstQuery,
+    uint32_t                                    queryCount) {
+
+    auto* mvkQueryPool = (MVKQueryPool*)queryPool;
+    mvkQueryPool->resetResults(firstQuery, queryCount, nullptr);
+}
+
+
+#pragma mark -
 #pragma mark iOS & macOS surface extensions
 
 MVK_PUBLIC_SYMBOL VkResult vkCreate_PLATFORM_SurfaceMVK(