sync: False positive on host reset event
Environment:
- OS: Windows 10
- GPU and driver version: Reproduced on AMD Radeon RX 5700XT and Nvidia GeForce RTX 2080 (driver 536.23)
- SDK or header version if building from repo: Tried with SDK 1.3.280.0 and built from source (02a12a0ad15ddfd78cad7683707e1b6ce14161b2)
- Options enabled (synchronization, best practices, etc.): Synchronization (with QueueSubmit Synchronization Validation)
Describe the Issue
When executing the following Vulkan code:
C++
// Set and wait for an event.
VkCommandBuffer cmd1 = CreateCommandBuffer();
vkCmdSetEvent(cmd1, event, VK_PIPELINE_STAGE_TRANSFER_BIT);
vkCmdWaitEvents(cmd1, 1, &event, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, nullptr, 0, nullptr, 0, nullptr);
FinishAndSubmit(cmd1);
vkDeviceWaitIdle(device);
// Set and wait for the same event using different pipeline stages.
VkCommandBuffer cmd2 = CreateCommandBuffer();
vkCmdSetEvent(cmd2, event, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT);
vkCmdWaitEvents(cmd2, 1, &event, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, nullptr, 0, nullptr, 0, nullptr);
FinishAndSubmit(cmd2);
vkDeviceWaitIdle(device);
I (correctly) get the following validation error:
Validation error
VUID-vkCmdWaitEvents-srcStageMask-01158(ERROR / SPEC): msgNum: -220967945 - Validation Error: [ VUID-vkCmdWaitEvents-srcStageMask-01158 ] Object 0: handle = 0x74d977000000004a, type = VK_OBJECT_TYPE_EVENT; | MessageID = 0xf2d44bf7 | vkCmdWaitEvents(): VkEvent 0x74d977000000004a[] stageMask 1000 includes bits not present in srcStageMask 0xc. Bits missing from srcStageMask VK_PIPELINE_STAGE_TRANSFER_BIT. Wait operation is ignored for this event. The Vulkan spec states: srcStageMask must be the bitwise OR of the stageMask parameter used in previous calls to vkCmdSetEvent with any of the elements of pEvents and VK_PIPELINE_STAGE_HOST_BIT if any of the elements of pEvents was set using vkSetEvent (https://vulkan.lunarg.com/doc/view/1.3.275.0/windows/1.3-extensions/vkspec.html#VUID-vkCmdWaitEvents-srcStageMask-01158)
Objects: 1
[0] 0x74d977000000004a, type: 11, name: NULL
VUID-vkCmdWaitEvents-srcStageMask-01158(ERROR / SPEC): msgNum: -220967945 - Validation Error: [ VUID-vkCmdWaitEvents-srcStageMask-01158 ] Object 0: handle = 0x22c06957890, type = VK_OBJECT_TYPE_QUEUE; | MessageID = 0xf2d44bf7 | vkCmdWaitEvents(): srcStageMask 0xc contains stages not present in pEvents stageMask. Extra stages are VK_PIPELINE_STAGE_VERTEX_INPUT_BIT|VK_PIPELINE_STAGE_VERTEX_SHADER_BIT. The Vulkan spec states: srcStageMask must be the bitwise OR of the stageMask parameter used in previous calls to vkCmdSetEvent with any of the elements of pEvents and VK_PIPELINE_STAGE_HOST_BIT if any of the elements of pEvents was set using vkSetEvent (https://vulkan.lunarg.com/doc/view/1.3.275.0/windows/1.3-extensions/vkspec.html#VUID-vkCmdWaitEvents-srcStageMask-01158)
Objects: 1
[0] 0x22c06957890, type: 4, name: NULL
Resetting the event in between the two command buffers (correctly) makes the validation error go away.
C++
// Set and wait for an event.
VkCommandBuffer cmd1 = CreateCommandBuffer();
vkCmdSetEvent(cmd1, event, VK_PIPELINE_STAGE_TRANSFER_BIT);
vkCmdWaitEvents(cmd1, 1, &event, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, nullptr, 0, nullptr, 0, nullptr);
FinishAndSubmit(cmd1);
vkDeviceWaitIdle(device);
// Reset the event.
VkCommandBuffer cmd2 = CreateCommandBuffer();
vkCmdResetEvent(cmd2, event, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
FinishAndSubmit(cmd2);
vkDeviceWaitIdle(device);
// Set and wait for the same event using different pipeline stages.
VkCommandBuffer cmd3 = CreateCommandBuffer();
vkCmdSetEvent(cmd3, event, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT);
vkCmdWaitEvents(cmd3, 1, &event, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, nullptr, 0, nullptr, 0, nullptr);
FinishAndSubmit(cmd3);
vkDeviceWaitIdle(device);
However, this only happens if I reset the event on the device. Using a host reset, the validation error persists:
C++
// Set and wait for an event.
VkCommandBuffer cmd1 = CreateCommandBuffer();
vkCmdSetEvent(cmd1, event, VK_PIPELINE_STAGE_TRANSFER_BIT);
vkCmdWaitEvents(cmd1, 1, &event, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, nullptr, 0, nullptr, 0, nullptr);
FinishAndSubmit(cmd1);
vkDeviceWaitIdle(device);
// Reset on host.
vkResetEvent(device, event);
// Set and wait for the same event using different pipeline stages.
VkCommandBuffer cmd2 = CreateCommandBuffer();
vkCmdSetEvent(cmd2, event, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT);
vkCmdWaitEvents(cmd2, 1, &event, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, nullptr, 0, nullptr, 0, nullptr);
FinishAndSubmit(cmd2);
vkDeviceWaitIdle(device);
Expected behavior
Resetting the event on device or on host should have the same effect (as long as host-device synchronization is taken care of (in this case using vkDeviceWaitIdle)).
Valid Usage ID VUID-vkCmdWaitEvents-srcStageMask-01158
TODO: Currently VUID-vkCmdWaitEvents-srcStageMask-01158 is not covered by the tests. Add the tests as part of the fix. Also it is not clear why the validation is implemented in syncval. Another task might be to move this to core.