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;