tests: Prevent new unexpected errors
Add a filter to the error monitor and require explicit function for
unexpected errors. This helps developers easily detect when they
inadvertently add an unexpected error.
Change-Id: I652951fb135795770b06b6805155cd5e4a0e0c62
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp
index 1f7ae7a..1033228 100644
--- a/tests/layer_validation_tests.cpp
+++ b/tests/layer_validation_tests.cpp
@@ -36,6 +36,8 @@
#include "vk_layer_config.h"
#include "vk_validation_error_messages.h"
#include "vkrenderframework.h"
+
+#include <algorithm>
#include <limits.h>
#include <unordered_set>
@@ -130,6 +132,7 @@
failure_message_strings_.clear();
desired_message_strings_.clear();
desired_message_ids_.clear();
+ ignore_message_strings_.clear();
other_messages_.clear();
message_outstanding_count_ = 0;
}
@@ -160,6 +163,17 @@
test_platform_thread_unlock_mutex(&mutex_);
}
+ // Set an error that the error monitor will ignore. Do not use this function if you are creating a new test.
+ // TODO: This is stopgap to block new unexpected errors from being introduced. The long-term goal is to remove the use of this
+ // function and its definition.
+ void SetUnexpectedError(const char *const msg) {
+ test_platform_thread_lock_mutex(&mutex_);
+
+ ignore_message_strings_.emplace_back(msg);
+
+ test_platform_thread_unlock_mutex(&mutex_);
+ }
+
VkBool32 CheckForDesiredMsg(const uint32_t message_code, const char *const msgString) {
VkBool32 result = VK_FALSE;
test_platform_thread_lock_mutex(&mutex_);
@@ -169,53 +183,56 @@
string errorString(msgString);
bool found_expected = false;
- for (auto desired_msg : desired_message_strings_) {
- if (desired_msg.length() == 0) {
- // An empty desired_msg string "" indicates a positive test - not expecting an error.
- // Return true to avoid calling layers/driver with this error.
- // And don't erase the "" string, so it remains if another error is found.
- result = VK_TRUE;
- found_expected = true;
- message_found_ = VK_TRUE;
- failure_message_strings_.insert(errorString);
- } else if (errorString.find(desired_msg) != string::npos) {
- found_expected = true;
- message_outstanding_count_--;
- failure_message_strings_.insert(errorString);
- message_found_ = VK_TRUE;
- result = VK_TRUE;
- // We only want one match for each expected error so remove from set here
- // Since we're about the break the loop it's ok to remove from set we're iterating over
- desired_message_strings_.erase(desired_msg);
- break;
- }
- }
- for (auto desired_id : desired_message_ids_) {
- if (desired_id == VALIDATION_ERROR_MAX_ENUM) {
- // A message ID set to MAX_ENUM indicates a positive test - not expecting an error.
- // Return true to avoid calling layers/driver with this error.
- result = VK_TRUE;
- } else if (desired_id == message_code) {
- // Double-check that the string matches the error enum
- if (errorString.find(validation_error_map[desired_id]) != string::npos) {
+ if (!IgnoreMessage(errorString)) {
+ for (auto desired_msg : desired_message_strings_) {
+ if (desired_msg.length() == 0) {
+ // An empty desired_msg string "" indicates a positive test - not expecting an error.
+ // Return true to avoid calling layers/driver with this error.
+ // And don't erase the "" string, so it remains if another error is found.
+ result = VK_TRUE;
+ found_expected = true;
+ message_found_ = VK_TRUE;
+ failure_message_strings_.insert(errorString);
+ } else if (errorString.find(desired_msg) != string::npos) {
found_expected = true;
message_outstanding_count_--;
- result = VK_TRUE;
+ failure_message_strings_.insert(errorString);
message_found_ = VK_TRUE;
- desired_message_ids_.erase(desired_id);
+ result = VK_TRUE;
+ // We only want one match for each expected error so remove from set here
+ // Since we're about the break the loop it's ok to remove from set we're iterating over
+ desired_message_strings_.erase(desired_msg);
break;
- } else {
- // Treat this message as a regular unexpected error, but print a warning jic
- printf("Message (%s) from MessageID %d does not correspond to expected message from error Database (%s)\n",
- errorString.c_str(), desired_id, validation_error_map[desired_id]);
}
}
+ for (auto desired_id : desired_message_ids_) {
+ if (desired_id == VALIDATION_ERROR_MAX_ENUM) {
+ // A message ID set to MAX_ENUM indicates a positive test - not expecting an error.
+ // Return true to avoid calling layers/driver with this error.
+ result = VK_TRUE;
+ } else if (desired_id == message_code) {
+ // Double-check that the string matches the error enum
+ if (errorString.find(validation_error_map[desired_id]) != string::npos) {
+ found_expected = true;
+ message_outstanding_count_--;
+ result = VK_TRUE;
+ message_found_ = VK_TRUE;
+ desired_message_ids_.erase(desired_id);
+ break;
+ } else {
+ // Treat this message as a regular unexpected error, but print a warning jic
+ printf("Message (%s) from MessageID %d does not correspond to expected message from error Database (%s)\n",
+ errorString.c_str(), desired_id, validation_error_map[desired_id]);
+ }
+ }
+ }
+
+ if (!found_expected) {
+ printf("Unexpected: %s\n", msgString);
+ other_messages_.push_back(errorString);
+ }
}
- if (!found_expected) {
- printf("Unexpected: %s\n", msgString);
- other_messages_.push_back(errorString);
- }
test_platform_thread_unlock_mutex(&mutex_);
return result;
}
@@ -275,10 +292,23 @@
}
private:
+ // TODO: This is stopgap to block new unexpected errors from being introduced. The long-term goal is to remove the use of this
+ // function and its definition.
+ bool IgnoreMessage(std::string const &msg) const {
+ if (ignore_message_strings_.empty()) {
+ return false;
+ }
+
+ return std::find_if(ignore_message_strings_.begin(), ignore_message_strings_.end(), [&msg](std::string const &str) {
+ return msg.find(str) != std::string::npos;
+ }) != ignore_message_strings_.end();
+ }
+
VkFlags message_flags_;
std::unordered_set<uint32_t> desired_message_ids_;
std::unordered_set<string> desired_message_strings_;
std::unordered_set<string> failure_message_strings_;
+ std::vector<std::string> ignore_message_strings_;
vector<string> other_messages_;
test_platform_thread_mutex mutex_;
bool *bailout_;
@@ -2975,6 +3005,7 @@
image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
vk_testing::Image dst_image;
dst_image.init(*m_device, (const VkImageCreateInfo &)image_create_info, reqs);
+ m_errorMonitor->SetUnexpectedError("attempts to implicitly reset cmdBuffer created from command pool");
m_commandBuffer->BeginCommandBuffer();
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
"was created with a sample count "
@@ -2997,6 +3028,7 @@
image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
vk_testing::Image dst_image;
dst_image.init(*m_device, (const VkImageCreateInfo &)image_create_info, reqs);
+ m_errorMonitor->SetUnexpectedError("attempts to implicitly reset cmdBuffer created from command pool");
m_commandBuffer->BeginCommandBuffer();
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
"was created with a sample count "
@@ -3026,6 +3058,9 @@
image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
vk_testing::Image dst_image;
dst_image.init(*m_device, (const VkImageCreateInfo &)image_create_info, reqs);
+ m_errorMonitor->SetUnexpectedError(
+ "If commandBuffer was allocated from a VkCommandPool which did not have the "
+ "VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT flag set, commandBuffer must be in the initial state");
m_commandBuffer->BeginCommandBuffer();
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
"was created with a sample count "
@@ -3046,6 +3081,7 @@
image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
vk_testing::Image src_image;
src_image.init(*m_device, (const VkImageCreateInfo &)image_create_info, reqs);
+ m_errorMonitor->SetUnexpectedError("attempts to implicitly reset cmdBuffer created from command pool");
m_commandBuffer->BeginCommandBuffer();
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
"was created with a sample count "
@@ -3282,6 +3318,7 @@
"queue family.");
ASSERT_NO_FATAL_FAILURE(InitState());
+
// This test is meaningless unless we have multiple queue families
auto queue_family_properties = m_device->phy().queue_properties();
if (queue_family_properties.size() < 2) {
@@ -3944,6 +3981,10 @@
fb_info.height = 100;
fb_info.layers = 1;
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_00413);
+ m_errorMonitor->SetUnexpectedError(
+ "has dimensions smaller than the corresponding framebuffer dimensions. Attachment dimensions must be at least as large. "
+ "Here are the respective dimensions for attachment");
+
err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
m_errorMonitor->VerifyFound();
@@ -3956,6 +3997,9 @@
fb_info.height = m_device->props.limits.maxFramebufferHeight + 1;
fb_info.layers = 1;
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_00414);
+ m_errorMonitor->SetUnexpectedError(
+ "has dimensions smaller than the corresponding framebuffer dimensions. Attachment dimensions must be at least as large. "
+ "Here are the respective dimensions for attachment");
err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
m_errorMonitor->VerifyFound();
@@ -3968,6 +4012,9 @@
fb_info.height = 100;
fb_info.layers = m_device->props.limits.maxFramebufferLayers + 1;
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_00415);
+ m_errorMonitor->SetUnexpectedError(
+ "has dimensions smaller than the corresponding framebuffer dimensions. Attachment dimensions must be at least as large. "
+ "Here are the respective dimensions for attachment");
err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
m_errorMonitor->VerifyFound();
@@ -4587,6 +4634,7 @@
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &m_commandBuffer->handle();
+ m_errorMonitor->SetUnexpectedError("Cannot submit cmd buffer using deleted buffer");
vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
@@ -4823,6 +4871,7 @@
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &m_commandBuffer->handle();
+ m_errorMonitor->SetUnexpectedError("Cannot submit cmd buffer using deleted image");
vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
@@ -4901,6 +4950,7 @@
m_renderPassBeginInfo.framebuffer = fb;
// Create Null cmd buffer for submit
m_commandBuffer->BeginCommandBuffer();
+ m_errorMonitor->SetUnexpectedError("Cannot execute a render pass with renderArea not within the bound of the framebuffer.");
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
m_commandBuffer->EndRenderPass();
m_commandBuffer->EndCommandBuffer();
@@ -4908,6 +4958,7 @@
vkDestroyImage(m_device->device(), image, NULL);
// Now attempt to submit cmd buffer and verify error
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " that is invalid because bound image ");
+ m_errorMonitor->SetUnexpectedError("Cannot submit cmd buffer using deleted image");
QueueCommandBuffer(false);
m_errorMonitor->VerifyFound();
@@ -4954,6 +5005,8 @@
m_errorMonitor->VerifyFound();
// Wait for queue to complete so we can safely destroy everything
vkQueueWaitIdle(m_device->m_queue);
+ m_errorMonitor->SetUnexpectedError("If framebuffer is not VK_NULL_HANDLE, framebuffer must be a valid VkFramebuffer handle");
+ m_errorMonitor->SetUnexpectedError("Unable to remove Framebuffer obj");
vkDestroyFramebuffer(m_device->device(), fb, nullptr);
}
@@ -5040,6 +5093,8 @@
m_errorMonitor->VerifyFound();
// Wait for queue to complete so we can safely destroy image and other objects
vkQueueWaitIdle(m_device->m_queue);
+ m_errorMonitor->SetUnexpectedError("If image is not VK_NULL_HANDLE, image must be a valid VkImage handle");
+ m_errorMonitor->SetUnexpectedError("Unable to remove Image obj");
vkDestroyImage(m_device->device(), image, NULL);
vkDestroyFramebuffer(m_device->device(), fb, nullptr);
vkDestroyImageView(m_device->device(), view, nullptr);
@@ -5138,6 +5193,9 @@
err = vkCreatePipelineCache(m_device->device(), &pc_ci, NULL, &pipe_cache);
ASSERT_VK_SUCCESS(err);
+ m_errorMonitor->SetUnexpectedError(
+ "If pColorBlendState is not NULL, The attachmentCount member of pColorBlendState must be equal to the colorAttachmentCount "
+ "used to create subpass");
err = vkCreateGraphicsPipelines(m_device->device(), pipe_cache, 1, &gp_ci, NULL, &pipeline);
ASSERT_VK_SUCCESS(err);
// Bind pipeline to cmd buffer, will also bind renderpass
@@ -5157,6 +5215,8 @@
// Wait for queue to complete so we can safely destroy everything
vkQueueWaitIdle(m_device->m_queue);
+ m_errorMonitor->SetUnexpectedError("If renderPass is not VK_NULL_HANDLE, renderPass must be a valid VkRenderPass handle");
+ m_errorMonitor->SetUnexpectedError("Unable to remove Render Pass obj");
vkDestroyRenderPass(m_device->device(), rp, nullptr);
vkDestroyPipeline(m_device->device(), pipeline, nullptr);
vkDestroyPipelineCache(m_device->device(), pipe_cache, nullptr);
@@ -5306,6 +5366,7 @@
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &m_commandBuffer->handle();
+ m_errorMonitor->SetUnexpectedError("Cannot submit cmd buffer using deleted event");
vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
@@ -5337,6 +5398,7 @@
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &m_commandBuffer->handle();
+ m_errorMonitor->SetUnexpectedError("Cannot submit cmd buffer using deleted query pool");
vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
@@ -5433,6 +5495,7 @@
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &m_commandBuffer->handle();
+ m_errorMonitor->SetUnexpectedError("Cannot submit cmd buffer using deleted pipeline");
vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
@@ -5595,6 +5658,7 @@
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &m_commandBuffer->handle();
+ m_errorMonitor->SetUnexpectedError("Cannot submit cmd buffer using deleted buffer");
vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
// Cleanup
@@ -5820,6 +5884,7 @@
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &m_commandBuffer->handle();
+ m_errorMonitor->SetUnexpectedError("that is invalid because bound sampler");
vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
@@ -5849,6 +5914,7 @@
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &m_commandBuffer->handle();
+ m_errorMonitor->SetUnexpectedError("Cannot submit cmd buffer using deleted image");
vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
// Now update descriptor to be valid, but then free descriptor
@@ -5874,6 +5940,10 @@
// Try again once the queue is idle - should succeed w/o error
// TODO - though the particular error above doesn't re-occur, there are other 'unexpecteds' still to clean up
vkQueueWaitIdle(m_device->m_queue);
+ m_errorMonitor->SetUnexpectedError(
+ "pDescriptorSets must be a pointer to an array of descriptorSetCount VkDescriptorSet handles, each element of which must "
+ "either be a valid handle or VK_NULL_HANDLE");
+ m_errorMonitor->SetUnexpectedError("Unable to remove Descriptor Set obj");
vkFreeDescriptorSets(m_device->device(), ds_pool, 1, &descriptorSet);
// Attempt to submit cmd buffer containing the freed descriptor set
@@ -5882,6 +5952,7 @@
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &m_commandBuffer->handle();
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " that is invalid because bound descriptor set ");
+ m_errorMonitor->SetUnexpectedError("Cannot submit cmd buffer using deleted descriptor set");
vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
@@ -6052,6 +6123,9 @@
vkDestroySampler(m_device->device(), sampler, NULL);
vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);
vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
+ m_errorMonitor->SetUnexpectedError(
+ "If descriptorPool is not VK_NULL_HANDLE, descriptorPool must be a valid VkDescriptorPool handle");
+ m_errorMonitor->SetUnexpectedError("Unable to remove Descriptor Pool obj");
vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL);
// TODO : It seems Validation layers think ds_pool was already destroyed, even though it wasn't?
}
@@ -8652,6 +8726,7 @@
const VkImageSubresourceRange range = vk_testing::Image::subresource_range(image_create_info, VK_IMAGE_ASPECT_COLOR_BIT);
+ m_errorMonitor->SetUnexpectedError("image must have been created with VK_IMAGE_USAGE_TRANSFER_DST_BIT usage flag");
vkCmdClearColorImage(m_commandBuffer->GetBufferHandle(), dstImage.handle(), VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &range);
m_errorMonitor->VerifyFound();
@@ -9138,6 +9213,8 @@
// vkCmdBindPipeline(m_commandBuffer->GetBufferHandle(),
// VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
// Should error before calling to driver so don't care about actual data
+ m_errorMonitor->SetUnexpectedError(
+ "If buffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object");
vkCmdBindIndexBuffer(m_commandBuffer->GetBufferHandle(), ib, 7, VK_INDEX_TYPE_UINT16);
m_errorMonitor->VerifyFound();
@@ -9165,6 +9242,8 @@
buffCI.sharingMode = VK_SHARING_MODE_CONCURRENT; // qfi only matters in CONCURRENT mode
VkBuffer ib;
+ m_errorMonitor->SetUnexpectedError(
+ "If sharingMode is VK_SHARING_MODE_CONCURRENT, queueFamilyIndexCount must be greater than 1");
vkCreateBuffer(m_device->device(), &buffCI, NULL, &ib);
m_errorMonitor->VerifyFound();
@@ -9191,6 +9270,8 @@
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "vkCmdExecuteCommands() called w/ Primary Cmd Buffer ");
vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &handle);
m_errorMonitor->VerifyFound();
+
+ m_errorMonitor->SetUnexpectedError("All elements of pCommandBuffers must not be pending execution");
}
TEST_F(VkLayerTest, DSUsageBitsErrors) {
@@ -9530,6 +9611,9 @@
descriptor_write.dstSet = descriptor_set;
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_00959);
+ m_errorMonitor->SetUnexpectedError(
+ "If descriptorType is VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER or VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, the offset member of "
+ "any given element of pBufferInfo must be a multiple of VkPhysicalDeviceLimits::minUniformBufferOffsetAlignment");
vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
m_errorMonitor->VerifyFound();
@@ -9546,12 +9630,17 @@
buff_info.range = 200;
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_00961);
+ m_errorMonitor->SetUnexpectedError(
+ "If descriptorType is VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER or VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, the offset member of "
+ "any given element of pBufferInfo must be a multiple of VkPhysicalDeviceLimits::minUniformBufferOffsetAlignment");
vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
m_errorMonitor->VerifyFound();
vkFreeMemory(m_device->device(), mem, NULL);
vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
vkDestroyBuffer(m_device->device(), buffer, NULL);
+ m_errorMonitor->SetUnexpectedError(
+ "descriptorPool must have been created with the VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT flag");
vkFreeDescriptorSets(m_device->device(), ds_pool, 1, &descriptor_set);
vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL);
}
@@ -9847,6 +9936,8 @@
vkDestroyImage(m_device->device(), image, NULL);
vkFreeMemory(m_device->device(), image_mem, NULL);
vkDestroyImageView(m_device->device(), image_view, NULL);
+ m_errorMonitor->SetUnexpectedError(
+ "descriptorPool must have been created with the VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT flag");
vkFreeDescriptorSets(m_device->device(), ds_pool, 1, &descriptor_set);
vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL);
}
@@ -10008,6 +10099,7 @@
descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptor_write.pBufferInfo = &buff_info;
+ m_errorMonitor->SetUnexpectedError("required parameter pDescriptorWrites");
vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
m_errorMonitor->VerifyFound();
@@ -10974,6 +11066,9 @@
pipe.AddShader(&vs);
pipe.AddShader(&fs);
pipe.SetMSAA(&pipe_ms_state_ci);
+ m_errorMonitor->SetUnexpectedError(
+ "If pColorBlendState is not NULL, The attachmentCount member of pColorBlendState must be equal to the colorAttachmentCount "
+ "used to create subpass");
pipe.CreateVKPipeline(pipeline_layout, renderPass());
m_commandBuffer->BeginCommandBuffer();
@@ -11149,6 +11244,7 @@
device_create_info.queueCreateInfoCount = 1;
device_create_info.pQueueCreateInfos = &queue_create_info;
device_create_info.pEnabledFeatures = &features;
+ m_errorMonitor->SetUnexpectedError("Failed to create device chain.");
vkCreateDevice(gpu(), &device_create_info, nullptr, &testDevice);
m_errorMonitor->VerifyFound();
@@ -11161,6 +11257,10 @@
feature_array[i] = VK_TRUE;
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, unavailable_feature_message);
device_create_info.pEnabledFeatures = &features;
+ m_errorMonitor->SetUnexpectedError(
+ "You requested features that are unavailable on this device. You should first query feature availability by "
+ "calling vkGetPhysicalDeviceFeatures().");
+ m_errorMonitor->SetUnexpectedError("Failed to create device chain.");
vkCreateDevice(gpu(), &device_create_info, nullptr, &testDevice);
m_errorMonitor->VerifyFound();
break;
@@ -11373,9 +11473,13 @@
}
m_errorMonitor->VerifyFound();
+ m_errorMonitor->SetUnexpectedError("value of pCreateInfo->usage must not be 0");
if (VkBufferTest::GetTestConditionValid(m_device, VkBufferTest::eInvalidMemoryOffset)) {
// Create and bind a memory buffer with an invalid offset.
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, invalid_offset_message);
+ m_errorMonitor->SetUnexpectedError(
+ "If buffer was created with the VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT or VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, "
+ "memoryOffset must be a multiple of VkPhysicalDeviceLimits::minTexelBufferOffsetAlignment");
VkBufferTest buffer_test(m_device, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, VkBufferTest::eInvalidMemoryOffset);
(void)buffer_test;
m_errorMonitor->VerifyFound();
@@ -11386,6 +11490,9 @@
// Create and bind a memory buffer with an invalid offset again,
// but look for a texel buffer message.
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, invalid_texel_buffer_offset_message);
+ m_errorMonitor->SetUnexpectedError(
+ "memoryOffset must be an integer multiple of the alignment member of the VkMemoryRequirements structure returned from "
+ "a call to vkGetBufferMemoryRequirements with buffer");
VkBufferTest buffer_test(m_device, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, VkBufferTest::eInvalidDeviceOffset);
(void)buffer_test;
m_errorMonitor->VerifyFound();
@@ -11395,6 +11502,9 @@
// Create and bind a memory buffer with an invalid offset again, but
// look for a uniform buffer message.
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, invalid_uniform_buffer_offset_message);
+ m_errorMonitor->SetUnexpectedError(
+ "memoryOffset must be an integer multiple of the alignment member of the VkMemoryRequirements structure returned from "
+ "a call to vkGetBufferMemoryRequirements with buffer");
VkBufferTest buffer_test(m_device, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VkBufferTest::eInvalidDeviceOffset);
(void)buffer_test;
m_errorMonitor->VerifyFound();
@@ -11404,6 +11514,9 @@
// Create and bind a memory buffer with an invalid offset again, but
// look for a storage buffer message.
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, invalid_storage_buffer_offset_message);
+ m_errorMonitor->SetUnexpectedError(
+ "memoryOffset must be an integer multiple of the alignment member of the VkMemoryRequirements structure returned from "
+ "a call to vkGetBufferMemoryRequirements with buffer");
VkBufferTest buffer_test(m_device, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VkBufferTest::eInvalidDeviceOffset);
(void)buffer_test;
m_errorMonitor->VerifyFound();
@@ -11412,6 +11525,8 @@
{
// Attempt to bind a null buffer.
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_00799);
+ m_errorMonitor->SetUnexpectedError("required parameter memory specified as VK_NULL_HANDLE");
+ m_errorMonitor->SetUnexpectedError("memory must be a valid VkDeviceMemory handle");
VkBufferTest buffer_test(m_device, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VkBufferTest::eBindNullBuffer);
(void)buffer_test;
m_errorMonitor->VerifyFound();
@@ -11534,6 +11649,7 @@
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
"Layout for input image should be TRANSFER_SRC_OPTIMAL instead of GENERAL.");
+ m_errorMonitor->SetUnexpectedError("Layout for output image should be TRANSFER_DST_OPTIMAL instead of GENERAL.");
m_commandBuffer->CopyImage(src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, VK_IMAGE_LAYOUT_GENERAL, 1, ©_region);
m_errorMonitor->VerifyFound();
// Now cause error due to src image layout changing
@@ -11541,17 +11657,23 @@
"Cannot copy from an image whose source layout is "
"VK_IMAGE_LAYOUT_UNDEFINED and doesn't match the current "
"layout VK_IMAGE_LAYOUT_GENERAL.");
+ m_errorMonitor->SetUnexpectedError(
+ "srcImageLayout must be either of VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL");
m_commandBuffer->CopyImage(src_image, VK_IMAGE_LAYOUT_UNDEFINED, dst_image, VK_IMAGE_LAYOUT_GENERAL, 1, ©_region);
m_errorMonitor->VerifyFound();
// Final src error is due to bad layout type
m_errorMonitor->SetDesiredFailureMsg(
VK_DEBUG_REPORT_ERROR_BIT_EXT,
"Layout for input image is VK_IMAGE_LAYOUT_UNDEFINED but can only be TRANSFER_SRC_OPTIMAL or GENERAL.");
+ m_errorMonitor->SetUnexpectedError(
+ "Cannot copy from an image whose source layout is VK_IMAGE_LAYOUT_UNDEFINED and doesn't match the current layout "
+ "VK_IMAGE_LAYOUT_GENERAL.");
m_commandBuffer->CopyImage(src_image, VK_IMAGE_LAYOUT_UNDEFINED, dst_image, VK_IMAGE_LAYOUT_GENERAL, 1, ©_region);
m_errorMonitor->VerifyFound();
// Now verify same checks for dst
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
"Layout for output image should be TRANSFER_DST_OPTIMAL instead of GENERAL.");
+ m_errorMonitor->SetUnexpectedError("Layout for input image should be TRANSFER_SRC_OPTIMAL instead of GENERAL.");
m_commandBuffer->CopyImage(src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, VK_IMAGE_LAYOUT_GENERAL, 1, ©_region);
m_errorMonitor->VerifyFound();
// Now cause error due to src image layout changing
@@ -11559,11 +11681,16 @@
"Cannot copy from an image whose dest layout is "
"VK_IMAGE_LAYOUT_UNDEFINED and doesn't match the current "
"layout VK_IMAGE_LAYOUT_GENERAL.");
+ m_errorMonitor->SetUnexpectedError(
+ "dstImageLayout must be either of VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL");
m_commandBuffer->CopyImage(src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, VK_IMAGE_LAYOUT_UNDEFINED, 1, ©_region);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredFailureMsg(
VK_DEBUG_REPORT_ERROR_BIT_EXT,
"Layout for output image is VK_IMAGE_LAYOUT_UNDEFINED but can only be TRANSFER_DST_OPTIMAL or GENERAL.");
+ m_errorMonitor->SetUnexpectedError(
+ "Cannot copy from an image whose dest layout is VK_IMAGE_LAYOUT_UNDEFINED and doesn't match the current layout "
+ "VK_IMAGE_LAYOUT_GENERAL.");
m_commandBuffer->CopyImage(src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, VK_IMAGE_LAYOUT_UNDEFINED, 1, ©_region);
m_errorMonitor->VerifyFound();
@@ -11877,6 +12004,10 @@
m_errorMonitor->VerifyNotFound();
command_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
+ m_errorMonitor->SetUnexpectedError("commandBuffer must not currently be pending execution");
+ m_errorMonitor->SetUnexpectedError(
+ "If commandBuffer was allocated from a VkCommandPool which did not have the "
+ "VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT flag set, commandBuffer must be in the initial state");
vkBeginCommandBuffer(m_commandBuffer->handle(), &command_buffer_begin_info);
vkCmdBeginRenderPass(m_commandBuffer->handle(), &renderPassBeginInfo(), VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
@@ -11887,6 +12018,8 @@
vkEndCommandBuffer(m_commandBuffer->handle());
vkQueueWaitIdle(m_device->m_queue);
+
+ m_errorMonitor->SetUnexpectedError("All elements of pCommandBuffers must not be pending execution");
}
TEST_F(VkLayerTest, SimultaneousUseOneShot) {
@@ -12134,8 +12267,14 @@
m_errorMonitor->VerifyFound();
vkQueueWaitIdle(m_device->m_queue);
+ m_errorMonitor->SetUnexpectedError("If semaphore is not VK_NULL_HANDLE, semaphore must be a valid VkSemaphore handle");
+ m_errorMonitor->SetUnexpectedError("Unable to remove Semaphore obj");
vkDestroySemaphore(m_device->device(), semaphore, nullptr);
+ m_errorMonitor->SetUnexpectedError("If fence is not VK_NULL_HANDLE, fence must be a valid VkFence handle");
+ m_errorMonitor->SetUnexpectedError("Unable to remove Fence obj");
vkDestroyFence(m_device->device(), fence, nullptr);
+ m_errorMonitor->SetUnexpectedError("If event is not VK_NULL_HANDLE, event must be a valid VkEvent handle");
+ m_errorMonitor->SetUnexpectedError("Unable to remove Event obj");
vkDestroyEvent(m_device->device(), event, nullptr);
vkDestroyDescriptorPool(m_device->device(), descriptorset_pool, nullptr);
vkDestroyDescriptorSetLayout(m_device->device(), descriptorset_layout, nullptr);
@@ -12173,6 +12312,8 @@
vkQueueWaitIdle(m_device->m_queue);
// Now that cmd buffer done we can safely destroy query_pool
+ m_errorMonitor->SetUnexpectedError("If queryPool is not VK_NULL_HANDLE, queryPool must be a valid VkQueryPool handle");
+ m_errorMonitor->SetUnexpectedError("Unable to remove Query Pool obj");
vkDestroyQueryPool(m_device->handle(), query_pool, NULL);
}
@@ -12222,6 +12363,8 @@
m_errorMonitor->VerifyFound();
// Make sure queue finished and then actually delete pipeline
vkQueueWaitIdle(m_device->m_queue);
+ m_errorMonitor->SetUnexpectedError("If pipeline is not VK_NULL_HANDLE, pipeline must be a valid VkPipeline handle");
+ m_errorMonitor->SetUnexpectedError("Unable to remove Pipeline obj");
vkDestroyPipeline(m_device->handle(), delete_this_pipeline, nullptr);
vkDestroyPipelineLayout(m_device->handle(), pipeline_layout, nullptr);
}
@@ -12391,6 +12534,8 @@
m_errorMonitor->VerifyFound();
vkQueueWaitIdle(m_device->m_queue);
// Now we can actually destroy imageView
+ m_errorMonitor->SetUnexpectedError("If imageView is not VK_NULL_HANDLE, imageView must be a valid VkImageView handle");
+ m_errorMonitor->SetUnexpectedError("Unable to remove Image View obj");
vkDestroyImageView(m_device->device(), view, NULL);
vkDestroySampler(m_device->device(), sampler, nullptr);
vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);
@@ -12554,6 +12699,8 @@
m_errorMonitor->VerifyFound();
vkQueueWaitIdle(m_device->m_queue);
// Now we can actually destroy bufferView
+ m_errorMonitor->SetUnexpectedError("If bufferView is not VK_NULL_HANDLE, bufferView must be a valid VkBufferView handle");
+ m_errorMonitor->SetUnexpectedError("Unable to remove Buffer View obj");
vkDestroyBufferView(m_device->device(), view, NULL);
vkDestroyBuffer(m_device->device(), buffer, NULL);
vkFreeMemory(m_device->device(), buffer_memory, NULL);
@@ -12728,6 +12875,8 @@
vkQueueWaitIdle(m_device->m_queue);
// Now we can actually destroy sampler
+ m_errorMonitor->SetUnexpectedError("If sampler is not VK_NULL_HANDLE, sampler must be a valid VkSampler handle");
+ m_errorMonitor->SetUnexpectedError("Unable to remove Sampler obj");
vkDestroySampler(m_device->device(), sampler, NULL); // Destroyed for real
vkDestroyImageView(m_device->device(), view, NULL);
vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);
@@ -13935,6 +14084,7 @@
descriptorSet.AppendDummy();
descriptorSet.CreateVKDescriptorSet(m_commandBuffer);
+ m_errorMonitor->SetUnexpectedError("Vertex shader consumes input at location 1 but not provided");
pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass());
m_errorMonitor->VerifyFound();
@@ -14159,6 +14309,7 @@
descriptorSet.AppendDummy();
descriptorSet.CreateVKDescriptorSet(m_commandBuffer);
+ m_errorMonitor->SetUnexpectedError("Vertex shader consumes input at location 1 but not provided");
pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass());
m_errorMonitor->VerifyFound();
@@ -15232,6 +15383,7 @@
// Introduce error by sending down a bogus width extent
image_create_info.extent.width = 0;
+ m_errorMonitor->SetUnexpectedError("parameter pCreateInfo->extent.width must be greater than 0");
vkCreateImage(m_device->device(), &image_create_info, NULL, &image);
m_errorMonitor->VerifyFound();
@@ -15315,6 +15467,8 @@
image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
VkImageView view;
+ m_errorMonitor->SetUnexpectedError(
+ "If image is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object");
err = vkCreateImageView(m_device->device(), &image_view_create_info, NULL, &view);
m_errorMonitor->VerifyFound();
@@ -15524,6 +15678,10 @@
"vkCreateImage: VkFormat for image must not be VK_FORMAT_UNDEFINED");
VkImage localImage;
+ m_errorMonitor->SetUnexpectedError("CreateImage extents exceed allowable limits for format");
+ m_errorMonitor->SetUnexpectedError("CreateImage mipLevels=1 exceeds allowable maximum supported by format of 0");
+ m_errorMonitor->SetUnexpectedError("arrayLayers must be less than or equal to VkImageFormatProperties::maxArrayLayers");
+ m_errorMonitor->SetUnexpectedError("samples must be a bit value that is set in VkImageFormatProperties::sampleCounts");
vkCreateImage(m_device->handle(), &image_create_info, NULL, &localImage);
m_errorMonitor->VerifyFound();
@@ -15542,6 +15700,14 @@
image_create_info.format = unsupported;
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "is an unsupported format");
+ m_errorMonitor->SetUnexpectedError("CreateImage extents exceed allowable limits for format");
+ m_errorMonitor->SetUnexpectedError("CreateImage resource size exceeds allowable maximum Image resource size");
+ m_errorMonitor->SetUnexpectedError("CreateImage mipLevels=1 exceeds allowable maximum supported by format of 0");
+ m_errorMonitor->SetUnexpectedError("arrayLayers must be less than or equal to VkImageFormatProperties::maxArrayLayers");
+ m_errorMonitor->SetUnexpectedError(
+ "samples must be a bit value that is set in VkImageFormatProperties::sampleCounts returned by "
+ "vkGetPhysicalDeviceImageFormatProperties with format, type, tiling, usage, and flags equal to those in this "
+ "structure");
vkCreateImage(m_device->handle(), &image_create_info, NULL, &localImage);
m_errorMonitor->VerifyFound();
}
@@ -15636,6 +15802,8 @@
ret = vkCreateImage(m_device->handle(), &mutImgInfo, NULL, &mutImage);
ASSERT_VK_SUCCESS(ret);
imgViewInfo.image = mutImage;
+ m_errorMonitor->SetUnexpectedError(
+ "If image is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object");
vkCreateImageView(m_device->handle(), &imgViewInfo, NULL, &imgView);
m_errorMonitor->VerifyFound();
imgViewInfo.image = image.handle();
@@ -15757,6 +15925,7 @@
// Look for NULL-blit warning
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, "Offsets specify a zero-volume area.");
+ m_errorMonitor->SetUnexpectedError("vkCmdBlitImage: pRegions[0].dstOffsets specify a zero-volume area.");
vkCmdBlitImage(m_commandBuffer->GetBufferHandle(), intImage1.handle(), intImage1.layout(), intImage2.handle(),
intImage2.layout(), 1, &blitRegion, VK_FILTER_LINEAR);
m_errorMonitor->VerifyFound();