[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

vulkan: Changes to 'upstream-unstable'



Rebased ref, commits from common ancestor:
commit 8d021e4d5a9f91436f4462df1dafb222908e296d
Author: Tony Barbour <tony@LunarG.com>
Date:   Wed Jun 14 11:59:55 2017 -0600

    demos: Modify correct uniform buffer for next frame
    
    Change-Id: I78b8f5ef63fb2c14a3ce431f3e6f6a809e65972f

diff --git a/demos/cube.c b/demos/cube.c
index a0c6dde..ba6d53e 100644
--- a/demos/cube.c
+++ b/demos/cube.c
@@ -957,8 +957,6 @@ static void demo_draw(struct demo *demo) {
     vkWaitForFences(demo->device, 1, &demo->fences[demo->frame_index], VK_TRUE, UINT64_MAX);
     vkResetFences(demo->device, 1, &demo->fences[demo->frame_index]);
 
-    demo_update_data_buffer(demo);
-
     err = !(VK_SUCCESS);
     while (err != VK_SUCCESS) {
         // Get the index of the next available swapchain image:
@@ -979,6 +977,8 @@ static void demo_draw(struct demo *demo) {
         }
     }
 
+    demo_update_data_buffer(demo);
+
     if (demo->VK_GOOGLE_display_timing_enabled) {
         // Look at what happened to previous presents, and make appropriate
         // adjustments in timing:

commit 3db0e68dc5142c81230139da039f8c457e46c1f5
Author: Mark Lobodzinski <mark@lunarg.com>
Date:   Tue Jun 13 13:00:05 2017 -0600

    layers: Use copies of layout data for descriptorsets
    
    DescriptrSets used pointers to descriptorsetlayout data, which caused
    invalid references if the layouts were deleted before the descriptor
    sets. Changed the layer to copy the data.
    
    Change-Id: I671f1efed2aa0986f3a370b51f2f96c07b555af7

diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index 6560497..026c140 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -4754,6 +4754,7 @@ static void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkD
                                                    &dev_data->setMap, dev_data);
 }
 
+// TODO: PostCallRecord routine is dependent on data generated in PreCallValidate -- needs to be moved out
 VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo,
                                                       VkDescriptorSet *pDescriptorSets) {
     layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp
index e8c9069..877d0d6 100644
--- a/layers/descriptor_sets.cpp
+++ b/layers/descriptor_sets.cpp
@@ -316,17 +316,17 @@ cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const V
     : some_update_(false),
       set_(set),
       pool_state_(nullptr),
-      p_layout_(layout),
+      p_layout_(*layout),
       device_data_(dev_data),
       limits_(GetPhysDevProperties(dev_data)->properties.limits) {
     pool_state_ = GetDescriptorPoolState(dev_data, pool);
     // Foreach binding, create default descriptors of given type
-    for (uint32_t i = 0; i < p_layout_->GetBindingCount(); ++i) {
-        auto type = p_layout_->GetTypeFromIndex(i);
+    for (uint32_t i = 0; i < p_layout_.GetBindingCount(); ++i) {
+        auto type = p_layout_.GetTypeFromIndex(i);
         switch (type) {
             case VK_DESCRIPTOR_TYPE_SAMPLER: {
-                auto immut_sampler = p_layout_->GetImmutableSamplerPtrFromIndex(i);
-                for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) {
+                auto immut_sampler = p_layout_.GetImmutableSamplerPtrFromIndex(i);
+                for (uint32_t di = 0; di < p_layout_.GetDescriptorCountFromIndex(i); ++di) {
                     if (immut_sampler) {
                         descriptors_.emplace_back(new SamplerDescriptor(immut_sampler + di));
                         some_update_ = true;  // Immutable samplers are updated at creation
@@ -336,8 +336,8 @@ cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const V
                 break;
             }
             case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
-                auto immut = p_layout_->GetImmutableSamplerPtrFromIndex(i);
-                for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) {
+                auto immut = p_layout_.GetImmutableSamplerPtrFromIndex(i);
+                for (uint32_t di = 0; di < p_layout_.GetDescriptorCountFromIndex(i); ++di) {
                     if (immut) {
                         descriptors_.emplace_back(new ImageSamplerDescriptor(immut + di));
                         some_update_ = true;  // Immutable samplers are updated at creation
@@ -350,19 +350,19 @@ cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const V
             case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
             case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
             case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
-                for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
+                for (uint32_t di = 0; di < p_layout_.GetDescriptorCountFromIndex(i); ++di)
                     descriptors_.emplace_back(new ImageDescriptor(type));
                 break;
             case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
             case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
-                for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
+                for (uint32_t di = 0; di < p_layout_.GetDescriptorCountFromIndex(i); ++di)
                     descriptors_.emplace_back(new TexelDescriptor(type));
                 break;
             case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
             case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
             case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
             case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
-                for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
+                for (uint32_t di = 0; di < p_layout_.GetDescriptorCountFromIndex(i); ++di)
                     descriptors_.emplace_back(new BufferDescriptor(type));
                 break;
             default:
@@ -390,7 +390,7 @@ static std::string string_descriptor_req_view_type(descriptor_req req) {
 
 // Is this sets underlying layout compatible with passed in layout according to "Pipeline Layout Compatibility" in spec?
 bool cvdescriptorset::DescriptorSet::IsCompatible(const DescriptorSetLayout *layout, std::string *error) const {
-    return layout->IsCompatible(p_layout_, error);
+    return layout->IsCompatible(&p_layout_, error);
 }
 
 // Validate that the state of this set is appropriate for the given bindings and dynamic_offsets at Draw time
@@ -402,15 +402,15 @@ bool cvdescriptorset::DescriptorSet::ValidateDrawState(const std::map<uint32_t,
                                                        const char *caller, std::string *error) const {
     for (auto binding_pair : bindings) {
         auto binding = binding_pair.first;
-        if (!p_layout_->HasBinding(binding)) {
+        if (!p_layout_.HasBinding(binding)) {
             std::stringstream error_str;
             error_str << "Attempting to validate DrawState for binding #" << binding
                       << " which is an invalid binding for this descriptor set.";
             *error = error_str.str();
             return false;
         }
-        auto start_idx = p_layout_->GetGlobalStartIndexFromBinding(binding);
-        auto end_idx = p_layout_->GetGlobalEndIndexFromBinding(binding);
+        auto start_idx = p_layout_.GetGlobalStartIndexFromBinding(binding);
+        auto end_idx = p_layout_.GetGlobalEndIndexFromBinding(binding);
         auto array_idx = 0;  // Track array idx if we're dealing with array descriptors
         for (uint32_t i = start_idx; i <= end_idx; ++i, ++array_idx) {
             if (!descriptors_[i]->updated) {
@@ -552,20 +552,20 @@ uint32_t cvdescriptorset::DescriptorSet::GetStorageUpdates(const std::map<uint32
     for (auto binding_pair : bindings) {
         auto binding = binding_pair.first;
         // If a binding doesn't exist, skip it
-        if (!p_layout_->HasBinding(binding)) {
+        if (!p_layout_.HasBinding(binding)) {
             continue;
         }
-        auto start_idx = p_layout_->GetGlobalStartIndexFromBinding(binding);
+        auto start_idx = p_layout_.GetGlobalStartIndexFromBinding(binding);
         if (descriptors_[start_idx]->IsStorage()) {
             if (Image == descriptors_[start_idx]->descriptor_class) {
-                for (uint32_t i = 0; i < p_layout_->GetDescriptorCountFromBinding(binding); ++i) {
+                for (uint32_t i = 0; i < p_layout_.GetDescriptorCountFromBinding(binding); ++i) {
                     if (descriptors_[start_idx + i]->updated) {
                         image_set->insert(static_cast<ImageDescriptor *>(descriptors_[start_idx + i].get())->GetImageView());
                         num_updates++;
                     }
                 }
             } else if (TexelBuffer == descriptors_[start_idx]->descriptor_class) {
-                for (uint32_t i = 0; i < p_layout_->GetDescriptorCountFromBinding(binding); ++i) {
+                for (uint32_t i = 0; i < p_layout_.GetDescriptorCountFromBinding(binding); ++i) {
                     if (descriptors_[start_idx + i]->updated) {
                         auto bufferview = static_cast<TexelDescriptor *>(descriptors_[start_idx + i].get())->GetBufferView();
                         auto bv_state = GetBufferViewState(device_data_, bufferview);
@@ -576,7 +576,7 @@ uint32_t cvdescriptorset::DescriptorSet::GetStorageUpdates(const std::map<uint32
                     }
                 }
             } else if (GeneralBuffer == descriptors_[start_idx]->descriptor_class) {
-                for (uint32_t i = 0; i < p_layout_->GetDescriptorCountFromBinding(binding); ++i) {
+                for (uint32_t i = 0; i < p_layout_.GetDescriptorCountFromBinding(binding); ++i) {
                     if (descriptors_[start_idx + i]->updated) {
                         buffer_set->insert(static_cast<BufferDescriptor *>(descriptors_[start_idx + i].get())->GetBuffer());
                         num_updates++;
@@ -599,7 +599,7 @@ void cvdescriptorset::DescriptorSet::PerformWriteUpdate(const VkWriteDescriptorS
     auto offset = update->dstArrayElement;
     while (descriptors_remaining) {
         uint32_t update_count = std::min(descriptors_remaining, GetDescriptorCountFromBinding(binding_being_updated));
-        auto global_idx = p_layout_->GetGlobalStartIndexFromBinding(binding_being_updated) + offset;
+        auto global_idx = p_layout_.GetGlobalStartIndexFromBinding(binding_being_updated) + offset;
         // Loop over the updates for a single binding at a time
         for (uint32_t di = 0; di < update_count; ++di) {
             descriptors_[global_idx + di]->WriteUpdate(update, di);
@@ -627,7 +627,7 @@ bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data
         *error_msg = error_str.str();
         return false;
     }
-    if (!p_layout_->HasBinding(update->dstBinding)) {
+    if (!p_layout_.HasBinding(update->dstBinding)) {
         *error_code = VALIDATION_ERROR_032002b6;
         std::stringstream error_str;
         error_str << "DescriptorSet " << set_ << " does not have copy update dest binding of " << update->dstBinding;
@@ -655,15 +655,15 @@ bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data
         *error_msg = error_str.str();
         return false;
     }
-    auto dst_start_idx = p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding) + update->dstArrayElement;
-    if ((dst_start_idx + update->descriptorCount) > p_layout_->GetTotalDescriptorCount()) {
+    auto dst_start_idx = p_layout_.GetGlobalStartIndexFromBinding(update->dstBinding) + update->dstArrayElement;
+    if ((dst_start_idx + update->descriptorCount) > p_layout_.GetTotalDescriptorCount()) {
         // DST update out of bounds
         *error_code = VALIDATION_ERROR_032002b8;
         std::stringstream error_str;
         error_str << "Attempting copy update to descriptorSet " << set_ << " binding#" << update->dstBinding
-                  << " with offset index of " << p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding)
+                  << " with offset index of " << p_layout_.GetGlobalStartIndexFromBinding(update->dstBinding)
                   << " plus update array offset of " << update->dstArrayElement << " and update of " << update->descriptorCount
-                  << " descriptors oversteps total number of descriptors in set: " << p_layout_->GetTotalDescriptorCount();
+                  << " descriptors oversteps total number of descriptors in set: " << p_layout_.GetTotalDescriptorCount();
         *error_msg = error_str.str();
         return false;
     }
@@ -672,7 +672,7 @@ bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data
     // fine-grained error codes
     *error_code = VALIDATION_ERROR_032002ba;
     auto src_type = src_set->GetTypeFromBinding(update->srcBinding);
-    auto dst_type = p_layout_->GetTypeFromBinding(update->dstBinding);
+    auto dst_type = p_layout_.GetTypeFromBinding(update->dstBinding);
     if (src_type != dst_type) {
         std::stringstream error_str;
         error_str << "Attempting copy update to descriptorSet " << set_ << " binding #" << update->dstBinding << " with type "
@@ -684,7 +684,7 @@ bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data
     // Verify consistency of src & dst bindings if update crosses binding boundaries
     if ((!src_set->GetLayout()->VerifyUpdateConsistency(update->srcBinding, update->srcArrayElement, update->descriptorCount,
                                                         "copy update from", src_set->GetSet(), error_msg)) ||
-        (!p_layout_->VerifyUpdateConsistency(update->dstBinding, update->dstArrayElement, update->descriptorCount, "copy update to",
+        (!p_layout_.VerifyUpdateConsistency(update->dstBinding, update->dstArrayElement, update->descriptorCount, "copy update to",
                                              set_, error_msg))) {
         return false;
     }
@@ -707,7 +707,7 @@ bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data
 // Perform Copy update
 void cvdescriptorset::DescriptorSet::PerformCopyUpdate(const VkCopyDescriptorSet *update, const DescriptorSet *src_set) {
     auto src_start_idx = src_set->GetGlobalStartIndexFromBinding(update->srcBinding) + update->srcArrayElement;
-    auto dst_start_idx = p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding) + update->dstArrayElement;
+    auto dst_start_idx = p_layout_.GetGlobalStartIndexFromBinding(update->dstBinding) + update->dstArrayElement;
     // Update parameters all look good so perform update
     for (uint32_t di = 0; di < update->descriptorCount; ++di) {
         descriptors_[dst_start_idx + di]->CopyUpdate(src_set->descriptors_[src_start_idx + di].get());
@@ -732,8 +732,8 @@ void cvdescriptorset::DescriptorSet::BindCommandBuffer(GLOBAL_CB_NODE *cb_node,
     // resources
     for (auto binding_req_pair : binding_req_map) {
         auto binding = binding_req_pair.first;
-        auto start_idx = p_layout_->GetGlobalStartIndexFromBinding(binding);
-        auto end_idx = p_layout_->GetGlobalEndIndexFromBinding(binding);
+        auto start_idx = p_layout_.GetGlobalStartIndexFromBinding(binding);
+        auto end_idx = p_layout_.GetGlobalEndIndexFromBinding(binding);
         for (uint32_t i = start_idx; i <= end_idx; ++i) {
             descriptors_[i]->BindCommandBuffer(device_data_, cb_node);
         }
@@ -1242,7 +1242,7 @@ bool cvdescriptorset::DescriptorSet::ValidateWriteUpdate(const debug_report_data
         return false;
     }
     // Verify dst binding exists
-    if (!p_layout_->HasBinding(update->dstBinding)) {
+    if (!p_layout_.HasBinding(update->dstBinding)) {
         *error_code = VALIDATION_ERROR_15c00276;
         std::stringstream error_str;
         error_str << "DescriptorSet " << set_ << " does not have binding " << update->dstBinding;
@@ -1250,7 +1250,7 @@ bool cvdescriptorset::DescriptorSet::ValidateWriteUpdate(const debug_report_data
         return false;
     } else {
         // Make sure binding isn't empty
-        if (0 == p_layout_->GetDescriptorCountFromBinding(update->dstBinding)) {
+        if (0 == p_layout_.GetDescriptorCountFromBinding(update->dstBinding)) {
             *error_code = VALIDATION_ERROR_15c00278;
             std::stringstream error_str;
             error_str << "DescriptorSet " << set_ << " cannot updated binding " << update->dstBinding << " that has 0 descriptors";
@@ -1259,8 +1259,8 @@ bool cvdescriptorset::DescriptorSet::ValidateWriteUpdate(const debug_report_data
         }
     }
     // We know that binding is valid, verify update and do update on each descriptor
-    auto start_idx = p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding) + update->dstArrayElement;
-    auto type = p_layout_->GetTypeFromBinding(update->dstBinding);
+    auto start_idx = p_layout_.GetGlobalStartIndexFromBinding(update->dstBinding) + update->dstArrayElement;
+    auto type = p_layout_.GetTypeFromBinding(update->dstBinding);
     if (type != update->descriptorType) {
         *error_code = VALIDATION_ERROR_15c0027e;
         std::stringstream error_str;
@@ -1281,7 +1281,7 @@ bool cvdescriptorset::DescriptorSet::ValidateWriteUpdate(const debug_report_data
         return false;
     }
     // Verify consecutive bindings match (if needed)
-    if (!p_layout_->VerifyUpdateConsistency(update->dstBinding, update->dstArrayElement, update->descriptorCount, "write update to",
+    if (!p_layout_.VerifyUpdateConsistency(update->dstBinding, update->dstArrayElement, update->descriptorCount, "write update to",
                                             set_, error_msg)) {
         // TODO : Should break out "consecutive binding updates" language into valid usage statements
         *error_code = VALIDATION_ERROR_15c00282;
@@ -1694,14 +1694,12 @@ void cvdescriptorset::PerformAllocateDescriptorSets(const VkDescriptorSetAllocat
                                                     std::unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> *set_map,
                                                     const layer_data *dev_data) {
     auto pool_state = (*pool_map)[p_alloc_info->descriptorPool];
-    /* Account for sets and individual descriptors allocated from pool */
+    // Account for sets and individual descriptors allocated from pool
     pool_state->availableSets -= p_alloc_info->descriptorSetCount;
     for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) {
         pool_state->availableDescriptorTypeCount[i] -= ds_data->required_descriptors_by_type[i];
     }
-    /* Create tracking object for each descriptor set; insert into
-     * global map and the pool's set.
-     */
+    // Create tracking object for each descriptor set; insert into global map and the pool's set.
     for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
         auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], p_alloc_info->descriptorPool, ds_data->layout_nodes[i],
                                                          dev_data);
diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h
index 396082b..00fa830 100644
--- a/layers/descriptor_sets.h
+++ b/layers/descriptor_sets.h
@@ -324,30 +324,30 @@ class DescriptorSet : public BASE_NODE {
     DescriptorSet(const VkDescriptorSet, const VkDescriptorPool, const DescriptorSetLayout *, const core_validation::layer_data *);
     ~DescriptorSet();
     // A number of common Get* functions that return data based on layout from which this set was created
-    uint32_t GetTotalDescriptorCount() const { return p_layout_ ? p_layout_->GetTotalDescriptorCount() : 0; };
-    uint32_t GetDynamicDescriptorCount() const { return p_layout_ ? p_layout_->GetDynamicDescriptorCount() : 0; };
-    uint32_t GetBindingCount() const { return p_layout_ ? p_layout_->GetBindingCount() : 0; };
+    uint32_t GetTotalDescriptorCount() const { return p_layout_.GetTotalDescriptorCount(); };
+    uint32_t GetDynamicDescriptorCount() const { return p_layout_.GetDynamicDescriptorCount(); };
+    uint32_t GetBindingCount() const { return p_layout_.GetBindingCount(); };
     VkDescriptorType GetTypeFromIndex(const uint32_t index) const {
-        return p_layout_ ? p_layout_->GetTypeFromIndex(index) : VK_DESCRIPTOR_TYPE_MAX_ENUM;
+        return p_layout_.GetTypeFromIndex(index);
     };
     VkDescriptorType GetTypeFromGlobalIndex(const uint32_t index) const {
-        return p_layout_ ? p_layout_->GetTypeFromGlobalIndex(index) : VK_DESCRIPTOR_TYPE_MAX_ENUM;
+        return p_layout_.GetTypeFromGlobalIndex(index);
     };
     VkDescriptorType GetTypeFromBinding(const uint32_t binding) const {
-        return p_layout_ ? p_layout_->GetTypeFromBinding(binding) : VK_DESCRIPTOR_TYPE_MAX_ENUM;
+        return p_layout_.GetTypeFromBinding(binding);
     };
     uint32_t GetDescriptorCountFromIndex(const uint32_t index) const {
-        return p_layout_ ? p_layout_->GetDescriptorCountFromIndex(index) : 0;
+        return p_layout_.GetDescriptorCountFromIndex(index);
     };
     uint32_t GetDescriptorCountFromBinding(const uint32_t binding) const {
-        return p_layout_ ? p_layout_->GetDescriptorCountFromBinding(binding) : 0;
+        return p_layout_.GetDescriptorCountFromBinding(binding);
     };
     // Return index into dynamic offset array for given binding
     int32_t GetDynamicOffsetIndexFromBinding(uint32_t binding) const {
-        return p_layout_ ? p_layout_->GetDynamicOffsetIndexFromBinding(binding) : -1;
+        return p_layout_.GetDynamicOffsetIndexFromBinding(binding);
     }
     // Return true if given binding is present in this set
-    bool HasBinding(const uint32_t binding) const { return p_layout_->HasBinding(binding); };
+    bool HasBinding(const uint32_t binding) const { return p_layout_.HasBinding(binding); };
     // Is this set compatible with the given layout?
     bool IsCompatible(const DescriptorSetLayout *, std::string *) const;
     // For given bindings validate state at time of draw is correct, returning false on error and writing error details into string*
@@ -370,7 +370,7 @@ class DescriptorSet : public BASE_NODE {
     // Perform a CopyUpdate whose contents were just validated using ValidateCopyUpdate
     void PerformCopyUpdate(const VkCopyDescriptorSet *, const DescriptorSet *);
 
-    const DescriptorSetLayout *GetLayout() const { return p_layout_; };
+    const DescriptorSetLayout *GetLayout() const { return &p_layout_; };
     VkDescriptorSet GetSet() const { return set_; };
     // Return unordered_set of all command buffers that this set is bound to
     std::unordered_set<GLOBAL_CB_NODE *> GetBoundCmdBuffers() const { return cb_bindings; }
@@ -379,14 +379,14 @@ class DescriptorSet : public BASE_NODE {
     // If given cmd_buffer is in the cb_bindings set, remove it
     void RemoveBoundCommandBuffer(GLOBAL_CB_NODE *cb_node) { cb_bindings.erase(cb_node); }
     VkSampler const *GetImmutableSamplerPtrFromBinding(const uint32_t index) const {
-        return p_layout_->GetImmutableSamplerPtrFromBinding(index);
+        return p_layout_.GetImmutableSamplerPtrFromBinding(index);
     };
     // For a particular binding, get the global index
     uint32_t GetGlobalStartIndexFromBinding(const uint32_t binding) const {
-        return p_layout_->GetGlobalStartIndexFromBinding(binding);
+        return p_layout_.GetGlobalStartIndexFromBinding(binding);
     };
     uint32_t GetGlobalEndIndexFromBinding(const uint32_t binding) const {
-        return p_layout_->GetGlobalEndIndexFromBinding(binding);
+        return p_layout_.GetGlobalEndIndexFromBinding(binding);
     };
     // Return true if any part of set has ever been updated
     bool IsUpdated() const { return some_update_; };
@@ -404,7 +404,7 @@ class DescriptorSet : public BASE_NODE {
     bool some_update_;  // has any part of the set ever been updated?
     VkDescriptorSet set_;
     DESCRIPTOR_POOL_STATE *pool_state_;
-    const DescriptorSetLayout *p_layout_;
+    const DescriptorSetLayout p_layout_;
     std::vector<std::unique_ptr<Descriptor>> descriptors_;
     // Ptr to device data used for various data look-ups
     const core_validation::layer_data *device_data_;

commit 074821cda387269b8075ac01bc9bb1f39af9c290
Author: Mark Young <marky@lunarg.com>
Date:   Thu Jun 15 08:36:58 2017 -0600

    loader: Fix alloc issue
    
    We were allocating the wrong struct for the dispatch table object
    when creating the instance.  This left us using invalid memory
    when using the physical device extension trampolines.
    
    Change-Id: I9939a8c9fe320b0d07592ab4beb5b6faaba40383

diff --git a/loader/trampoline.c b/loader/trampoline.c
index 1afe445..b03ebda 100644
--- a/loader/trampoline.c
+++ b/loader/trampoline.c
@@ -307,16 +307,16 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCr
         goto out;
     }
 
-    ptr_instance->disp =
-        loader_instance_heap_alloc(ptr_instance, sizeof(VkLayerInstanceDispatchTable), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+    ptr_instance->disp = loader_instance_heap_alloc(ptr_instance, sizeof(struct loader_instance_dispatch_table),
+                                                    VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
     if (ptr_instance->disp == NULL) {
         loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
-                   "vkCreateInstance:  Failed to allocate Instance dispatch"
-                   " table.");
+                   "vkCreateInstance:  Failed to allocate Loader's full Instance dispatch table.");
         res = VK_ERROR_OUT_OF_HOST_MEMORY;
         goto out;
     }
-    memcpy(ptr_instance->disp, &instance_disp, sizeof(instance_disp));
+    memcpy(&ptr_instance->disp->layer_inst_disp, &instance_disp, sizeof(instance_disp));
+
     ptr_instance->next = loader.instances;
     loader.instances = ptr_instance;
 

commit e22f27e2b028f8502b7c23d0cc0e44de5af8ec52
Author: Jeremy Hayes <jeremy@lunarg.com>
Date:   Mon Jun 12 15:25:25 2017 -0600

    external: update external revisions
    
    Change-Id: I076eb49526ea8b54bde2d584c5779c8251e56a3e

diff --git a/external_revisions/glslang_revision b/external_revisions/glslang_revision
index d1bd6a6..dc8d66d 100644
--- a/external_revisions/glslang_revision
+++ b/external_revisions/glslang_revision
@@ -1 +1 @@
-136b1e2d5d90284fd7bdd77ed605c70a8d31c8c4
+91c46c656720a6e1e71a3411cd1f4f792b427b2d
diff --git a/external_revisions/spirv-tools_revision b/external_revisions/spirv-tools_revision
index dac2c85..56dbda8 100644
--- a/external_revisions/spirv-tools_revision
+++ b/external_revisions/spirv-tools_revision
@@ -1 +1 @@
-e7aff807a0907b5fc1eb263d71ac27c26f48950f
+7c8da66bc27cc5c4ccb6a0fa612f56c9417518ff

commit 7c9b2aea1e047762ea9cff97ddd1fd33b5efc71d
Author: Chris Forbes <chrisforbes@google.com>
Date:   Mon Jun 12 15:45:11 2017 -0700

    layers: Use correct tracking for display planes query

diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index 439158b..6560497 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -10062,14 +10062,14 @@ static void PostCallRecordGetPhysicalDeviceDisplayPlanePropertiesKHR(instance_la
     auto physical_device_state = GetPhysicalDeviceState(instanceData, physicalDevice);
 
     if (*pPropertyCount) {
-        if (physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState < QUERY_COUNT) {
-            physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState = QUERY_COUNT;
+        if (physical_device_state->vkGetPhysicalDeviceDisplayPlanePropertiesKHRState < QUERY_COUNT) {
+            physical_device_state->vkGetPhysicalDeviceDisplayPlanePropertiesKHRState = QUERY_COUNT;
         }
         physical_device_state->display_plane_property_count = *pPropertyCount;
     }
     if (pProperties) {
-        if (physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState < QUERY_DETAILS) {
-            physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState = QUERY_DETAILS;
+        if (physical_device_state->vkGetPhysicalDeviceDisplayPlanePropertiesKHRState < QUERY_DETAILS) {
+            physical_device_state->vkGetPhysicalDeviceDisplayPlanePropertiesKHRState = QUERY_DETAILS;
         }
     }
 }
@@ -10093,7 +10093,7 @@ static bool ValidateGetPhysicalDeviceDisplayPlanePropertiesKHRQuery(instance_lay
                                                                     const char *api_name) {
     bool skip = false;
     auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice);
-    if (physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState == UNCALLED) {
+    if (physical_device_state->vkGetPhysicalDeviceDisplayPlanePropertiesKHRState == UNCALLED) {
         skip |= log_msg(
             instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
             HandleToUint64(physicalDevice), __LINE__, SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY, "DL",

commit 4d285deca53ab503c0c9eb65ba1c4fb711138d7c
Author: Chris Forbes <chrisforbes@google.com>
Date:   Mon Jun 12 12:51:32 2017 -0700

    layers: Untangle validate & update in CmdCopyQueryPoolResults

diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index f50e6b7..439158b 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -6649,34 +6649,36 @@ VKAPI_ATTR void VKAPI_CALL CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer
     auto dst_buff_state = GetBufferState(dev_data, dstBuffer);
     if (cb_node && dst_buff_state) {
         skip |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_19400674);
-        // Update bindings between buffer and cmd buffer
-        AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state);
         // Validate that DST buffer has correct usage flags set
         skip |=
             ValidateBufferUsageFlags(dev_data, dst_buff_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_19400672,
                                      "vkCmdCopyQueryPoolResults()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
-        std::function<bool()> function = [=]() {
+        skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdCopyQueryPoolResults()",
+                                      VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_19402415);
+        skip |= ValidateCmd(dev_data, cb_node, CMD_COPYQUERYPOOLRESULTS, "vkCmdCopyQueryPoolResults()");
+        skip |= insideRenderPass(dev_data, cb_node, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_19400017);
+    }
+    lock.unlock();
+
+    if (skip) return;
+
+    dev_data->dispatch_table.CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset,
+                                                     stride, flags);
+
+    lock.lock();
+    if (cb_node && dst_buff_state) {
+        AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state);
+        cb_node->validate_functions.emplace_back([=]() {
             SetBufferMemoryValid(dev_data, dst_buff_state, true);
             return false;
-        };
-        cb_node->validate_functions.push_back(function);
+        });
         cb_node->queryUpdates.emplace_back([=](VkQueue q) {
             return validateQuery(q, cb_node, queryPool, firstQuery, queryCount);
         });
-        skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdCopyQueryPoolResults()",
-                                      VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_19402415);
-        skip |= ValidateCmd(dev_data, cb_node, CMD_COPYQUERYPOOLRESULTS, "vkCmdCopyQueryPoolResults()");
         UpdateCmdBufferLastCmd(cb_node, CMD_COPYQUERYPOOLRESULTS);
-        skip |= insideRenderPass(dev_data, cb_node, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_19400017);
         addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings,
                                 {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, cb_node);
-    } else {
-        assert(0);
     }
-    lock.unlock();
-    if (!skip)
-        dev_data->dispatch_table.CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset,
-                                                         stride, flags);
 }
 
 VKAPI_ATTR void VKAPI_CALL CmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags,

commit 6eff586acc3c02decfb0c3af269693252efc8ef8
Author: Chris Forbes <chrisforbes@google.com>
Date:   Mon Jun 12 12:46:39 2017 -0700

    layers: Split validate & update of CmdWriteTimestamp

diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index df227dd..f50e6b7 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -6732,15 +6732,22 @@ VKAPI_ATTR void VKAPI_CALL CmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPi
     std::unique_lock<std::mutex> lock(global_lock);
     GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
     if (cb_state) {
-        QueryObject query = {queryPool, slot};
-        cb_state->queryUpdates.emplace_back([=](VkQueue q) {return setQueryState(q, commandBuffer, query, true);});
         skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdWriteTimestamp()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
                                       VALIDATION_ERROR_1e802415);
         skip |= ValidateCmd(dev_data, cb_state, CMD_WRITETIMESTAMP, "vkCmdWriteTimestamp()");
-        UpdateCmdBufferLastCmd(cb_state, CMD_WRITETIMESTAMP);
     }
     lock.unlock();
-    if (!skip) dev_data->dispatch_table.CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot);
+
+    if (skip) return;
+
+    dev_data->dispatch_table.CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot);
+
+    lock.lock();
+    if (cb_state) {
+        QueryObject query = {queryPool, slot};
+        cb_state->queryUpdates.emplace_back([=](VkQueue q) {return setQueryState(q, commandBuffer, query, true);});
+        UpdateCmdBufferLastCmd(cb_state, CMD_WRITETIMESTAMP);
+    }
 }
 
 static bool MatchUsage(layer_data *dev_data, uint32_t count, const VkAttachmentReference *attachments,

commit e17228238940d38a82570bc5b0ed4dd44e4cbd6d
Author: Chris Forbes <chrisforbes@google.com>
Date:   Mon Jun 12 12:46:20 2017 -0700

    layers: Split validate & update of CmdEndQuery

diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index 41c03ed..df227dd 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -6552,27 +6552,33 @@ VKAPI_ATTR void VKAPI_CALL CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPoo
     bool skip = false;
     layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
     std::unique_lock<std::mutex> lock(global_lock);
+    QueryObject query = {queryPool, slot};
     GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
     if (cb_state) {
-        QueryObject query = {queryPool, slot};
         if (!cb_state->activeQueries.count(query)) {
             skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
                             HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1ae00652, "DS",
                             "Ending a query before it was started: queryPool 0x%" PRIx64 ", index %d. %s",
                             HandleToUint64(queryPool), slot, validation_error_map[VALIDATION_ERROR_1ae00652]);
-        } else {
-            cb_state->activeQueries.erase(query);
         }
-        cb_state->queryUpdates.emplace_back([=](VkQueue q){return setQueryState(q, commandBuffer, query, true);});
         skip |= ValidateCmdQueueFlags(dev_data, cb_state, "VkCmdEndQuery()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
                                       VALIDATION_ERROR_1ae02415);
         skip |= ValidateCmd(dev_data, cb_state, CMD_ENDQUERY, "VkCmdEndQuery()");
+    }
+    lock.unlock();
+
+    if (skip) return;
+
+    dev_data->dispatch_table.CmdEndQuery(commandBuffer, queryPool, slot);
+
+    lock.lock();
+    if (cb_state) {
+        cb_state->activeQueries.erase(query);
+        cb_state->queryUpdates.emplace_back([=](VkQueue q){return setQueryState(q, commandBuffer, query, true);});
         UpdateCmdBufferLastCmd(cb_state, CMD_ENDQUERY);
         addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings,
                                 {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, cb_state);
     }
-    lock.unlock();
-    if (!skip) dev_data->dispatch_table.CmdEndQuery(commandBuffer, queryPool, slot);
 }
 
 VKAPI_ATTR void VKAPI_CALL CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery,

commit 43ec3f090ca979777b306abe7c25662b9429e06d
Author: Chris Forbes <chrisforbes@google.com>
Date:   Mon Jun 12 12:41:47 2017 -0700

    layers: Untangle validate & update of CmdBeginQuery

diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index 0d17859..41c03ed 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -6508,7 +6508,7 @@ VKAPI_ATTR void VKAPI_CALL CmdPipelineBarrier(VkCommandBuffer commandBuffer, VkP
     }
 }
 
-bool setQueryState(VkQueue queue, VkCommandBuffer commandBuffer, QueryObject object, bool value) {
+static bool setQueryState(VkQueue queue, VkCommandBuffer commandBuffer, QueryObject object, bool value) {
     layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
     GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
     if (pCB) {
@@ -6527,20 +6527,25 @@ VKAPI_ATTR void VKAPI_CALL CmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryP
     std::unique_lock<std::mutex> lock(global_lock);
     GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
     if (pCB) {
-        QueryObject query = {queryPool, slot};
-        pCB->activeQueries.insert(query);
-        if (!pCB->startedQueries.count(query)) {
-            pCB->startedQueries.insert(query);
-        }
         skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdBeginQuery()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
                                       VALIDATION_ERROR_17802415);
         skip |= ValidateCmd(dev_data, pCB, CMD_BEGINQUERY, "vkCmdBeginQuery()");
+    }
+    lock.unlock();
+
+    if (skip) return;
+
+    dev_data->dispatch_table.CmdBeginQuery(commandBuffer, queryPool, slot, flags);
+
+    lock.lock();
+    if (pCB) {
+        QueryObject query = {queryPool, slot};
+        pCB->activeQueries.insert(query);
+        pCB->startedQueries.insert(query);
         UpdateCmdBufferLastCmd(pCB, CMD_BEGINQUERY);
         addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings,
                                 {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, pCB);
     }
-    lock.unlock();
-    if (!skip) dev_data->dispatch_table.CmdBeginQuery(commandBuffer, queryPool, slot, flags);
 }
 
 VKAPI_ATTR void VKAPI_CALL CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot) {

commit f49bd2b5f4c968a3033b3e5099bbbcff51201575
Author: Chris Forbes <chrisforbes@google.com>
Date:   Mon Jun 12 11:40:36 2017 -0700

    layers: Convert all the std::bind to lambdas

diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index c484bce..0d17859 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -6108,9 +6108,7 @@ VKAPI_ATTR void VKAPI_CALL CmdSetEvent(VkCommandBuffer commandBuffer, VkEvent ev
         if (!pCB->waitedEvents.count(event)) {
             pCB->writeEventsBeforeWait.push_back(event);
         }
-        std::function<bool(VkQueue)> eventUpdate =
-            std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, stageMask);
-        pCB->eventUpdates.push_back(eventUpdate);
+        pCB->eventUpdates.emplace_back([=](VkQueue q){return setEventStageMask(q, commandBuffer, event, stageMask);});
     }
     lock.unlock();
     if (!skip) dev_data->dispatch_table.CmdSetEvent(commandBuffer, event, stageMask);
@@ -6139,9 +6137,7 @@ VKAPI_ATTR void VKAPI_CALL CmdResetEvent(VkCommandBuffer commandBuffer, VkEvent
             pCB->writeEventsBeforeWait.push_back(event);
         }
         // TODO : Add check for VALIDATION_ERROR_32c008f8
-        std::function<bool(VkQueue)> eventUpdate =
-            std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, VkPipelineStageFlags(0));
-        pCB->eventUpdates.push_back(eventUpdate);
+        pCB->eventUpdates.emplace_back([=](VkQueue q){return setEventStageMask(q, commandBuffer, event, VkPipelineStageFlags(0));});
     }
     lock.unlock();
     if (!skip) dev_data->dispatch_table.CmdResetEvent(commandBuffer, event, stageMask);
@@ -6434,9 +6430,9 @@ VKAPI_ATTR void VKAPI_CALL CmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t
             cb_state->waitedEvents.insert(pEvents[i]);
             cb_state->events.push_back(pEvents[i]);
         }
-        std::function<bool(VkQueue)> event_update =
-            std::bind(validateEventStageMask, std::placeholders::_1, cb_state, eventCount, first_event_index, sourceStageMask);
-        cb_state->eventUpdates.push_back(event_update);
+        cb_state->eventUpdates.emplace_back([=](VkQueue q){
+            return validateEventStageMask(q, cb_state, eventCount, first_event_index, sourceStageMask);
+        });
         skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdWaitEvents()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
                                       VALIDATION_ERROR_1e602415);
         skip |= ValidateCmd(dev_data, cb_state, CMD_WAITEVENTS, "vkCmdWaitEvents()");
@@ -6562,8 +6558,7 @@ VKAPI_ATTR void VKAPI_CALL CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPoo
         } else {
             cb_state->activeQueries.erase(query);
         }
-        std::function<bool(VkQueue)> query_update = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true);
-        cb_state->queryUpdates.push_back(query_update);
+        cb_state->queryUpdates.emplace_back([=](VkQueue q){return setQueryState(q, commandBuffer, query, true);});
         skip |= ValidateCmdQueueFlags(dev_data, cb_state, "VkCmdEndQuery()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
                                       VALIDATION_ERROR_1ae02415);
         skip |= ValidateCmd(dev_data, cb_state, CMD_ENDQUERY, "VkCmdEndQuery()");
@@ -6595,9 +6590,7 @@ VKAPI_ATTR void VKAPI_CALL CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQu
     for (uint32_t i = 0; i < queryCount; i++) {
         QueryObject query = {queryPool, firstQuery + i};
         cb_state->waitedEventsBeforeQueryReset[query] = cb_state->waitedEvents;
-        std::function<bool(VkQueue)> query_update =
-            std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, false);
-        cb_state->queryUpdates.push_back(query_update);
+        cb_state->queryUpdates.emplace_back([=](VkQueue q){return setQueryState(q, commandBuffer, query, false);});
     }
     UpdateCmdBufferLastCmd(cb_state, CMD_RESETQUERYPOOL);
     addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings,
@@ -6656,9 +6649,9 @@ VKAPI_ATTR void VKAPI_CALL CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer
             return false;
         };
         cb_node->validate_functions.push_back(function);
-        std::function<bool(VkQueue)> query_update =
-            std::bind(validateQuery, std::placeholders::_1, cb_node, queryPool, firstQuery, queryCount);
-        cb_node->queryUpdates.push_back(query_update);
+        cb_node->queryUpdates.emplace_back([=](VkQueue q) {
+            return validateQuery(q, cb_node, queryPool, firstQuery, queryCount);
+        });
         skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdCopyQueryPoolResults()",
                                       VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_19402415);
         skip |= ValidateCmd(dev_data, cb_node, CMD_COPYQUERYPOOLRESULTS, "vkCmdCopyQueryPoolResults()");
@@ -6729,8 +6722,7 @@ VKAPI_ATTR void VKAPI_CALL CmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPi
     GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
     if (cb_state) {
         QueryObject query = {queryPool, slot};
-        std::function<bool(VkQueue)> query_update = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true);
-        cb_state->queryUpdates.push_back(query_update);
+        cb_state->queryUpdates.emplace_back([=](VkQueue q) {return setQueryState(q, commandBuffer, query, true);});
         skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdWriteTimestamp()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
                                       VALIDATION_ERROR_1e802415);
         skip |= ValidateCmd(dev_data, cb_state, CMD_WRITETIMESTAMP, "vkCmdWriteTimestamp()");

commit 7ffbe89a37f5f822858a35646be0213fd2cd2b08
Author: Chris Forbes <chrisforbes@google.com>
Date:   Mon Jun 12 11:30:24 2017 -0700

    layers: Untangle validateQuery some

diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index f63eb9a..c484bce 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -6604,30 +6604,27 @@ VKAPI_ATTR void VKAPI_CALL CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQu
                             {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, cb_state);
 }
 
-bool validateQuery(VkQueue queue, GLOBAL_CB_NODE *pCB, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) {
+static bool IsQueryInvalid(layer_data *dev_data, QUEUE_STATE *queue_data, VkQueryPool queryPool, uint32_t queryIndex) {
+    QueryObject query = {queryPool, queryIndex};
+    auto query_data = queue_data->queryToStateMap.find(query);
+    if (query_data != queue_data->queryToStateMap.end()) {
+        if (!query_data->second) return true;
+    } else {
+        auto it = dev_data->queryToStateMap.find(query);
+        if (it == dev_data->queryToStateMap.end() || !it->second)
+            return true;
+    }
+
+    return false;
+}
+
+static bool validateQuery(VkQueue queue, GLOBAL_CB_NODE *pCB, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) {
     bool skip = false;
     layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(pCB->commandBuffer), layer_data_map);
-    auto queue_data = dev_data->queueMap.find(queue);
-    if (queue_data == dev_data->queueMap.end()) return false;
+    auto queue_data = GetQueueState(dev_data, queue);
+    if (!queue_data) return false;
     for (uint32_t i = 0; i < queryCount; i++) {
-        QueryObject query = {queryPool, firstQuery + i};
-        auto query_data = queue_data->second.queryToStateMap.find(query);
-        bool fail = false;
-        if (query_data != queue_data->second.queryToStateMap.end()) {
-            if (!query_data->second) {
-                fail = true;
-            }
-        } else {
-            auto global_query_data = dev_data->queryToStateMap.find(query);
-            if (global_query_data != dev_data->queryToStateMap.end()) {
-                if (!global_query_data->second) {
-                    fail = true;
-                }
-            } else {
-                fail = true;
-            }
-        }
-        if (fail) {
+        if (IsQueryInvalid(dev_data, queue_data, queryPool, firstQuery + i)) {
             skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
                             HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUERY, "DS",
                             "Requesting a copy from query to buffer with invalid query: queryPool 0x%" PRIx64 ", index %d",

commit 2e487f902921a36496fdb4c35279cdd281ca02b0
Author: Chris Forbes <chrisforbes@google.com>
Date:   Mon Jun 12 11:20:45 2017 -0700

    layers: Fix parameter order for validateQuery
    
    This was reversed from every case of these two parameters in the API,
    which was confusing.

diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index 60639a5..f63eb9a 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -6604,7 +6604,7 @@ VKAPI_ATTR void VKAPI_CALL CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQu
                             {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, cb_state);
 }
 
-bool validateQuery(VkQueue queue, GLOBAL_CB_NODE *pCB, VkQueryPool queryPool, uint32_t queryCount, uint32_t firstQuery) {
+bool validateQuery(VkQueue queue, GLOBAL_CB_NODE *pCB, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) {
     bool skip = false;
     layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(pCB->commandBuffer), layer_data_map);
     auto queue_data = dev_data->queueMap.find(queue);
@@ -6660,7 +6660,7 @@ VKAPI_ATTR void VKAPI_CALL CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer
         };
         cb_node->validate_functions.push_back(function);
         std::function<bool(VkQueue)> query_update =
-            std::bind(validateQuery, std::placeholders::_1, cb_node, queryPool, queryCount, firstQuery);
+            std::bind(validateQuery, std::placeholders::_1, cb_node, queryPool, firstQuery, queryCount);
         cb_node->queryUpdates.push_back(query_update);
         skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdCopyQueryPoolResults()",
                                       VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_19402415);

commit 3a4c679ed508b10fd119bb97c127c79b5d126d74
Author: Chris Forbes <chrisforbes@google.com>
Date:   Mon Jun 12 11:17:21 2017 -0700

    layers: Untangle validate from side effects in CmdResetQueryPool

diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index 62a7131..60639a5 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -6581,24 +6581,27 @@ VKAPI_ATTR void VKAPI_CALL CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQu
     layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
     std::unique_lock<std::mutex> lock(global_lock);
     GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
-    if (cb_state) {
-        for (uint32_t i = 0; i < queryCount; i++) {
-            QueryObject query = {queryPool, firstQuery + i};
-            cb_state->waitedEventsBeforeQueryReset[query] = cb_state->waitedEvents;
-            std::function<bool(VkQueue)> query_update =
-                std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, false);
-            cb_state->queryUpdates.push_back(query_update);
-        }
+        skip |= insideRenderPass(dev_data, cb_state, "vkCmdResetQueryPool()", VALIDATION_ERROR_1c600017);
+        skip |= ValidateCmd(dev_data, cb_state, CMD_RESETQUERYPOOL, "VkCmdResetQueryPool()");
         skip |= ValidateCmdQueueFlags(dev_data, cb_state, "VkCmdResetQueryPool()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
                                       VALIDATION_ERROR_1c602415);
-        skip |= ValidateCmd(dev_data, cb_state, CMD_RESETQUERYPOOL, "VkCmdResetQueryPool()");
-        UpdateCmdBufferLastCmd(cb_state, CMD_RESETQUERYPOOL);
-        skip |= insideRenderPass(dev_data, cb_state, "vkCmdResetQueryPool()", VALIDATION_ERROR_1c600017);
-        addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings,
-                                {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, cb_state);
-    }
     lock.unlock();
-    if (!skip) dev_data->dispatch_table.CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount);
+
+    if (skip) return;
+
+    dev_data->dispatch_table.CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount);
+
+    lock.lock();
+    for (uint32_t i = 0; i < queryCount; i++) {
+        QueryObject query = {queryPool, firstQuery + i};
+        cb_state->waitedEventsBeforeQueryReset[query] = cb_state->waitedEvents;
+        std::function<bool(VkQueue)> query_update =
+            std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, false);
+        cb_state->queryUpdates.push_back(query_update);
+    }
+    UpdateCmdBufferLastCmd(cb_state, CMD_RESETQUERYPOOL);
+    addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings,
+                            {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, cb_state);
 }
 
 bool validateQuery(VkQueue queue, GLOBAL_CB_NODE *pCB, VkQueryPool queryPool, uint32_t queryCount, uint32_t firstQuery) {

commit 3531bcd5012a0ea7b0e87eecc5f8d026c868ca8c
Author: Karl Schultz <karl@lunarg.com>
Date:   Mon Jun 12 11:23:57 2017 -0600

    build: Add CMake flag to suppress LVL content
    
    Add CMake flag INSTALL_LVL_FILES (default ON) that when
    set to OFF, suppresses the installation of LVL artifacts
    when running "make install" on Linux.
    
    This flag doesn't have much use in the LVL repo because
    when turned off, CMake won't generate an install target
    in the makefiles.
    
    However, for the downstream VulkanTools and VulkanSamples
    repos, it can be useful to avoid installing LVL files on
    top of files that may have already been installed from
    a previous "make install" installation of the LVL repo.
    
    An example of such a use case would be the desire to
    have a more up-to-date version of LVL on the system
    than the one last merged into the downstream repo.
    
    This new flag is meant to address the need mentioned in
    LVL Pull Request #1844.
    
    Change-Id: I421f37ea4e885fbf0a268eff363a28f0537b1953

diff --git a/CMakeLists.txt b/CMakeLists.txt
index a5b82ed..b4b7d54 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,6 +43,12 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
     if (BUILD_WSI_MIR_SUPPORT)
         find_package(Mir REQUIRED)
     endif()
+
+    # This option can be used to suppress the installation of artifacts from the
+    # Vulkan-LoaderAndValidationLayers repo while running "make install" for the
+    # VulkanTools and VulkanSamples repos.  This can be used to prevent the
+    # overwriting of LVL artifacts when installing these downstream repos.
+    option(INSTALL_LVL_FILES "Install content from LoaderAndValidationLayers repo" ON)
 endif()
 
 set(SCRIPTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/scripts")
@@ -310,7 +316,9 @@ if(NOT WIN32)
 endif()
 
 if(UNIX)
-    install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/vulkan" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+    if(INSTALL_LVL_FILES)
+        install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/vulkan" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+    endif()
 
 # uninstall target
 configure_file(
diff --git a/demos/CMakeLists.txt b/demos/CMakeLists.txt
index 917ea88..b9ea9d0 100644
--- a/demos/CMakeLists.txt
+++ b/demos/CMakeLists.txt
@@ -155,5 +155,7 @@ if ((${CMAKE_SYSTEM_PROCESSOR} STREQUAL ${CMAKE_HOST_SYSTEM_PROCESSOR}))
 endif()
 
 if(UNIX)
-    install(TARGETS ${API_LOWERCASE}info DESTINATION ${CMAKE_INSTALL_BINDIR})
+    if(INSTALL_LVL_FILES)


Reply to: