layers: Ignore 'noautovalidity' params w/codgen
Add special handling to the parameter_validation layer's code
generator for vk.xml parameters with the 'noautovalidty' attribute:
- Ignore vk.xml parameters with the 'noautovalidity' attribute
when generating code for the parameter_validation layer.
- Implement custom validation routines for parameters with
'noautovalidity' tags.
Issues-Addressed: GitHub 515
Change-Id: I1bd28cc79233fb8b040d6e107ed5e2176a84edb5
diff --git a/layers/parameter_validation.cpp b/layers/parameter_validation.cpp
index 20676b4..035b929 100644
--- a/layers/parameter_validation.cpp
+++ b/layers/parameter_validation.cpp
@@ -2237,16 +2237,31 @@
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(my_data != NULL);
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ assert(device_data != nullptr);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkCreateQueryPool(my_data->report_data, pCreateInfo, pAllocator, pQueryPool);
+ skip_call |= parameter_validation_vkCreateQueryPool(device_data->report_data, pCreateInfo, pAllocator, pQueryPool);
- if (!skipCall) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ if (pCreateInfo != nullptr) {
+ // If queryType is VK_QUERY_TYPE_PIPELINE_STATISTICS, pipelineStatistics must be a valid combination of
+ // VkQueryPipelineStatisticFlagBits values
+ if ((pCreateInfo->queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS) && (pCreateInfo->pipelineStatistics != 0) &&
+ ((pCreateInfo->pipelineStatistics & (~AllVkQueryPipelineStatisticFlagBits)) != 0)) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
+ UNRECOGNIZED_VALUE, LayerName, "vkCreateQueryPool: if pCreateInfo->queryType is "
+ "VK_QUERY_TYPE_PIPELINE_STATISTICS, pCreateInfo->pipelineStatistics must be "
+ "a valid combination of VkQueryPipelineStatisticFlagBits values");
+ }
+ }
+
+ if (!skip_call) {
result = get_dispatch_table(pc_device_table_map, device)->CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool);
- validate_result(my_data->report_data, "vkCreateQueryPool", result);
+ validate_result(report_data, "vkCreateQueryPool", result);
}
return result;
@@ -2286,32 +2301,47 @@
return result;
}
-bool PreCreateBuffer(layer_data *device_data, const VkBufferCreateInfo *pCreateInfo) {
- if (pCreateInfo != nullptr) {
- if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
- validate_queue_family_indices(device_data, "vkCreateBuffer", "pCreateInfo->pQueueFamilyIndices",
- pCreateInfo->queueFamilyIndexCount, pCreateInfo->pQueueFamilyIndices);
- }
- }
-
- return true;
-}
-
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(my_data != NULL);
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ assert(device_data != nullptr);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkCreateBuffer(my_data->report_data, pCreateInfo, pAllocator, pBuffer);
+ skip_call |= parameter_validation_vkCreateBuffer(report_data, pCreateInfo, pAllocator, pBuffer);
- if (!skipCall) {
- PreCreateBuffer(my_data, pCreateInfo);
+ if (pCreateInfo != nullptr) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
+ // If sharingMode is VK_SHARING_MODE_CONCURRENT, queueFamilyIndexCount must be greater than 1
+ if (pCreateInfo->queueFamilyIndexCount <= 1) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
+ INVALID_USAGE, LayerName, "vkCreateBuffer: if pCreateInfo->sharingMode is VK_SHARING_MODE_CONCURRENT, "
+ "pCreateInfo->queueFamilyIndexCount must be greater than 1");
+ }
+ // If sharingMode is VK_SHARING_MODE_CONCURRENT, pQueueFamilyIndices must be a pointer to an array of
+ // queueFamilyIndexCount uint32_t values
+ if (pCreateInfo->pQueueFamilyIndices == nullptr) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkCreateBuffer: if pCreateInfo->sharingMode is VK_SHARING_MODE_CONCURRENT, "
+ "pCreateInfo->pQueueFamilyIndices must be a pointer to an array of "
+ "pCreateInfo->queueFamilyIndexCount uint32_t values");
+ }
+
+ // Ensure that the queue family indices were specified at device creation
+ skip_call |= validate_queue_family_indices(device_data, "vkCreateBuffer", "pCreateInfo->pQueueFamilyIndices",
+ pCreateInfo->queueFamilyIndexCount, pCreateInfo->pQueueFamilyIndices);
+ }
+ }
+
+ if (!skip_call) {
result = get_dispatch_table(pc_device_table_map, device)->CreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
- validate_result(my_data->report_data, "vkCreateBuffer", result);
+ validate_result(report_data, "vkCreateBuffer", result);
}
return result;
@@ -2366,20 +2396,31 @@
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skip_call = false;
layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(device_data != NULL);
+ assert(device_data != nullptr);
debug_report_data *report_data = device_data->report_data;
skip_call |= parameter_validation_vkCreateImage(report_data, pCreateInfo, pAllocator, pImage);
if (pCreateInfo != nullptr) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
- // pQueueFamilyIndices must not be NULL
- skip_call |= validate_required_pointer(report_data, "vkCreateImage", "pCreateInfo->pQueueFamilyIndices",
- pCreateInfo->pQueueFamilyIndices);
+ // If sharingMode is VK_SHARING_MODE_CONCURRENT, queueFamilyIndexCount must be greater than 1
+ if (pCreateInfo->queueFamilyIndexCount <= 1) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
+ INVALID_USAGE, LayerName, "vkCreateImage: if pCreateInfo->sharingMode is VK_SHARING_MODE_CONCURRENT, "
+ "pCreateInfo->queueFamilyIndexCount must be greater than 1");
+ }
- // queueFamilyIndexCount must be greater than 1
- skip_call |= ValidateGreaterThan(report_data, "vkCreateImage", "pCreateInfo->pQueueFamilyIndices",
- pCreateInfo->queueFamilyIndexCount, 1u);
+ // If sharingMode is VK_SHARING_MODE_CONCURRENT, pQueueFamilyIndices must be a pointer to an array of
+ // queueFamilyIndexCount uint32_t values
+ if (pCreateInfo->pQueueFamilyIndices == nullptr) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkCreateImage: if pCreateInfo->sharingMode is VK_SHARING_MODE_CONCURRENT, "
+ "pCreateInfo->pQueueFamilyIndices must be a pointer to an array of "
+ "pCreateInfo->queueFamilyIndexCount uint32_t values");
+ }
skip_call |= validate_queue_family_indices(device_data, "vkCreateImage", "pCreateInfo->pQueueFamilyIndices",
pCreateInfo->queueFamilyIndexCount, pCreateInfo->pQueueFamilyIndices);
@@ -2730,20 +2771,185 @@
const VkGraphicsPipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
VkPipeline *pPipelines) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(my_data != NULL);
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ assert(device_data != nullptr);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkCreateGraphicsPipelines(my_data->report_data, pipelineCache, createInfoCount, pCreateInfos,
- pAllocator, pPipelines);
+ skip_call |= parameter_validation_vkCreateGraphicsPipelines(report_data, pipelineCache, createInfoCount, pCreateInfos,
+ pAllocator, pPipelines);
- if (!skipCall) {
+ if (pCreateInfos != nullptr) {
+ for (uint32_t i = 0; i < createInfoCount; ++i) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ if (pCreateInfos[i].pTessellationState == nullptr) {
+ if (pCreateInfos[i].pStages != nullptr) {
+ // If pStages includes a tessellation control shader stage and a tessellation evaluation shader stage,
+ // pTessellationState must not be NULL
+ bool has_control = false;
+ bool has_eval = false;
+
+ for (uint32_t stage_index = 0; stage_index < pCreateInfos[i].stageCount; ++stage_index) {
+ if (pCreateInfos[i].pStages[stage_index].stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) {
+ has_control = true;
+ } else if (pCreateInfos[i].pStages[stage_index].stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) {
+ has_eval = true;
+ }
+ }
+
+ if (has_control && has_eval) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkCreateGraphicsPipelines: if pCreateInfos[%d].pStages includes a tessellation "
+ "control shader stage and a tessellation evaluation shader stage, "
+ "pCreateInfos[%d].pTessellationState must not be NULL",
+ i, i);
+ }
+ }
+ } else if (pCreateInfos[i].pTessellationState->sType != VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, INVALID_STRUCT_STYPE, LayerName,
+ "vkCreateGraphicsPipelines: parameter pCreateInfos[%d].pTessellationState->sType must be "
+ "VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO",
+ i);
+ }
+
+ if (pCreateInfos[i].pViewportState == nullptr) {
+ // If the rasterizerDiscardEnable member of pRasterizationState is VK_FALSE, pViewportState must be a pointer to a
+ // valid VkPipelineViewportStateCreateInfo structure
+ if ((pCreateInfos[i].pRasterizationState != nullptr) &&
+ (pCreateInfos[i].pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) {
+ skip_call |= log_msg(
+ report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
+ REQUIRED_PARAMETER, LayerName,
+ "vkCreateGraphicsPipelines: if pCreateInfos[%d].pRasterizationState->rasterizerDiscardEnable is VK_FALSE, "
+ "pCreateInfos[%d].pViewportState must be a pointer to a valid VkPipelineViewportStateCreateInfo structure",
+ i, i);
+ }
+ } else {
+ if (pCreateInfos[i].pViewportState->sType != VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, INVALID_STRUCT_STYPE, LayerName,
+ "vkCreateGraphicsPipelines: parameter pCreateInfos[%d].pViewportState->sType must be "
+ "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO",
+ i);
+ }
+
+ if (pCreateInfos[i].pDynamicState != nullptr) {
+ bool has_dynamic_viewport = false;
+ bool has_dynamic_scissor = false;
+
+ for (uint32_t state_index = 0; state_index < pCreateInfos[i].pDynamicState->dynamicStateCount; ++state_index) {
+ if (pCreateInfos[i].pDynamicState->pDynamicStates[state_index] == VK_DYNAMIC_STATE_VIEWPORT) {
+ has_dynamic_viewport = true;
+ } else if (pCreateInfos[i].pDynamicState->pDynamicStates[state_index] == VK_DYNAMIC_STATE_SCISSOR) {
+ has_dynamic_scissor = true;
+ }
+ }
+
+ // viewportCount must be greater than 0
+ // TODO: viewportCount must be 1 when multiple_viewport feature is not enabled
+ if (pCreateInfos[i].pViewportState->viewportCount == 0) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkCreateGraphicsPipelines: if pCreateInfos[%d].pDynamicState->pDynamicStates "
+ "contains VK_DYNAMIC_STATE_VIEWPORT, pCreateInfos[%d].pViewportState->viewportCount "
+ "must be greater than 0",
+ i, i);
+ }
+
+ // If no element of the pDynamicStates member of pDynamicState is VK_DYNAMIC_STATE_VIEWPORT, the pViewports
+ // member of pViewportState must be a pointer to an array of pViewportState->viewportCount VkViewport structures
+ if (!has_dynamic_viewport && (pCreateInfos[i].pViewportState->pViewports == nullptr)) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkCreateGraphicsPipelines: if pCreateInfos[%d].pDynamicState->pDynamicStates contains "
+ "VK_DYNAMIC_STATE_VIEWPORT, pCreateInfos[%d].pViewportState->pViewports must not be NULL",
+ i, i);
+ }
+
+ // scissorCount must be greater than 0
+ // TODO: scissorCount must be 1 when multiple_viewport feature is not enabled
+ if (pCreateInfos[i].pViewportState->scissorCount == 0) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkCreateGraphicsPipelines: if pCreateInfos[%d].pDynamicState->pDynamicStates "
+ "contains VK_DYNAMIC_STATE_SCISSOR, pCreateInfos[%d].pViewportState->scissorCount "
+ "must be greater than 0",
+ i, i);
+ }
+
+ // If no element of the pDynamicStates member of pDynamicState is VK_DYNAMIC_STATE_SCISSOR, the pScissors member
+ // of pViewportState must be a pointer to an array of pViewportState->scissorCount VkRect2D structures
+ if (!has_dynamic_scissor && (pCreateInfos[i].pViewportState->pScissors == nullptr)) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkCreateGraphicsPipelines: if pCreateInfos[%d].pDynamicState->pDynamicStates contains "
+ "VK_DYNAMIC_STATE_SCISSOR, pCreateInfos[%d].pViewportState->pScissors must not be NULL",
+ i, i);
+ }
+ }
+ }
+
+ if (pCreateInfos[i].pMultisampleState == nullptr) {
+ // If the rasterizerDiscardEnable member of pRasterizationState is VK_FALSE, pMultisampleState must be a pointer to
+ // a valid VkPipelineMultisampleStateCreateInfo structure
+ if ((pCreateInfos[i].pRasterizationState != nullptr) &&
+ pCreateInfos[i].pRasterizationState->rasterizerDiscardEnable == VK_FALSE) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
+ REQUIRED_PARAMETER, LayerName, "vkCreateGraphicsPipelines: if "
+ "pCreateInfos[%d].pRasterizationState->rasterizerDiscardEnable is "
+ "VK_FALSE, pCreateInfos[%d].pMultisampleState must not be NULL",
+ i, i);
+ }
+ } else if (pCreateInfos[i].pMultisampleState->sType != VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, INVALID_STRUCT_STYPE, LayerName,
+ "vkCreateGraphicsPipelines: parameter pCreateInfos[%d].pMultisampleState->sType must be "
+ "VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO",
+ i);
+ }
+
+ // TODO: Conditional NULL check based on rasterizerDiscardEnable and subpass
+ if ((pCreateInfos[i].pDepthStencilState != nullptr) &&
+ (pCreateInfos[i].pDepthStencilState->sType != VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO)) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, INVALID_STRUCT_STYPE, LayerName,
+ "vkCreateGraphicsPipelines: parameter pCreateInfos[%d].pDepthStencilState->sType must be "
+ "VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO",
+ i);
+ }
+
+ // TODO: Conditional NULL check based on rasterizerDiscardEnable and subpass
+ if (pCreateInfos[i].pColorBlendState != nullptr) {
+ if (pCreateInfos[i].pColorBlendState->sType != VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, INVALID_STRUCT_STYPE, LayerName,
+ "vkCreateGraphicsPipelines: parameter pCreateInfos[%d].pColorBlendState->sType must be "
+ "VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO",
+ i);
+ }
+
+ // If logicOpEnable is VK_TRUE, logicOp must be a valid VkLogicOp value
+ if (pCreateInfos[i].pColorBlendState->logicOpEnable == VK_TRUE) {
+ skip_call |= validate_ranged_enum(
+ report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pColorBlendState->logicOp", "VkLogicOp",
+ VK_LOGIC_OP_BEGIN_RANGE, VK_LOGIC_OP_END_RANGE, pCreateInfos[i].pColorBlendState->logicOp);
+ }
+ }
+ }
+ }
+
+ if (!skip_call) {
PreCreateGraphicsPipelines(device, pCreateInfos);
result = get_dispatch_table(pc_device_table_map, device)
->CreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
- validate_result(my_data->report_data, "vkCreateGraphicsPipelines", result);
+ validate_result(report_data, "vkCreateGraphicsPipelines", result);
}
return result;
@@ -2834,16 +3040,35 @@
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(my_data != NULL);
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ assert(device_data != NULL);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkCreateSampler(my_data->report_data, pCreateInfo, pAllocator, pSampler);
+ skip_call |= parameter_validation_vkCreateSampler(report_data, pCreateInfo, pAllocator, pSampler);
- if (!skipCall) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ if (pCreateInfo != nullptr) {
+ // If compareEnable is VK_TRUE, compareOp must be a valid VkCompareOp value
+ if (pCreateInfo->compareEnable == VK_TRUE) {
+ skip_call |= validate_ranged_enum(report_data, "vkCreateSampler", "pCreateInfo->compareOp", "VkCompareOp",
+ VK_COMPARE_OP_BEGIN_RANGE, VK_COMPARE_OP_END_RANGE, pCreateInfo->compareOp);
+ }
+
+ // If any of addressModeU, addressModeV or addressModeW are VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, borderColor must be a
+ // valid VkBorderColor value
+ if ((pCreateInfo->addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) ||
+ (pCreateInfo->addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) ||
+ (pCreateInfo->addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)) {
+ skip_call |= validate_ranged_enum(report_data, "vkCreateSampler", "pCreateInfo->borderColor", "VkBorderColor",
+ VK_BORDER_COLOR_BEGIN_RANGE, VK_BORDER_COLOR_END_RANGE, pCreateInfo->borderColor);
+ }
+ }
+
+ if (!skip_call) {
result = get_dispatch_table(pc_device_table_map, device)->CreateSampler(device, pCreateInfo, pAllocator, pSampler);
- validate_result(my_data->report_data, "vkCreateSampler", result);
+ validate_result(report_data, "vkCreateSampler", result);
}
return result;
@@ -2866,17 +3091,55 @@
vkCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkDescriptorSetLayout *pSetLayout) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(my_data != NULL);
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ assert(device_data != nullptr);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkCreateDescriptorSetLayout(my_data->report_data, pCreateInfo, pAllocator, pSetLayout);
+ skip_call |= parameter_validation_vkCreateDescriptorSetLayout(report_data, pCreateInfo, pAllocator, pSetLayout);
- if (!skipCall) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ if ((pCreateInfo != nullptr) && (pCreateInfo->pBindings != nullptr)) {
+ for (uint32_t i = 0; i < pCreateInfo->bindingCount; ++i) {
+ if (pCreateInfo->pBindings[i].descriptorCount != 0) {
+ // If descriptorType is VK_DESCRIPTOR_TYPE_SAMPLER or VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, and descriptorCount
+ // is not 0 and pImmutableSamplers is not NULL, pImmutableSamplers must be a pointer to an array of descriptorCount
+ // valid VkSampler handles
+ if (((pCreateInfo->pBindings[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) ||
+ (pCreateInfo->pBindings[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)) &&
+ (pCreateInfo->pBindings[i].pImmutableSamplers != nullptr)) {
+ for (uint32_t descriptor_index = 0; descriptor_index < pCreateInfo->pBindings[i].descriptorCount;
+ ++descriptor_index) {
+ if (pCreateInfo->pBindings[i].pImmutableSamplers[descriptor_index] == VK_NULL_HANDLE) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName, "vkCreateDescriptorSetLayout: required parameter "
+ "pCreateInfo->pBindings[%d].pImmutableSamplers[%d]"
+ " specified as VK_NULL_HANDLE",
+ i, descriptor_index);
+ }
+ }
+ }
+
+ // If descriptorCount is not 0, stageFlags must be a valid combination of VkShaderStageFlagBits values
+ if ((pCreateInfo->pBindings[i].stageFlags != 0) &&
+ ((pCreateInfo->pBindings[i].stageFlags & (~AllVkShaderStageFlagBits)) != 0)) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
+ UNRECOGNIZED_VALUE, LayerName,
+ "vkCreateDescriptorSetLayout: if pCreateInfo->pBindings[%d].descriptorCount is not 0, "
+ "pCreateInfo->pBindings[%d].stageFlags must be a valid combination of VkShaderStageFlagBits values",
+ i, i);
+ }
+ }
+ }
+ }
+
+ if (!skip_call) {
result =
get_dispatch_table(pc_device_table_map, device)->CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout);
- validate_result(my_data->report_data, "vkCreateDescriptorSetLayout", result);
+ validate_result(report_data, "vkCreateDescriptorSetLayout", result);
}
return result;
@@ -2970,17 +3233,24 @@
uint32_t descriptorSetCount,
const VkDescriptorSet *pDescriptorSets) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(my_data != NULL);
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ assert(device_data != nullptr);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkFreeDescriptorSets(my_data->report_data, descriptorPool, descriptorSetCount, pDescriptorSets);
+ skip_call |= parameter_validation_vkFreeDescriptorSets(report_data, descriptorPool, descriptorSetCount, pDescriptorSets);
- if (!skipCall) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ // This is an array of handles, where the elements are allowed to be VK_NULL_HANDLE, and does not require any validation beyond
+ // validate_array()
+ skip_call |= validate_array(report_data, "vkFreeDescriptorSets", "descriptorSetCount", "pDescriptorSets", descriptorSetCount,
+ pDescriptorSets, true, true);
+
+ if (!skip_call) {
result = get_dispatch_table(pc_device_table_map, device)
->FreeDescriptorSets(device, descriptorPool, descriptorSetCount, pDescriptorSets);
- validate_result(my_data->report_data, "vkFreeDescriptorSets", result);
+ validate_result(report_data, "vkFreeDescriptorSets", result);
}
return result;
@@ -2989,14 +3259,96 @@
VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
vkUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites,
uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies) {
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(my_data != NULL);
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ assert(device_data != NULL);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkUpdateDescriptorSets(my_data->report_data, descriptorWriteCount, pDescriptorWrites,
- descriptorCopyCount, pDescriptorCopies);
+ skip_call |= parameter_validation_vkUpdateDescriptorSets(report_data, descriptorWriteCount, pDescriptorWrites,
+ descriptorCopyCount, pDescriptorCopies);
- if (!skipCall) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ if (pDescriptorWrites != NULL) {
+ for (uint32_t i = 0; i < descriptorWriteCount; ++i) {
+ // descriptorCount must be greater than 0
+ if (pDescriptorWrites[i].descriptorCount == 0) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
+ REQUIRED_PARAMETER, LayerName,
+ "vkUpdateDescriptorSets: parameter pDescriptorWrites[%d].descriptorCount must be greater than 0", i);
+ }
+
+ if ((pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) ||
+ (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||
+ (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
+ (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ||
+ (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
+ // If descriptorType is VK_DESCRIPTOR_TYPE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ // VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE or VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
+ // pImageInfo must be a pointer to an array of descriptorCount valid VkDescriptorImageInfo structures
+ if (pDescriptorWrites[i].pImageInfo == nullptr) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkUpdateDescriptorSets: if pDescriptorWrites[%d].descriptorType is "
+ "VK_DESCRIPTOR_TYPE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "
+ "VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE or "
+ "VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, pDescriptorWrites[%d].pImageInfo must not be NULL",
+ i, i);
+ } else if (pDescriptorWrites[i].descriptorType != VK_DESCRIPTOR_TYPE_SAMPLER) {
+ // If descriptorType is VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
+ // VK_DESCRIPTOR_TYPE_STORAGE_IMAGE or VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, the imageView and imageLayout
+ // members of any given element of pImageInfo must be a valid VkImageView and VkImageLayout, respectively
+ for (uint32_t descriptor_index = 0; descriptor_index < pDescriptorWrites[i].descriptorCount;
+ ++descriptor_index) {
+ skip_call |= validate_required_handle(report_data, "vkUpdateDescriptorSets",
+ "pDescriptorWrites[i].pImageInfo[i].imageView",
+ pDescriptorWrites[i].pImageInfo[descriptor_index].imageView);
+ skip_call |= validate_ranged_enum(report_data, "vkUpdateDescriptorSets",
+ "pDescriptorWrites[i].pImageInfo[i].imageLayout", "VkImageLayout",
+ VK_IMAGE_LAYOUT_BEGIN_RANGE, VK_IMAGE_LAYOUT_END_RANGE,
+ pDescriptorWrites[i].pImageInfo[descriptor_index].imageLayout);
+ }
+ }
+ } else if ((pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
+ (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||
+ (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
+ (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
+ // If descriptorType is VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+ // VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, pBufferInfo must be a
+ // pointer to an array of descriptorCount valid VkDescriptorBufferInfo structures
+ if (pDescriptorWrites[i].pBufferInfo == nullptr) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkUpdateDescriptorSets: if pDescriptorWrites[%d].descriptorType is "
+ "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, "
+ "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, "
+ "pDescriptorWrites[%d].pBufferInfo must not be NULL",
+ i, i);
+ }
+ } else if ((pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ||
+ (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)) {
+ // If descriptorType is VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER or VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
+ // pTexelBufferView must be a pointer to an array of descriptorCount valid VkBufferView handles
+ if (pDescriptorWrites[i].pTexelBufferView == nullptr) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkUpdateDescriptorSets: if pDescriptorWrites[%d].descriptorType is "
+ "VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER or VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, "
+ "pDescriptorWrites[%d].pTexelBufferView must not be NULL",
+ i, i);
+ } else {
+ for (uint32_t descriptor_index = 0; descriptor_index < pDescriptorWrites[i].descriptorCount;
+ ++descriptor_index) {
+ skip_call |= validate_required_handle(report_data, "vkUpdateDescriptorSets",
+ "pDescriptorWrites[i].pTexelBufferView[i]",
+ pDescriptorWrites[i].pTexelBufferView[descriptor_index]);
+ }
+ }
+ }
+ }
+ }
+
+ if (!skip_call) {
get_dispatch_table(pc_device_table_map, device)
->UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
}
@@ -3153,13 +3505,20 @@
VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool,
uint32_t commandBufferCount,
const VkCommandBuffer *pCommandBuffers) {
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(my_data != NULL);
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ assert(device_data != nullptr);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkFreeCommandBuffers(my_data->report_data, commandPool, commandBufferCount, pCommandBuffers);
+ skip_call |= parameter_validation_vkFreeCommandBuffers(report_data, commandPool, commandBufferCount, pCommandBuffers);
- if (!skipCall) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ // This is an array of handles, where the elements are allowed to be VK_NULL_HANDLE, and does not require any validation beyond
+ // validate_array()
+ skip_call |= validate_array(report_data, "vkFreeCommandBuffers", "commandBufferCount", "pCommandBuffers", commandBufferCount,
+ pCommandBuffers, true, true);
+
+ if (!skip_call) {
get_dispatch_table(pc_device_table_map, device)
->FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers);
}
@@ -3168,16 +3527,34 @@
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
- assert(my_data != NULL);
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
+ assert(device_data != nullptr);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkBeginCommandBuffer(my_data->report_data, pBeginInfo);
+ skip_call |= parameter_validation_vkBeginCommandBuffer(report_data, pBeginInfo);
- if (!skipCall) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ // TODO: pBeginInfo->pInheritanceInfo must not be NULL if commandBuffer is a secondary command buffer
+ skip_call |= validate_struct_type(report_data, "vkBeginCommandBuffer", "pBeginInfo->pInheritanceInfo",
+ "VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO", pBeginInfo->pInheritanceInfo,
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, false);
+
+ if (pBeginInfo->pInheritanceInfo != NULL) {
+ // TODO: This only needs to be validated when the inherited queries feature is enabled
+ // skip_call |= validate_flags(report_data, "vkBeginCommandBuffer", "pBeginInfo->pInheritanceInfo->queryFlags",
+ // "VkQueryControlFlagBits", AllVkQueryControlFlagBits, pBeginInfo->pInheritanceInfo->queryFlags, false);
+
+ // TODO: This must be 0 if the pipeline statistics queries feature is not enabled
+ skip_call |= validate_flags(report_data, "vkBeginCommandBuffer", "pBeginInfo->pInheritanceInfo->pipelineStatistics",
+ "VkQueryPipelineStatisticFlagBits", AllVkQueryPipelineStatisticFlagBits,
+ pBeginInfo->pInheritanceInfo->pipelineStatistics, false);
+ }
+
+ if (!skip_call) {
result = get_dispatch_table(pc_device_table_map, commandBuffer)->BeginCommandBuffer(commandBuffer, pBeginInfo);
- validate_result(my_data->report_data, "vkBeginCommandBuffer", result);
+ validate_result(report_data, "vkBeginCommandBuffer", result);
}
return result;