Fix some raytracing (and mesh) issues.

FindEntrypoint was assuming SPIR-V ExecutionModel values and Vulkan shader stage bits line up, but they no longer do. Add translation from one namespace to the other.

Add missing handling of acceleration structure OpType/descriptorType.

Fix some remaining places that still treated VK_PIPELINE_BIND_POINT as contiguous enums.
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index 88ab5ec..3f459a5 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -1997,8 +1997,8 @@
         pCB->viewportMask = 0;
         pCB->scissorMask = 0;
 
-        for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) {
-            pCB->lastBound[i].reset();
+        for (auto &item : pCB->lastBound) {
+            item.second.reset();
         }
 
         memset(&pCB->activeRenderPassBeginInfo, 0, sizeof(pCB->activeRenderPassBeginInfo));
@@ -7246,16 +7246,19 @@
 // Takes array of error codes as some of the VUID's (e.g. vkCmdBindPipeline) are written per bindpoint
 // TODO add vkCmdBindPipeline bind_point validation using this call.
 bool ValidatePipelineBindPoint(layer_data *device_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point,
-                               const char *func_name,
-                               const std::array<std::string, VK_PIPELINE_BIND_POINT_RANGE_SIZE> &bind_errors) {
+                               const char *func_name, const std::map<VkPipelineBindPoint, std::string> &bind_errors) {
     bool skip = false;
     auto pool = GetCommandPoolNode(device_data, cb_state->createInfo.commandPool);
     if (pool) {  // The loss of a pool in a recording cmd is reported in DestroyCommandPool
-        static const VkQueueFlags flag_mask[VK_PIPELINE_BIND_POINT_RANGE_SIZE] = {VK_QUEUE_GRAPHICS_BIT, VK_QUEUE_COMPUTE_BIT};
-        const auto bind_point_index = bind_point - VK_PIPELINE_BIND_POINT_BEGIN_RANGE;  // typeof enum is not defined, use auto
+        static const std::map<VkPipelineBindPoint, VkQueueFlags> flag_mask = {
+            std::make_pair(VK_PIPELINE_BIND_POINT_GRAPHICS, static_cast<VkQueueFlags>(VK_QUEUE_GRAPHICS_BIT)),
+            std::make_pair(VK_PIPELINE_BIND_POINT_COMPUTE, static_cast<VkQueueFlags>(VK_QUEUE_COMPUTE_BIT)),
+            std::make_pair(VK_PIPELINE_BIND_POINT_RAYTRACING_NVX,
+                           static_cast<VkQueueFlags>(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT)),
+        };
         const auto &qfp = GetPhysDevProperties(device_data)->queue_family_properties[pool->queueFamilyIndex];
-        if (0 == (qfp.queueFlags & flag_mask[bind_point_index])) {
-            const std::string error = bind_errors[bind_point_index];
+        if (0 == (qfp.queueFlags & flag_mask.at(bind_point))) {
+            const std::string error = bind_errors.at(bind_point);
             auto cb_u64 = HandleToUint64(cb_state->commandBuffer);
             auto cp_u64 = HandleToUint64(cb_state->createInfo.commandPool);
             skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
@@ -7276,9 +7279,13 @@
     skip |= ValidateCmd(device_data, cb_state, CMD_PUSHDESCRIPTORSETKHR, func_name);
     skip |= ValidateCmdQueueFlags(device_data, cb_state, func_name, (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT),
                                   "VUID-vkCmdPushDescriptorSetKHR-commandBuffer-cmdpool");
-    skip |= ValidatePipelineBindPoint(
-        device_data, cb_state, bind_point, func_name,
-        {{"VUID-vkCmdPushDescriptorSetKHR-pipelineBindPoint-00363", "VUID-vkCmdPushDescriptorSetKHR-pipelineBindPoint-00363"}});
+
+    static const std::map<VkPipelineBindPoint, std::string> bind_errors = {
+        std::make_pair(VK_PIPELINE_BIND_POINT_GRAPHICS, "VUID-vkCmdPushDescriptorSetKHR-pipelineBindPoint-00363"),
+        std::make_pair(VK_PIPELINE_BIND_POINT_COMPUTE, "VUID-vkCmdPushDescriptorSetKHR-pipelineBindPoint-00363"),
+        std::make_pair(VK_PIPELINE_BIND_POINT_RAYTRACING_NVX, "VUID-vkCmdPushDescriptorSetKHR-pipelineBindPoint-00363")};
+
+    skip |= ValidatePipelineBindPoint(device_data, cb_state, bind_point, func_name, bind_errors);
     auto layout_data = GetPipelineLayout(device_data, layout);
 
     // Validate the set index points to a push descriptor set and is in range
@@ -14112,8 +14119,8 @@
     bool skip = false;
 
     unique_lock_t lock(global_lock);
-    skip |= PreCallValidateCmdDrawMeshTasksNV(dev_data, commandBuffer, true,
-                                              VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, "vkCmdDrawMeshTasksNV()");
+    skip |= PreCallValidateCmdDrawMeshTasksNV(dev_data, commandBuffer, /* indexed */ false, VK_PIPELINE_BIND_POINT_GRAPHICS,
+                                              &cb_state, "vkCmdDrawMeshTasksNV()");
 
     if (!skip) {
         PreCallRecordCmdDrawMeshTasksNV(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS);
@@ -14152,7 +14159,7 @@
     bool skip = false;
 
     unique_lock_t lock(global_lock);
-    skip |= PreCallValidateCmdDrawMeshTasksIndirectNV(dev_data, commandBuffer, buffer, true,
+    skip |= PreCallValidateCmdDrawMeshTasksIndirectNV(dev_data, commandBuffer, buffer, /* indexed */ false,
                                                       VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, &buffer_state,
                                                       "vkCmdDrawMeshTasksIndirectNV()");
 
@@ -14202,7 +14209,7 @@
     bool skip = false;
 
     unique_lock_t lock(global_lock);
-    skip |= PreCallValidateCmdDrawMeshTasksIndirectCountNV(dev_data, commandBuffer, buffer, countBuffer, true,
+    skip |= PreCallValidateCmdDrawMeshTasksIndirectCountNV(dev_data, commandBuffer, buffer, countBuffer, /* indexed */ false,
                                                            VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, &buffer_state,
                                                            &count_buffer_state, "vkCmdDrawMeshTasksIndirectCountNV()");
 
diff --git a/layers/shader_validation.cpp b/layers/shader_validation.cpp
index 55c0166..85edd86 100644
--- a/layers/shader_validation.cpp
+++ b/layers/shader_validation.cpp
@@ -91,6 +91,7 @@
             case spv::OpTypeReserveId:
             case spv::OpTypeQueue:
             case spv::OpTypePipe:
+            case spv::OpTypeAccelerationStructureNVX:
                 def_index[insn.word(1)] = insn.offset();
                 break;
 
@@ -130,11 +131,47 @@
     }
 }
 
+unsigned ExecutionModelToShaderStageFlagBits(unsigned mode) {
+    switch (mode) {
+        case spv::ExecutionModelVertex:
+            return VK_SHADER_STAGE_VERTEX_BIT;
+        case spv::ExecutionModelTessellationControl:
+            return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
+        case spv::ExecutionModelTessellationEvaluation:
+            return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
+        case spv::ExecutionModelGeometry:
+            return VK_SHADER_STAGE_GEOMETRY_BIT;
+        case spv::ExecutionModelFragment:
+            return VK_SHADER_STAGE_FRAGMENT_BIT;
+        case spv::ExecutionModelGLCompute:
+            return VK_SHADER_STAGE_COMPUTE_BIT;
+        case spv::ExecutionModelRayGenerationNVX:
+            return VK_SHADER_STAGE_RAYGEN_BIT_NVX;
+        case spv::ExecutionModelAnyHitNVX:
+            return VK_SHADER_STAGE_ANY_HIT_BIT_NVX;
+        case spv::ExecutionModelClosestHitNVX:
+            return VK_SHADER_STAGE_CLOSEST_HIT_BIT_NVX;
+        case spv::ExecutionModelMissNVX:
+            return VK_SHADER_STAGE_MISS_BIT_NVX;
+        case spv::ExecutionModelIntersectionNVX:
+            return VK_SHADER_STAGE_INTERSECTION_BIT_NVX;
+        case spv::ExecutionModelCallableNVX:
+            return VK_SHADER_STAGE_CALLABLE_BIT_NVX;
+        case spv::ExecutionModelTaskNV:
+            return VK_SHADER_STAGE_TASK_BIT_NV;
+        case spv::ExecutionModelMeshNV:
+            return VK_SHADER_STAGE_MESH_BIT_NV;
+        default:
+            return 0;
+    }
+}
+
 static spirv_inst_iter FindEntrypoint(shader_module const *src, char const *name, VkShaderStageFlagBits stageBits) {
     for (auto insn : *src) {
         if (insn.opcode() == spv::OpEntryPoint) {
             auto entrypointName = (char const *)&insn.word(3);
-            auto entrypointStageBits = 1u << insn.word(1);
+            auto executionModel = insn.word(1);
+            auto entrypointStageBits = ExecutionModelToShaderStageFlagBits(executionModel);
 
             if (!strcmp(entrypointName, name) && (entrypointStageBits & stageBits)) {
                 return insn;
@@ -248,6 +285,9 @@
         case spv::OpTypeImage:
             ss << "image(dim=" << insn.word(3) << ", sampled=" << insn.word(7) << ")";
             break;
+        case spv::OpTypeAccelerationStructureNVX:
+            ss << "accelerationStruture";
+            break;
         default:
             ss << "oddtype";
             break;
@@ -1261,6 +1301,9 @@
                 return ret;
             }
         }
+        case spv::OpTypeAccelerationStructureNVX:
+            ret.insert(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NVX);
+            return ret;
 
             // We shouldn't really see any other junk types -- but if we do, they're a mismatch.
         default:
@@ -1540,7 +1583,7 @@
 }
 
 static void ProcessExecutionModes(shader_module const *src, spirv_inst_iter entrypoint, PIPELINE_STATE *pipeline) {
-    auto entrypoint_id = entrypoint.word(1);
+    auto entrypoint_id = entrypoint.word(2);
     bool is_point_mode = false;
 
     for (auto insn : *src) {
@@ -1803,7 +1846,9 @@
             stage_mask |= pCreateInfo->pStages[i].stage;
         }
         // Determine which shader in which PointSize should be written (the final geometry stage)
-        if (stage_mask & VK_SHADER_STAGE_GEOMETRY_BIT) {
+        if (stage_mask & VK_SHADER_STAGE_MESH_BIT_NV) {
+            stage_mask = VK_SHADER_STAGE_MESH_BIT_NV;
+        } else if (stage_mask & VK_SHADER_STAGE_GEOMETRY_BIT) {
             stage_mask = VK_SHADER_STAGE_GEOMETRY_BIT;
         } else if (stage_mask & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) {
             stage_mask = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;