diff options
author | locke-luanrg <locke@lunarg.com> | 2019-05-15 22:54:32 -0600 |
---|---|---|
committer | Locke Lin <47329816+locke-lunarg@users.noreply.github.com> | 2019-05-17 09:08:39 -0600 |
commit | b746f156f0b2fa2ebad888918e2bd0c6097c046d (patch) | |
tree | b9452625c043ea02dea6b416397747bf9058e4b9 /tests/layer_validation_tests.cpp | |
parent | 99867f57140e6088ab0e7db0451bac01b42c7c9c (diff) | |
download | vulkan-validation-layers-b746f156f0b2fa2ebad888918e2bd0c6097c046d.tar.gz |
tests: Remove tests and common codes
Leave main function, and remove tests and common codes.
Change-Id: I5c8b675363113d79e80943a4a11c7a8f350210a4
Diffstat (limited to 'tests/layer_validation_tests.cpp')
-rw-r--r-- | tests/layer_validation_tests.cpp | 39504 |
1 files changed, 1 insertions, 39503 deletions
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp index 3858afbf0..727670cfd 100644 --- a/tests/layer_validation_tests.cpp +++ b/tests/layer_validation_tests.cpp @@ -23,39509 +23,7 @@ * Author: Shannon McPherson <shannon@lunarg.com> * Author: John Zulauf <jzulauf@lunarg.com> */ - -#ifdef ANDROID -#include "vulkan_wrapper.h" -#else -#define NOMINMAX -#include <vulkan/vulkan.h> -#endif - -#include "layers/vk_device_profile_api_layer.h" - -#if defined(ANDROID) -#include <android/log.h> -#if defined(VALIDATION_APK) -#include <android_native_app_glue.h> -#endif -#endif - -#include "icd-spv.h" -#include "test_common.h" -#include "vk_layer_config.h" -#include "vk_format_utils.h" -#include "vkrenderframework.h" -#include "vk_typemap_helper.h" -#include "convert_to_renderpass2.h" - -#include <algorithm> -#include <cmath> -#include <functional> -#include <limits> -#include <memory> -#include <unordered_set> - -//-------------------------------------------------------------------------------------- -// Mesh and VertexFormat Data -//-------------------------------------------------------------------------------------- - -const char *kSkipPrefix = " TEST SKIPPED:"; - -enum BsoFailSelect { - BsoFailNone, - BsoFailLineWidth, - BsoFailDepthBias, - BsoFailViewport, - BsoFailScissor, - BsoFailBlend, - BsoFailDepthBounds, - BsoFailStencilReadMask, - BsoFailStencilWriteMask, - BsoFailStencilReference, - BsoFailCmdClearAttachments, - BsoFailIndexBuffer, - BsoFailIndexBufferBadSize, - BsoFailIndexBufferBadOffset, - BsoFailIndexBufferBadMapSize, - BsoFailIndexBufferBadMapOffset -}; - -static const char bindStateVertShaderText[] = - "#version 450\n" - "vec2 vertices[3];\n" - "void main() {\n" - " vertices[0] = vec2(-1.0, -1.0);\n" - " vertices[1] = vec2( 1.0, -1.0);\n" - " vertices[2] = vec2( 0.0, 1.0);\n" - " gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);\n" - "}\n"; - -static const char bindStateFragShaderText[] = - "#version 450\n" - "\n" - "layout(location = 0) out vec4 uFragColor;\n" - "void main(){\n" - " uFragColor = vec4(0,1,0,1);\n" - "}\n"; - -// Static arrays helper -template <class ElementT, size_t array_size> -size_t size(ElementT (&)[array_size]) { - return array_size; -} - -// Format search helper -VkFormat FindSupportedDepthStencilFormat(VkPhysicalDevice phy) { - VkFormat ds_formats[] = {VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT}; - for (uint32_t i = 0; i < sizeof(ds_formats); i++) { - VkFormatProperties format_props; - vkGetPhysicalDeviceFormatProperties(phy, ds_formats[i], &format_props); - - if (format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) { - return ds_formats[i]; - } - } - return VK_FORMAT_UNDEFINED; -} - -// Returns true if *any* requested features are available. -// Assumption is that the framework can successfully create an image as -// long as at least one of the feature bits is present (excepting VTX_BUF). -bool ImageFormatIsSupported(VkPhysicalDevice phy, VkFormat format, VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL, - VkFormatFeatureFlags features = ~VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) { - VkFormatProperties format_props; - vkGetPhysicalDeviceFormatProperties(phy, format, &format_props); - VkFormatFeatureFlags phy_features = - (VK_IMAGE_TILING_OPTIMAL == tiling ? format_props.optimalTilingFeatures : format_props.linearTilingFeatures); - return (0 != (phy_features & features)); -} - -// Returns true if format and *all* requested features are available. -bool ImageFormatAndFeaturesSupported(VkPhysicalDevice phy, VkFormat format, VkImageTiling tiling, VkFormatFeatureFlags features) { - VkFormatProperties format_props; - vkGetPhysicalDeviceFormatProperties(phy, format, &format_props); - VkFormatFeatureFlags phy_features = - (VK_IMAGE_TILING_OPTIMAL == tiling ? format_props.optimalTilingFeatures : format_props.linearTilingFeatures); - return (features == (phy_features & features)); -} - -// Returns true if format and *all* requested features are available. -bool ImageFormatAndFeaturesSupported(const VkInstance inst, const VkPhysicalDevice phy, const VkImageCreateInfo info, - const VkFormatFeatureFlags features) { - // Verify physical device support of format features - if (!ImageFormatAndFeaturesSupported(phy, info.format, info.tiling, features)) { - return false; - } - - // Verify that PhysDevImageFormatProp() also claims support for the specific usage - VkImageFormatProperties props; - VkResult err = - vkGetPhysicalDeviceImageFormatProperties(phy, info.format, info.imageType, info.tiling, info.usage, info.flags, &props); - if (VK_SUCCESS != err) { - return false; - } - -#if 0 // Convinced this chunk doesn't currently add any additional info, but leaving in place because it may be - // necessary with future extensions - - // Verify again using version 2, if supported, which *can* return more property data than the original... - // (It's not clear that this is any more definitive than using the original version - but no harm) - PFN_vkGetPhysicalDeviceImageFormatProperties2KHR p_GetPDIFP2KHR = - (PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)vkGetInstanceProcAddr(inst, - "vkGetPhysicalDeviceImageFormatProperties2KHR"); - if (NULL != p_GetPDIFP2KHR) { - VkPhysicalDeviceImageFormatInfo2KHR fmt_info{}; - fmt_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR; - fmt_info.pNext = nullptr; - fmt_info.format = info.format; - fmt_info.type = info.imageType; - fmt_info.tiling = info.tiling; - fmt_info.usage = info.usage; - fmt_info.flags = info.flags; - - VkImageFormatProperties2KHR fmt_props = {}; - fmt_props.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR; - err = p_GetPDIFP2KHR(phy, &fmt_info, &fmt_props); - if (VK_SUCCESS != err) { - return false; - } - } -#endif - - return true; -} - -// Validation report callback prototype -static VKAPI_ATTR VkBool32 VKAPI_CALL myDbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, - size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg, - void *pUserData); - -// Simple sane SamplerCreateInfo boilerplate -static VkSamplerCreateInfo SafeSaneSamplerCreateInfo() { - VkSamplerCreateInfo sampler_create_info = {}; - sampler_create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - sampler_create_info.pNext = nullptr; - sampler_create_info.magFilter = VK_FILTER_NEAREST; - sampler_create_info.minFilter = VK_FILTER_NEAREST; - sampler_create_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; - sampler_create_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler_create_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler_create_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler_create_info.mipLodBias = 0.0; - sampler_create_info.anisotropyEnable = VK_FALSE; - sampler_create_info.maxAnisotropy = 1.0; - sampler_create_info.compareEnable = VK_FALSE; - sampler_create_info.compareOp = VK_COMPARE_OP_NEVER; - sampler_create_info.minLod = 0.0; - sampler_create_info.maxLod = 16.0; - sampler_create_info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - sampler_create_info.unnormalizedCoordinates = VK_FALSE; - - return sampler_create_info; -} - -static VkImageViewCreateInfo SafeSaneImageViewCreateInfo(VkImage image, VkFormat format, VkImageAspectFlags aspect_mask) { - VkImageViewCreateInfo image_view_create_info = {}; - image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - image_view_create_info.image = image; - image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - image_view_create_info.format = format; - image_view_create_info.subresourceRange.layerCount = 1; - image_view_create_info.subresourceRange.baseMipLevel = 0; - image_view_create_info.subresourceRange.levelCount = 1; - image_view_create_info.subresourceRange.aspectMask = aspect_mask; - - return image_view_create_info; -} - -static VkImageViewCreateInfo SafeSaneImageViewCreateInfo(const VkImageObj &image, VkFormat format, VkImageAspectFlags aspect_mask) { - return SafeSaneImageViewCreateInfo(image.handle(), format, aspect_mask); -} - -// Helper for checking createRenderPass2 support and adding related extensions. -static bool CheckCreateRenderPass2Support(VkRenderFramework *renderFramework, std::vector<const char *> &device_extension_names) { - if (renderFramework->DeviceExtensionSupported(renderFramework->gpu(), nullptr, VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME)) { - device_extension_names.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME); - device_extension_names.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME); - device_extension_names.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); - return true; - } - return false; -} -// Helper for checking descriptor_indexing support and adding related extensions. -static bool CheckDescriptorIndexingSupportAndInitFramework(VkRenderFramework *renderFramework, - std::vector<const char *> &instance_extension_names, - std::vector<const char *> &device_extension_names, - VkValidationFeaturesEXT *features, void *userData) { - bool descriptor_indexing = renderFramework->InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - if (descriptor_indexing) { - instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - renderFramework->InitFramework(myDbgFunc, userData, features); - descriptor_indexing = descriptor_indexing && renderFramework->DeviceExtensionSupported(renderFramework->gpu(), nullptr, - VK_KHR_MAINTENANCE3_EXTENSION_NAME); - descriptor_indexing = descriptor_indexing && renderFramework->DeviceExtensionSupported( - renderFramework->gpu(), nullptr, VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); - if (descriptor_indexing) { - device_extension_names.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME); - device_extension_names.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); - return true; - } - return false; -} - -// Dependent "false" type for the static assert, as GCC will evaluate -// non-dependent static_asserts even for non-instantiated templates -template <typename T> -struct AlwaysFalse : std::false_type {}; - -// Helpers to get nearest greater or smaller value (of float) -- useful for testing the boundary cases of Vulkan limits -template <typename T> -T NearestGreater(const T from) { - using Lim = std::numeric_limits<T>; - const auto positive_direction = Lim::has_infinity ? Lim::infinity() : Lim::max(); - - return std::nextafter(from, positive_direction); -} - -template <typename T> -T NearestSmaller(const T from) { - using Lim = std::numeric_limits<T>; - const auto negative_direction = Lim::has_infinity ? -Lim::infinity() : Lim::lowest(); - - return std::nextafter(from, negative_direction); -} - -// ErrorMonitor Usage: -// -// Call SetDesiredFailureMsg with a string to be compared against all -// encountered log messages, or a validation error enum identifying -// desired error message. Passing NULL or VALIDATION_ERROR_MAX_ENUM -// will match all log messages. logMsg will return true for skipCall -// only if msg is matched or NULL. -// -// Call VerifyFound to determine if all desired failure messages -// were encountered. Call VerifyNotFound to determine if any unexpected -// failure was encountered. -class ErrorMonitor { - public: - ErrorMonitor() { - test_platform_thread_create_mutex(&mutex_); - test_platform_thread_lock_mutex(&mutex_); - Reset(); - test_platform_thread_unlock_mutex(&mutex_); - } - - ~ErrorMonitor() { test_platform_thread_delete_mutex(&mutex_); } - - // Set monitor to pristine state - void Reset() { - message_flags_ = VK_DEBUG_REPORT_ERROR_BIT_EXT; - bailout_ = NULL; - message_found_ = VK_FALSE; - failure_message_strings_.clear(); - desired_message_strings_.clear(); - ignore_message_strings_.clear(); - other_messages_.clear(); - } - - // ErrorMonitor will look for an error message containing the specified string(s) - void SetDesiredFailureMsg(const VkFlags msgFlags, const std::string msg) { SetDesiredFailureMsg(msgFlags, msg.c_str()); } - void SetDesiredFailureMsg(const VkFlags msgFlags, const char *const msgString) { - test_platform_thread_lock_mutex(&mutex_); - desired_message_strings_.insert(msgString); - message_flags_ |= msgFlags; - test_platform_thread_unlock_mutex(&mutex_); - } - - // ErrorMonitor will look for an error message containing the specified string(s) - template <typename Iter> - void SetDesiredFailureMsg(const VkFlags msgFlags, Iter iter, const Iter end) { - for (; iter != end; ++iter) { - SetDesiredFailureMsg(msgFlags, *iter); - } - } - - // 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 char *const msgString) { - VkBool32 result = VK_FALSE; - test_platform_thread_lock_mutex(&mutex_); - if (bailout_ != nullptr) { - *bailout_ = true; - } - string errorString(msgString); - bool found_expected = false; - - if (!IgnoreMessage(errorString)) { - for (auto desired_msg_it = desired_message_strings_.begin(); desired_msg_it != desired_message_strings_.end(); - ++desired_msg_it) { - if ((*desired_msg_it).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_ = true; - failure_message_strings_.insert(errorString); - } else if (errorString.find(*desired_msg_it) != string::npos) { - found_expected = true; - failure_message_strings_.insert(errorString); - message_found_ = true; - result = VK_TRUE; - // Remove a maximum of one failure message from the set - // Multiset mutation is acceptable because `break` causes flow of control to exit the for loop - desired_message_strings_.erase(desired_msg_it); - break; - } - } - - if (!found_expected) { - printf("Unexpected: %s\n", msgString); - other_messages_.push_back(errorString); - } - } - - test_platform_thread_unlock_mutex(&mutex_); - return result; - } - - vector<string> GetOtherFailureMsgs() const { return other_messages_; } - - VkDebugReportFlagsEXT GetMessageFlags() const { return message_flags_; } - - bool AnyDesiredMsgFound() const { return message_found_; } - - bool AllDesiredMsgsFound() const { return desired_message_strings_.empty(); } - - void SetError(const char *const errorString) { - message_found_ = true; - failure_message_strings_.insert(errorString); - } - - void SetBailout(bool *bailout) { bailout_ = bailout; } - - void DumpFailureMsgs() const { - vector<string> otherMsgs = GetOtherFailureMsgs(); - if (otherMsgs.size()) { - cout << "Other error messages logged for this test were:" << endl; - for (auto iter = otherMsgs.begin(); iter != otherMsgs.end(); iter++) { - cout << " " << *iter << endl; - } - } - } - - // Helpers - - // ExpectSuccess now takes an optional argument allowing a custom combination of debug flags - void ExpectSuccess(VkDebugReportFlagsEXT const message_flag_mask = VK_DEBUG_REPORT_ERROR_BIT_EXT) { - // Match ANY message matching specified type - SetDesiredFailureMsg(message_flag_mask, ""); - message_flags_ = message_flag_mask; // override mask handling in SetDesired... - } - - void VerifyFound() { - // Not receiving expected message(s) is a failure. /Before/ throwing, dump any other messages - if (!AllDesiredMsgsFound()) { - DumpFailureMsgs(); - for (const auto desired_msg : desired_message_strings_) { - ADD_FAILURE() << "Did not receive expected error '" << desired_msg << "'"; - } - } else if (GetOtherFailureMsgs().size() > 0) { - // Fail test case for any unexpected errors -#if defined(ANDROID) - // This will get unexpected errors into the adb log - for (auto msg : other_messages_) { - __android_log_print(ANDROID_LOG_INFO, "VulkanLayerValidationTests", "[ UNEXPECTED_ERR ] '%s'", msg.c_str()); - } -#else - ADD_FAILURE() << "Received unexpected error(s)."; -#endif - } - Reset(); - } - - void VerifyNotFound() { - // ExpectSuccess() configured us to match anything. Any error is a failure. - if (AnyDesiredMsgFound()) { - DumpFailureMsgs(); - for (const auto msg : failure_message_strings_) { - ADD_FAILURE() << "Expected to succeed but got error: " << msg; - } - } else if (GetOtherFailureMsgs().size() > 0) { - // Fail test case for any unexpected errors -#if defined(ANDROID) - // This will get unexpected errors into the adb log - for (auto msg : other_messages_) { - __android_log_print(ANDROID_LOG_INFO, "VulkanLayerValidationTests", "[ UNEXPECTED_ERR ] '%s'", msg.c_str()); - } -#else - ADD_FAILURE() << "Received unexpected error(s)."; -#endif - } - Reset(); - } - - 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_multiset<std::string> desired_message_strings_; - std::unordered_multiset<std::string> failure_message_strings_; - std::vector<std::string> ignore_message_strings_; - vector<string> other_messages_; - test_platform_thread_mutex mutex_; - bool *bailout_; - bool message_found_; -}; - -static VKAPI_ATTR VkBool32 VKAPI_CALL myDbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, - size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg, - void *pUserData) { - ErrorMonitor *errMonitor = (ErrorMonitor *)pUserData; - if (msgFlags & errMonitor->GetMessageFlags()) { - return errMonitor->CheckForDesiredMsg(pMsg); - } - return VK_FALSE; -} - -class VkLayerTest : public VkRenderFramework { - public: - void VKTriangleTest(BsoFailSelect failCase); - void GenericDrawPreparation(VkCommandBufferObj *commandBuffer, VkPipelineObj &pipelineobj, VkDescriptorSetObj &descriptorSet, - BsoFailSelect failCase); - - void Init(VkPhysicalDeviceFeatures *features = nullptr, VkPhysicalDeviceFeatures2 *features2 = nullptr, - const VkCommandPoolCreateFlags flags = 0, void *instance_pnext = nullptr) { - InitFramework(myDbgFunc, m_errorMonitor, instance_pnext); - InitState(features, features2, flags); - } - - protected: - ErrorMonitor *m_errorMonitor; - uint32_t m_instance_api_version = 0; - uint32_t m_target_api_version = 0; - - public: - ErrorMonitor *Monitor() { return m_errorMonitor; } - VkCommandBufferObj *CommandBuffer() { return m_commandBuffer; } - - protected: - bool m_enableWSI; - - virtual void SetUp() { - m_instance_layer_names.clear(); - m_instance_extension_names.clear(); - m_device_extension_names.clear(); - - // Add default instance extensions to the list - m_instance_extension_names.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); - - if (VkTestFramework::m_khronos_layer_disable) { - m_instance_layer_names.push_back("VK_LAYER_GOOGLE_threading"); - m_instance_layer_names.push_back("VK_LAYER_LUNARG_parameter_validation"); - m_instance_layer_names.push_back("VK_LAYER_LUNARG_object_tracker"); - m_instance_layer_names.push_back("VK_LAYER_LUNARG_core_validation"); - m_instance_layer_names.push_back("VK_LAYER_GOOGLE_unique_objects"); - } else { - m_instance_layer_names.push_back("VK_LAYER_KHRONOS_validation"); - } - if (VkTestFramework::m_devsim_layer) { - if (InstanceLayerSupported("VK_LAYER_LUNARG_device_simulation")) { - m_instance_layer_names.push_back("VK_LAYER_LUNARG_device_simulation"); - } else { - VkTestFramework::m_devsim_layer = false; - printf(" Did not find VK_LAYER_LUNARG_device_simulation layer so it will not be enabled.\n"); - } - } - if (m_enableWSI) { - m_instance_extension_names.push_back(VK_KHR_SURFACE_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); -#ifdef NEED_TO_TEST_THIS_ON_PLATFORM -#if defined(VK_USE_PLATFORM_ANDROID_KHR) - m_instance_extension_names.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); -#endif // VK_USE_PLATFORM_ANDROID_KHR -#if defined(VK_USE_PLATFORM_WAYLAND_KHR) - m_instance_extension_names.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); -#endif // VK_USE_PLATFORM_WAYLAND_KHR -#if defined(VK_USE_PLATFORM_WIN32_KHR) - m_instance_extension_names.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); -#endif // VK_USE_PLATFORM_WIN32_KHR -#endif // NEED_TO_TEST_THIS_ON_PLATFORM -#if defined(VK_USE_PLATFORM_XCB_KHR) - m_instance_extension_names.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME); -#elif defined(VK_USE_PLATFORM_XLIB_KHR) - m_instance_extension_names.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); -#endif // VK_USE_PLATFORM_XLIB_KHR - } - - this->app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - this->app_info.pNext = NULL; - this->app_info.pApplicationName = "layer_tests"; - this->app_info.applicationVersion = 1; - this->app_info.pEngineName = "unittest"; - this->app_info.engineVersion = 1; - this->app_info.apiVersion = VK_API_VERSION_1_0; - - m_errorMonitor = new ErrorMonitor; - - // Find out what version the instance supports and record the default target instance - auto enumerateInstanceVersion = - (PFN_vkEnumerateInstanceVersion)vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"); - if (enumerateInstanceVersion) { - enumerateInstanceVersion(&m_instance_api_version); - } else { - m_instance_api_version = VK_API_VERSION_1_0; - } - m_target_api_version = app_info.apiVersion; - } - - uint32_t SetTargetApiVersion(uint32_t target_api_version) { - if (target_api_version == 0) target_api_version = VK_API_VERSION_1_0; - if (target_api_version <= m_instance_api_version) { - m_target_api_version = target_api_version; - app_info.apiVersion = m_target_api_version; - } - return m_target_api_version; - } - uint32_t DeviceValidationVersion() { - // The validation layers, assume the version we are validating to is the apiVersion unless the device apiVersion is lower - VkPhysicalDeviceProperties props; - GetPhysicalDeviceProperties(&props); - return std::min(m_target_api_version, props.apiVersion); - } - - bool LoadDeviceProfileLayer( - PFN_vkSetPhysicalDeviceFormatPropertiesEXT &fpvkSetPhysicalDeviceFormatPropertiesEXT, - PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT &fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT) { - // Load required functions - fpvkSetPhysicalDeviceFormatPropertiesEXT = - (PFN_vkSetPhysicalDeviceFormatPropertiesEXT)vkGetInstanceProcAddr(instance(), "vkSetPhysicalDeviceFormatPropertiesEXT"); - fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT = - (PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT)vkGetInstanceProcAddr( - instance(), "vkGetOriginalPhysicalDeviceFormatPropertiesEXT"); - - if (!(fpvkSetPhysicalDeviceFormatPropertiesEXT) || !(fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT)) { - printf("%s Can't find device_profile_api functions; skipped.\n", kSkipPrefix); - return 0; - } - - return 1; - } - - virtual void TearDown() { - // Clean up resources before we reset - ShutdownFramework(); - delete m_errorMonitor; - } - - VkLayerTest() { m_enableWSI = false; } -}; - -void VkLayerTest::VKTriangleTest(BsoFailSelect failCase) { - ASSERT_TRUE(m_device && m_device->initialized()); // VKTriangleTest assumes Init() has finished - - ASSERT_NO_FATAL_FAILURE(InitViewport()); - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj ps(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipelineobj(m_device); - pipelineobj.AddDefaultColorAttachment(); - pipelineobj.AddShader(&vs); - pipelineobj.AddShader(&ps); - - bool failcase_needs_depth = false; // to mark cases that need depth attachment - - VkBufferObj index_buffer; - - switch (failCase) { - case BsoFailLineWidth: { - pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_LINE_WIDTH); - VkPipelineInputAssemblyStateCreateInfo ia_state = {}; - ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - ia_state.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST; - pipelineobj.SetInputAssembly(&ia_state); - break; - } - case BsoFailDepthBias: { - pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_DEPTH_BIAS); - VkPipelineRasterizationStateCreateInfo rs_state = {}; - rs_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rs_state.depthBiasEnable = VK_TRUE; - rs_state.lineWidth = 1.0f; - pipelineobj.SetRasterization(&rs_state); - break; - } - case BsoFailViewport: { - pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_VIEWPORT); - break; - } - case BsoFailScissor: { - pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_SCISSOR); - break; - } - case BsoFailBlend: { - pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_BLEND_CONSTANTS); - VkPipelineColorBlendAttachmentState att_state = {}; - att_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR; - att_state.blendEnable = VK_TRUE; - pipelineobj.AddColorAttachment(0, att_state); - break; - } - case BsoFailDepthBounds: { - failcase_needs_depth = true; - pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_DEPTH_BOUNDS); - break; - } - case BsoFailStencilReadMask: { - failcase_needs_depth = true; - pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK); - break; - } - case BsoFailStencilWriteMask: { - failcase_needs_depth = true; - pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK); - break; - } - case BsoFailStencilReference: { - failcase_needs_depth = true; - pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_STENCIL_REFERENCE); - break; - } - - case BsoFailIndexBuffer: - break; - case BsoFailIndexBufferBadSize: - case BsoFailIndexBufferBadOffset: - case BsoFailIndexBufferBadMapSize: - case BsoFailIndexBufferBadMapOffset: { - // Create an index buffer for these tests. - // There is no need to populate it because we should bail before trying to draw. - uint32_t const indices[] = {0}; - VkBufferCreateInfo buffer_info = {}; - buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_info.size = 1024; - buffer_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; - buffer_info.queueFamilyIndexCount = 1; - buffer_info.pQueueFamilyIndices = indices; - index_buffer.init(*m_device, buffer_info, (VkMemoryPropertyFlags)VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - } break; - case BsoFailCmdClearAttachments: - break; - case BsoFailNone: - break; - default: - break; - } - - VkDescriptorSetObj descriptorSet(m_device); - - VkImageView *depth_attachment = nullptr; - if (failcase_needs_depth) { - m_depth_stencil_fmt = FindSupportedDepthStencilFormat(gpu()); - ASSERT_TRUE(m_depth_stencil_fmt != VK_FORMAT_UNDEFINED); - - m_depthStencil->Init(m_device, static_cast<uint32_t>(m_width), static_cast<uint32_t>(m_height), m_depth_stencil_fmt, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); - depth_attachment = m_depthStencil->BindInfo(); - } - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget(1, depth_attachment)); - m_commandBuffer->begin(); - - GenericDrawPreparation(m_commandBuffer, pipelineobj, descriptorSet, failCase); - - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - // render triangle - if (failCase == BsoFailIndexBuffer) { - // Use DrawIndexed w/o an index buffer bound - m_commandBuffer->DrawIndexed(3, 1, 0, 0, 0); - } else if (failCase == BsoFailIndexBufferBadSize) { - // Bind the index buffer and draw one too many indices - m_commandBuffer->BindIndexBuffer(&index_buffer, 0, VK_INDEX_TYPE_UINT16); - m_commandBuffer->DrawIndexed(513, 1, 0, 0, 0); - } else if (failCase == BsoFailIndexBufferBadOffset) { - // Bind the index buffer and draw one past the end of the buffer using the offset - m_commandBuffer->BindIndexBuffer(&index_buffer, 0, VK_INDEX_TYPE_UINT16); - m_commandBuffer->DrawIndexed(512, 1, 1, 0, 0); - } else if (failCase == BsoFailIndexBufferBadMapSize) { - // Bind the index buffer at the middle point and draw one too many indices - m_commandBuffer->BindIndexBuffer(&index_buffer, 512, VK_INDEX_TYPE_UINT16); - m_commandBuffer->DrawIndexed(257, 1, 0, 0, 0); - } else if (failCase == BsoFailIndexBufferBadMapOffset) { - // Bind the index buffer at the middle point and draw one past the end of the buffer - m_commandBuffer->BindIndexBuffer(&index_buffer, 512, VK_INDEX_TYPE_UINT16); - m_commandBuffer->DrawIndexed(256, 1, 1, 0, 0); - } else { - m_commandBuffer->Draw(3, 1, 0, 0); - } - - if (failCase == BsoFailCmdClearAttachments) { - VkClearAttachment color_attachment = {}; - color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - color_attachment.colorAttachment = 2000000000; // Someone who knew what they were doing would use 0 for the index; - VkClearRect clear_rect = {{{0, 0}, {static_cast<uint32_t>(m_width), static_cast<uint32_t>(m_height)}}, 0, 0}; - - vkCmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect); - } - - // finalize recording of the command buffer - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - m_commandBuffer->QueueCommandBuffer(true); - DestroyRenderTarget(); -} - -void VkLayerTest::GenericDrawPreparation(VkCommandBufferObj *commandBuffer, VkPipelineObj &pipelineobj, - VkDescriptorSetObj &descriptorSet, BsoFailSelect failCase) { - commandBuffer->ClearAllBuffers(m_renderTargets, m_clear_color, m_depthStencil, m_depth_clear_color, m_stencil_clear_color); - - commandBuffer->PrepareAttachments(m_renderTargets, m_depthStencil); - // Make sure depthWriteEnable is set so that Depth fail test will work - // correctly - // Make sure stencilTestEnable is set so that Stencil fail test will work - // correctly - VkStencilOpState stencil = {}; - stencil.failOp = VK_STENCIL_OP_KEEP; - stencil.passOp = VK_STENCIL_OP_KEEP; - stencil.depthFailOp = VK_STENCIL_OP_KEEP; - stencil.compareOp = VK_COMPARE_OP_NEVER; - - VkPipelineDepthStencilStateCreateInfo ds_ci = {}; - ds_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - ds_ci.pNext = NULL; - ds_ci.depthTestEnable = VK_FALSE; - ds_ci.depthWriteEnable = VK_TRUE; - ds_ci.depthCompareOp = VK_COMPARE_OP_NEVER; - ds_ci.depthBoundsTestEnable = VK_FALSE; - if (failCase == BsoFailDepthBounds) { - ds_ci.depthBoundsTestEnable = VK_TRUE; - ds_ci.maxDepthBounds = 0.0f; - ds_ci.minDepthBounds = 0.0f; - } - ds_ci.stencilTestEnable = VK_TRUE; - ds_ci.front = stencil; - ds_ci.back = stencil; - - pipelineobj.SetDepthStencil(&ds_ci); - pipelineobj.SetViewport(m_viewports); - pipelineobj.SetScissor(m_scissors); - descriptorSet.CreateVKDescriptorSet(commandBuffer); - VkResult err = pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - ASSERT_VK_SUCCESS(err); - vkCmdBindPipeline(commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineobj.handle()); - commandBuffer->BindDescriptorSet(descriptorSet); -} - -class VkPositiveLayerTest : public VkLayerTest { - public: - protected: -}; - -class VkWsiEnabledLayerTest : public VkLayerTest { - public: - protected: - VkWsiEnabledLayerTest() { m_enableWSI = true; } -}; - -class VkBufferTest { - public: - enum eTestEnFlags { - eDoubleDelete, - eInvalidDeviceOffset, - eInvalidMemoryOffset, - eBindNullBuffer, - eBindFakeBuffer, - eFreeInvalidHandle, - eNone, - }; - - enum eTestConditions { eOffsetAlignment = 1 }; - - static bool GetTestConditionValid(VkDeviceObj *aVulkanDevice, eTestEnFlags aTestFlag, VkBufferUsageFlags aBufferUsage = 0) { - if (eInvalidDeviceOffset != aTestFlag && eInvalidMemoryOffset != aTestFlag) { - return true; - } - VkDeviceSize offset_limit = 0; - if (eInvalidMemoryOffset == aTestFlag) { - VkBuffer vulkanBuffer; - VkBufferCreateInfo buffer_create_info = {}; - buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_create_info.size = 32; - buffer_create_info.usage = aBufferUsage; - - vkCreateBuffer(aVulkanDevice->device(), &buffer_create_info, nullptr, &vulkanBuffer); - VkMemoryRequirements memory_reqs = {}; - - vkGetBufferMemoryRequirements(aVulkanDevice->device(), vulkanBuffer, &memory_reqs); - vkDestroyBuffer(aVulkanDevice->device(), vulkanBuffer, nullptr); - offset_limit = memory_reqs.alignment; - } else if ((VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) & aBufferUsage) { - offset_limit = aVulkanDevice->props.limits.minTexelBufferOffsetAlignment; - } else if (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT & aBufferUsage) { - offset_limit = aVulkanDevice->props.limits.minUniformBufferOffsetAlignment; - } else if (VK_BUFFER_USAGE_STORAGE_BUFFER_BIT & aBufferUsage) { - offset_limit = aVulkanDevice->props.limits.minStorageBufferOffsetAlignment; - } - return eOffsetAlignment < offset_limit; - } - - // A constructor which performs validation tests within construction. - VkBufferTest(VkDeviceObj *aVulkanDevice, VkBufferUsageFlags aBufferUsage, eTestEnFlags aTestFlag = eNone) - : AllocateCurrent(true), - BoundCurrent(false), - CreateCurrent(false), - InvalidDeleteEn(false), - VulkanDevice(aVulkanDevice->device()) { - if (eBindNullBuffer == aTestFlag || eBindFakeBuffer == aTestFlag) { - VkMemoryAllocateInfo memory_allocate_info = {}; - memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_allocate_info.allocationSize = 1; // fake size -- shouldn't matter for the test - memory_allocate_info.memoryTypeIndex = 0; // fake type -- shouldn't matter for the test - vkAllocateMemory(VulkanDevice, &memory_allocate_info, nullptr, &VulkanMemory); - - VulkanBuffer = (aTestFlag == eBindNullBuffer) ? VK_NULL_HANDLE : (VkBuffer)0xCDCDCDCDCDCDCDCD; - - vkBindBufferMemory(VulkanDevice, VulkanBuffer, VulkanMemory, 0); - } else { - VkBufferCreateInfo buffer_create_info = {}; - buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_create_info.size = 32; - buffer_create_info.usage = aBufferUsage; - - vkCreateBuffer(VulkanDevice, &buffer_create_info, nullptr, &VulkanBuffer); - - CreateCurrent = true; - - VkMemoryRequirements memory_requirements; - vkGetBufferMemoryRequirements(VulkanDevice, VulkanBuffer, &memory_requirements); - - VkMemoryAllocateInfo memory_allocate_info = {}; - memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_allocate_info.allocationSize = memory_requirements.size + eOffsetAlignment; - bool pass = aVulkanDevice->phy().set_memory_type(memory_requirements.memoryTypeBits, &memory_allocate_info, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - if (!pass) { - CreateCurrent = false; - vkDestroyBuffer(VulkanDevice, VulkanBuffer, nullptr); - return; - } - - vkAllocateMemory(VulkanDevice, &memory_allocate_info, NULL, &VulkanMemory); - // NB: 1 is intentionally an invalid offset value - const bool offset_en = eInvalidDeviceOffset == aTestFlag || eInvalidMemoryOffset == aTestFlag; - vkBindBufferMemory(VulkanDevice, VulkanBuffer, VulkanMemory, offset_en ? eOffsetAlignment : 0); - BoundCurrent = true; - - InvalidDeleteEn = (eFreeInvalidHandle == aTestFlag); - } - } - - ~VkBufferTest() { - if (CreateCurrent) { - vkDestroyBuffer(VulkanDevice, VulkanBuffer, nullptr); - } - if (AllocateCurrent) { - if (InvalidDeleteEn) { - union { - VkDeviceMemory device_memory; - unsigned long long index_access; - } bad_index; - - bad_index.device_memory = VulkanMemory; - bad_index.index_access++; - - vkFreeMemory(VulkanDevice, bad_index.device_memory, nullptr); - } - vkFreeMemory(VulkanDevice, VulkanMemory, nullptr); - } - } - - bool GetBufferCurrent() { return AllocateCurrent && BoundCurrent && CreateCurrent; } - - const VkBuffer &GetBuffer() { return VulkanBuffer; } - - void TestDoubleDestroy() { - // Destroy the buffer but leave the flag set, which will cause - // the buffer to be destroyed again in the destructor. - vkDestroyBuffer(VulkanDevice, VulkanBuffer, nullptr); - } - - protected: - bool AllocateCurrent; - bool BoundCurrent; - bool CreateCurrent; - bool InvalidDeleteEn; - - VkBuffer VulkanBuffer; - VkDevice VulkanDevice; - VkDeviceMemory VulkanMemory; -}; - -class VkVerticesObj { - public: - VkVerticesObj(VkDeviceObj *aVulkanDevice, unsigned aAttributeCount, unsigned aBindingCount, unsigned aByteStride, - VkDeviceSize aVertexCount, const float *aVerticies) - : BoundCurrent(false), - AttributeCount(aAttributeCount), - BindingCount(aBindingCount), - BindId(BindIdGenerator), - PipelineVertexInputStateCreateInfo(), - VulkanMemoryBuffer(aVulkanDevice, static_cast<int>(aByteStride * aVertexCount), - reinterpret_cast<const void *>(aVerticies), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) { - BindIdGenerator++; // NB: This can wrap w/misuse - - VertexInputAttributeDescription = new VkVertexInputAttributeDescription[AttributeCount]; - VertexInputBindingDescription = new VkVertexInputBindingDescription[BindingCount]; - - PipelineVertexInputStateCreateInfo.pVertexAttributeDescriptions = VertexInputAttributeDescription; - PipelineVertexInputStateCreateInfo.vertexAttributeDescriptionCount = AttributeCount; - PipelineVertexInputStateCreateInfo.pVertexBindingDescriptions = VertexInputBindingDescription; - PipelineVertexInputStateCreateInfo.vertexBindingDescriptionCount = BindingCount; - PipelineVertexInputStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - - unsigned i = 0; - do { - VertexInputAttributeDescription[i].binding = BindId; - VertexInputAttributeDescription[i].location = i; - VertexInputAttributeDescription[i].format = VK_FORMAT_R32G32B32_SFLOAT; - VertexInputAttributeDescription[i].offset = sizeof(float) * aByteStride; - i++; - } while (AttributeCount < i); - - i = 0; - do { - VertexInputBindingDescription[i].binding = BindId; - VertexInputBindingDescription[i].stride = aByteStride; - VertexInputBindingDescription[i].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - i++; - } while (BindingCount < i); - } - - ~VkVerticesObj() { - if (VertexInputAttributeDescription) { - delete[] VertexInputAttributeDescription; - } - if (VertexInputBindingDescription) { - delete[] VertexInputBindingDescription; - } - } - - bool AddVertexInputToPipe(VkPipelineObj &aPipelineObj) { - aPipelineObj.AddVertexInputAttribs(VertexInputAttributeDescription, AttributeCount); - aPipelineObj.AddVertexInputBindings(VertexInputBindingDescription, BindingCount); - return true; - } - - void BindVertexBuffers(VkCommandBuffer aCommandBuffer, unsigned aOffsetCount = 0, VkDeviceSize *aOffsetList = nullptr) { - VkDeviceSize *offsetList; - unsigned offsetCount; - - if (aOffsetCount) { - offsetList = aOffsetList; - offsetCount = aOffsetCount; - } else { - offsetList = new VkDeviceSize[1](); - offsetCount = 1; - } - - vkCmdBindVertexBuffers(aCommandBuffer, BindId, offsetCount, &VulkanMemoryBuffer.handle(), offsetList); - BoundCurrent = true; - - if (!aOffsetCount) { - delete[] offsetList; - } - } - - protected: - static uint32_t BindIdGenerator; - - bool BoundCurrent; - unsigned AttributeCount; - unsigned BindingCount; - uint32_t BindId; - - VkPipelineVertexInputStateCreateInfo PipelineVertexInputStateCreateInfo; - VkVertexInputAttributeDescription *VertexInputAttributeDescription; - VkVertexInputBindingDescription *VertexInputBindingDescription; - VkConstantBufferObj VulkanMemoryBuffer; -}; - -uint32_t VkVerticesObj::BindIdGenerator; - -struct OneOffDescriptorSet { - VkDeviceObj *device_; - VkDescriptorPool pool_; - VkDescriptorSetLayoutObj layout_; - VkDescriptorSet set_; - typedef std::vector<VkDescriptorSetLayoutBinding> Bindings; - - OneOffDescriptorSet(VkDeviceObj *device, const Bindings &bindings, VkDescriptorSetLayoutCreateFlags layout_flags = 0, - void *layout_pnext = NULL, VkDescriptorPoolCreateFlags poolFlags = 0, void *allocate_pnext = NULL) - : device_{device}, pool_{}, layout_(device, bindings, layout_flags, layout_pnext), set_{} { - VkResult err; - - std::vector<VkDescriptorPoolSize> sizes; - for (const auto &b : bindings) sizes.push_back({b.descriptorType, std::max(1u, b.descriptorCount)}); - - VkDescriptorPoolCreateInfo dspci = { - VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, nullptr, poolFlags, 1, uint32_t(sizes.size()), sizes.data()}; - err = vkCreateDescriptorPool(device_->handle(), &dspci, nullptr, &pool_); - if (err != VK_SUCCESS) return; - - VkDescriptorSetAllocateInfo alloc_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, allocate_pnext, pool_, 1, - &layout_.handle()}; - err = vkAllocateDescriptorSets(device_->handle(), &alloc_info, &set_); - } - - ~OneOffDescriptorSet() { - // No need to destroy set-- it's going away with the pool. - vkDestroyDescriptorPool(device_->handle(), pool_, nullptr); - } - - bool Initialized() { return pool_ != VK_NULL_HANDLE && layout_.initialized() && set_ != VK_NULL_HANDLE; } -}; - -template <typename T> -bool IsValidVkStruct(const T &s) { - return LvlTypeMap<T>::kSType == s.sType; -} - -// Helper class for tersely creating create pipeline tests -// -// Designed with minimal error checking to ensure easy error state creation -// See OneshotTest for typical usage -struct CreatePipelineHelper { - public: - std::vector<VkDescriptorSetLayoutBinding> dsl_bindings_; - std::unique_ptr<OneOffDescriptorSet> descriptor_set_; - std::vector<VkPipelineShaderStageCreateInfo> shader_stages_; - VkPipelineVertexInputStateCreateInfo vi_ci_ = {}; - VkPipelineInputAssemblyStateCreateInfo ia_ci_ = {}; - VkPipelineTessellationStateCreateInfo tess_ci_ = {}; - VkViewport viewport_ = {}; - VkRect2D scissor_ = {}; - VkPipelineViewportStateCreateInfo vp_state_ci_ = {}; - VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci_ = {}; - VkPipelineLayoutCreateInfo pipeline_layout_ci_ = {}; - VkPipelineLayoutObj pipeline_layout_; - VkPipelineDynamicStateCreateInfo dyn_state_ci_ = {}; - VkPipelineRasterizationStateCreateInfo rs_state_ci_ = {}; - VkPipelineColorBlendAttachmentState cb_attachments_ = {}; - VkPipelineColorBlendStateCreateInfo cb_ci_ = {}; - VkGraphicsPipelineCreateInfo gp_ci_ = {}; - VkPipelineCacheCreateInfo pc_ci_ = {}; - VkPipeline pipeline_ = VK_NULL_HANDLE; - VkPipelineCache pipeline_cache_ = VK_NULL_HANDLE; - std::unique_ptr<VkShaderObj> vs_; - std::unique_ptr<VkShaderObj> fs_; - VkLayerTest &layer_test_; - CreatePipelineHelper(VkLayerTest &test) : layer_test_(test) {} - ~CreatePipelineHelper() { - VkDevice device = layer_test_.device(); - vkDestroyPipelineCache(device, pipeline_cache_, nullptr); - vkDestroyPipeline(device, pipeline_, nullptr); - } - - void InitDescriptorSetInfo() { dsl_bindings_ = {{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}; } - - void InitInputAndVertexInfo() { - vi_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - - ia_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; - } - - void InitMultisampleInfo() { - pipe_ms_state_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - pipe_ms_state_ci_.pNext = nullptr; - pipe_ms_state_ci_.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - pipe_ms_state_ci_.sampleShadingEnable = VK_FALSE; - pipe_ms_state_ci_.minSampleShading = 1.0; - pipe_ms_state_ci_.pSampleMask = NULL; - } - - void InitPipelineLayoutInfo() { - pipeline_layout_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_ci_.setLayoutCount = 1; // Not really changeable because InitState() sets exactly one pSetLayout - pipeline_layout_ci_.pSetLayouts = nullptr; // must bound after it is created - } - - void InitViewportInfo() { - viewport_ = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; - scissor_ = {{0, 0}, {64, 64}}; - - vp_state_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - vp_state_ci_.pNext = nullptr; - vp_state_ci_.viewportCount = 1; - vp_state_ci_.pViewports = &viewport_; // ignored if dynamic - vp_state_ci_.scissorCount = 1; - vp_state_ci_.pScissors = &scissor_; // ignored if dynamic - } - - void InitDynamicStateInfo() { - // Use a "validity" check on the {} initialized structure to detect initialization - // during late bind - } - - void InitShaderInfo() { - vs_.reset(new VkShaderObj(layer_test_.DeviceObj(), bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, &layer_test_)); - fs_.reset(new VkShaderObj(layer_test_.DeviceObj(), bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, &layer_test_)); - // We shouldn't need a fragment shader but add it to be able to run on more devices - shader_stages_ = {vs_->GetStageCreateInfo(), fs_->GetStageCreateInfo()}; - } - - void InitRasterizationInfo() { - rs_state_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rs_state_ci_.pNext = nullptr; - rs_state_ci_.flags = 0; - rs_state_ci_.depthClampEnable = VK_FALSE; - rs_state_ci_.rasterizerDiscardEnable = VK_FALSE; - rs_state_ci_.polygonMode = VK_POLYGON_MODE_FILL; - rs_state_ci_.cullMode = VK_CULL_MODE_BACK_BIT; - rs_state_ci_.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rs_state_ci_.depthBiasEnable = VK_FALSE; - rs_state_ci_.lineWidth = 1.0F; - } - - void InitBlendStateInfo() { - cb_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - cb_ci_.logicOpEnable = VK_FALSE; - cb_ci_.logicOp = VK_LOGIC_OP_COPY; // ignored if enable is VK_FALSE above - cb_ci_.attachmentCount = layer_test_.RenderPassInfo().subpassCount; - ASSERT_TRUE(IsValidVkStruct(layer_test_.RenderPassInfo())); - cb_ci_.pAttachments = &cb_attachments_; - for (int i = 0; i < 4; i++) { - cb_ci_.blendConstants[0] = 1.0F; - } - } - - void InitGraphicsPipelineInfo() { - // Color-only rendering in a subpass with no depth/stencil attachment - // Active Pipeline Shader Stages - // Vertex Shader - // Fragment Shader - // Required: Fixed-Function Pipeline Stages - // VkPipelineVertexInputStateCreateInfo - // VkPipelineInputAssemblyStateCreateInfo - // VkPipelineViewportStateCreateInfo - // VkPipelineRasterizationStateCreateInfo - // VkPipelineMultisampleStateCreateInfo - // VkPipelineColorBlendStateCreateInfo - gp_ci_.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - gp_ci_.pNext = nullptr; - gp_ci_.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; - gp_ci_.pVertexInputState = &vi_ci_; - gp_ci_.pInputAssemblyState = &ia_ci_; - gp_ci_.pTessellationState = nullptr; - gp_ci_.pViewportState = &vp_state_ci_; - gp_ci_.pRasterizationState = &rs_state_ci_; - gp_ci_.pMultisampleState = &pipe_ms_state_ci_; - gp_ci_.pDepthStencilState = nullptr; - gp_ci_.pColorBlendState = &cb_ci_; - gp_ci_.pDynamicState = nullptr; - gp_ci_.renderPass = layer_test_.renderPass(); - } - - void InitPipelineCacheInfo() { - pc_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - pc_ci_.pNext = nullptr; - pc_ci_.flags = 0; - pc_ci_.initialDataSize = 0; - pc_ci_.pInitialData = nullptr; - } - - // Not called by default during init_info - void InitTesselationState() { - // TBD -- add shaders and create_info - } - - // TDB -- add control for optional and/or additional initialization - void InitInfo() { - InitDescriptorSetInfo(); - InitInputAndVertexInfo(); - InitMultisampleInfo(); - InitPipelineLayoutInfo(); - InitViewportInfo(); - InitDynamicStateInfo(); - InitShaderInfo(); - InitRasterizationInfo(); - InitBlendStateInfo(); - InitGraphicsPipelineInfo(); - InitPipelineCacheInfo(); - } - - void InitState() { - VkResult err; - descriptor_set_.reset(new OneOffDescriptorSet(layer_test_.DeviceObj(), dsl_bindings_)); - ASSERT_TRUE(descriptor_set_->Initialized()); - - const std::vector<VkPushConstantRange> push_ranges( - pipeline_layout_ci_.pPushConstantRanges, - pipeline_layout_ci_.pPushConstantRanges + pipeline_layout_ci_.pushConstantRangeCount); - pipeline_layout_ = VkPipelineLayoutObj(layer_test_.DeviceObj(), {&descriptor_set_->layout_}, push_ranges); - - err = vkCreatePipelineCache(layer_test_.device(), &pc_ci_, NULL, &pipeline_cache_); - ASSERT_VK_SUCCESS(err); - } - - void LateBindPipelineInfo() { - // By value or dynamically located items must be late bound - gp_ci_.layout = pipeline_layout_.handle(); - gp_ci_.stageCount = shader_stages_.size(); - gp_ci_.pStages = shader_stages_.data(); - if ((gp_ci_.pTessellationState == nullptr) && IsValidVkStruct(tess_ci_)) { - gp_ci_.pTessellationState = &tess_ci_; - } - if ((gp_ci_.pDynamicState == nullptr) && IsValidVkStruct(dyn_state_ci_)) { - gp_ci_.pDynamicState = &dyn_state_ci_; - } - } - - VkResult CreateGraphicsPipeline(bool implicit_destroy = true, bool do_late_bind = true) { - VkResult err; - if (do_late_bind) { - LateBindPipelineInfo(); - } - if (implicit_destroy && (pipeline_ != VK_NULL_HANDLE)) { - vkDestroyPipeline(layer_test_.device(), pipeline_, nullptr); - pipeline_ = VK_NULL_HANDLE; - } - err = vkCreateGraphicsPipelines(layer_test_.device(), pipeline_cache_, 1, &gp_ci_, NULL, &pipeline_); - return err; - } - - // Helper function to create a simple test case (positive or negative) - // - // info_override can be any callable that takes a CreatePipelineHeper & - // flags, error can be any args accepted by "SetDesiredFailure". - template <typename Test, typename OverrideFunc, typename Error> - static void OneshotTest(Test &test, OverrideFunc &info_override, const VkFlags flags, const std::vector<Error> &errors, - bool positive_test = false) { - CreatePipelineHelper helper(test); - helper.InitInfo(); - info_override(helper); - helper.InitState(); - - for (const auto &error : errors) test.Monitor()->SetDesiredFailureMsg(flags, error); - helper.CreateGraphicsPipeline(); - - if (positive_test) { - test.Monitor()->VerifyNotFound(); - } else { - test.Monitor()->VerifyFound(); - } - } - - template <typename Test, typename OverrideFunc, typename Error> - static void OneshotTest(Test &test, OverrideFunc &info_override, const VkFlags flags, Error error, bool positive_test = false) { - OneshotTest(test, info_override, flags, std::vector<Error>(1, error), positive_test); - } -}; - -// Helper class for tersely creating create ray tracing pipeline tests -// -// Designed with minimal error checking to ensure easy error state creation -// See OneshotTest for typical usage -struct CreateNVRayTracingPipelineHelper { - public: - std::vector<VkDescriptorSetLayoutBinding> dsl_bindings_; - std::unique_ptr<OneOffDescriptorSet> descriptor_set_; - std::vector<VkPipelineShaderStageCreateInfo> shader_stages_; - VkPipelineLayoutCreateInfo pipeline_layout_ci_ = {}; - VkPipelineLayoutObj pipeline_layout_; - VkRayTracingPipelineCreateInfoNV rp_ci_ = {}; - VkPipelineCacheCreateInfo pc_ci_ = {}; - VkPipeline pipeline_ = VK_NULL_HANDLE; - VkPipelineCache pipeline_cache_ = VK_NULL_HANDLE; - std::vector<VkRayTracingShaderGroupCreateInfoNV> groups_; - std::unique_ptr<VkShaderObj> rgs_; - std::unique_ptr<VkShaderObj> chs_; - std::unique_ptr<VkShaderObj> mis_; - VkLayerTest &layer_test_; - CreateNVRayTracingPipelineHelper(VkLayerTest &test) : layer_test_(test) {} - ~CreateNVRayTracingPipelineHelper() { - VkDevice device = layer_test_.device(); - vkDestroyPipelineCache(device, pipeline_cache_, nullptr); - vkDestroyPipeline(device, pipeline_, nullptr); - } - - static bool InitInstanceExtensions(VkLayerTest &test, std::vector<const char *> &instance_extension_names) { - if (test.InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - return false; - } - return true; - } - - static bool InitDeviceExtensions(VkLayerTest &test, std::vector<const char *> &device_extension_names) { - std::array<const char *, 2> required_device_extensions = { - {VK_NV_RAY_TRACING_EXTENSION_NAME, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME}}; - for (auto device_extension : required_device_extensions) { - if (test.DeviceExtensionSupported(test.gpu(), nullptr, device_extension)) { - device_extension_names.push_back(device_extension); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension); - return false; - } - } - return true; - } - - void InitShaderGroups() { - { - VkRayTracingShaderGroupCreateInfoNV group = {}; - group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV; - group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV; - group.generalShader = 0; - group.closestHitShader = VK_SHADER_UNUSED_NV; - group.anyHitShader = VK_SHADER_UNUSED_NV; - group.intersectionShader = VK_SHADER_UNUSED_NV; - groups_.push_back(group); - } - { - VkRayTracingShaderGroupCreateInfoNV group = {}; - group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV; - group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV; - group.generalShader = VK_SHADER_UNUSED_NV; - group.closestHitShader = 1; - group.anyHitShader = VK_SHADER_UNUSED_NV; - group.intersectionShader = VK_SHADER_UNUSED_NV; - groups_.push_back(group); - } - { - VkRayTracingShaderGroupCreateInfoNV group = {}; - group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV; - group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV; - group.generalShader = 2; - group.closestHitShader = VK_SHADER_UNUSED_NV; - group.anyHitShader = VK_SHADER_UNUSED_NV; - group.intersectionShader = VK_SHADER_UNUSED_NV; - groups_.push_back(group); - } - } - - void InitDescriptorSetInfo() { - dsl_bindings_ = { - {0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_RAYGEN_BIT_NV, nullptr}, - {1, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV, 1, VK_SHADER_STAGE_RAYGEN_BIT_NV, nullptr}, - }; - } - - void InitPipelineLayoutInfo() { - pipeline_layout_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_ci_.setLayoutCount = 1; // Not really changeable because InitState() sets exactly one pSetLayout - pipeline_layout_ci_.pSetLayouts = nullptr; // must bound after it is created - } - - void InitShaderInfo() { // DONE - static const char rayGenShaderText[] = - "#version 460 core \n" - "#extension GL_NV_ray_tracing : require \n" - "layout(set = 0, binding = 0, rgba8) uniform image2D image; \n" - "layout(set = 0, binding = 1) uniform accelerationStructureNV as; \n" - " \n" - "layout(location = 0) rayPayloadNV float payload; \n" - " \n" - "void main() \n" - "{ \n" - " vec4 col = vec4(0, 0, 0, 1); \n" - " \n" - " vec3 origin = vec3(float(gl_LaunchIDNV.x)/float(gl_LaunchSizeNV.x), " - "float(gl_LaunchIDNV.y)/float(gl_LaunchSizeNV.y), " - "1.0); \n" - " vec3 dir = vec3(0.0, 0.0, -1.0); \n" - " \n" - " payload = 0.5; \n" - " traceNV(as, gl_RayFlagsCullBackFacingTrianglesNV, 0xff, 0, 1, 0, origin, 0.0, dir, 1000.0, 0); \n" - " \n" - " col.y = payload; \n" - " \n" - " imageStore(image, ivec2(gl_LaunchIDNV.xy), col); \n" - "}\n"; - - static char const closestHitShaderText[] = - "#version 460 core \n" - "#extension GL_NV_ray_tracing : require \n" - "layout(location = 0) rayPayloadInNV float hitValue; \n" - " \n" - "void main() { \n" - " hitValue = 1.0; \n" - "} \n"; - - static char const missShaderText[] = - "#version 460 core \n" - "#extension GL_NV_ray_tracing : require \n" - "layout(location = 0) rayPayloadInNV float hitValue; \n" - " \n" - "void main() { \n" - " hitValue = 0.0; \n" - "} \n"; - - rgs_.reset(new VkShaderObj(layer_test_.DeviceObj(), rayGenShaderText, VK_SHADER_STAGE_RAYGEN_BIT_NV, &layer_test_)); - chs_.reset( - new VkShaderObj(layer_test_.DeviceObj(), closestHitShaderText, VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV, &layer_test_)); - mis_.reset(new VkShaderObj(layer_test_.DeviceObj(), missShaderText, VK_SHADER_STAGE_MISS_BIT_NV, &layer_test_)); - - shader_stages_ = {rgs_->GetStageCreateInfo(), chs_->GetStageCreateInfo(), mis_->GetStageCreateInfo()}; - } - - void InitNVRayTracingPipelineInfo() { - rp_ci_.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV; - - rp_ci_.stageCount = shader_stages_.size(); - rp_ci_.pStages = shader_stages_.data(); - rp_ci_.groupCount = groups_.size(); - rp_ci_.pGroups = groups_.data(); - } - - void InitPipelineCacheInfo() { - pc_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - pc_ci_.pNext = nullptr; - pc_ci_.flags = 0; - pc_ci_.initialDataSize = 0; - pc_ci_.pInitialData = nullptr; - } - - void InitInfo() { - InitShaderGroups(); - InitDescriptorSetInfo(); - InitPipelineLayoutInfo(); - InitShaderInfo(); - InitNVRayTracingPipelineInfo(); - InitPipelineCacheInfo(); - } - - void InitState() { - VkResult err; - descriptor_set_.reset(new OneOffDescriptorSet(layer_test_.DeviceObj(), dsl_bindings_)); - ASSERT_TRUE(descriptor_set_->Initialized()); - - pipeline_layout_ = VkPipelineLayoutObj(layer_test_.DeviceObj(), {&descriptor_set_->layout_}); - - err = vkCreatePipelineCache(layer_test_.device(), &pc_ci_, NULL, &pipeline_cache_); - ASSERT_VK_SUCCESS(err); - } - - void LateBindPipelineInfo() { - // By value or dynamically located items must be late bound - rp_ci_.layout = pipeline_layout_.handle(); - rp_ci_.stageCount = shader_stages_.size(); - rp_ci_.pStages = shader_stages_.data(); - } - - VkResult CreateNVRayTracingPipeline(bool implicit_destroy = true, bool do_late_bind = true) { - VkResult err; - if (do_late_bind) { - LateBindPipelineInfo(); - } - if (implicit_destroy && (pipeline_ != VK_NULL_HANDLE)) { - vkDestroyPipeline(layer_test_.device(), pipeline_, nullptr); - pipeline_ = VK_NULL_HANDLE; - } - - PFN_vkCreateRayTracingPipelinesNV vkCreateRayTracingPipelinesNV = - (PFN_vkCreateRayTracingPipelinesNV)vkGetInstanceProcAddr(layer_test_.instance(), "vkCreateRayTracingPipelinesNV"); - err = vkCreateRayTracingPipelinesNV(layer_test_.device(), pipeline_cache_, 1, &rp_ci_, nullptr, &pipeline_); - return err; - } - - // Helper function to create a simple test case (positive or negative) - // - // info_override can be any callable that takes a CreateNVRayTracingPipelineHelper & - // flags, error can be any args accepted by "SetDesiredFailure". - template <typename Test, typename OverrideFunc, typename Error> - static void OneshotTest(Test &test, OverrideFunc &info_override, const std::vector<Error> &errors, - const VkFlags flags = VK_DEBUG_REPORT_ERROR_BIT_EXT) { - CreateNVRayTracingPipelineHelper helper(test); - helper.InitInfo(); - info_override(helper); - helper.InitState(); - - for (const auto &error : errors) test.Monitor()->SetDesiredFailureMsg(flags, error); - helper.CreateNVRayTracingPipeline(); - test.Monitor()->VerifyFound(); - } - - template <typename Test, typename OverrideFunc, typename Error> - static void OneshotTest(Test &test, OverrideFunc &info_override, Error error, - const VkFlags flags = VK_DEBUG_REPORT_ERROR_BIT_EXT) { - OneshotTest(test, info_override, std::vector<Error>(1, error), flags); - } - - template <typename Test, typename OverrideFunc> - static void OneshotPositiveTest(Test &test, OverrideFunc &info_override, - const VkDebugReportFlagsEXT message_flag_mask = VK_DEBUG_REPORT_ERROR_BIT_EXT) { - CreateNVRayTracingPipelineHelper helper(test); - helper.InitInfo(); - info_override(helper); - helper.InitState(); - - test.Monitor()->ExpectSuccess(message_flag_mask); - ASSERT_VK_SUCCESS(helper.CreateNVRayTracingPipeline()); - test.Monitor()->VerifyNotFound(); - } -}; - -namespace chain_util { -template <typename T> -T Init(const void *pnext_in = nullptr) { - T pnext_obj = {}; - pnext_obj.sType = LvlTypeMap<T>::kSType; - pnext_obj.pNext = pnext_in; - return pnext_obj; -} -class ExtensionChain { - const void *head_ = nullptr; - typedef std::function<bool(const char *)> AddIfFunction; - AddIfFunction add_if_; - typedef std::vector<const char *> List; - List *list_; - - public: - template <typename F> - ExtensionChain(F &add_if, List *list) : add_if_(add_if), list_(list) {} - template <typename T> - void Add(const char *name, T &obj) { - if (add_if_(name)) { - if (list_) { - list_->push_back(name); - } - obj.pNext = head_; - head_ = &obj; - } - } - const void *Head() const { return head_; } -}; -} // namespace chain_util - -// PushDescriptorProperties helper -VkPhysicalDevicePushDescriptorPropertiesKHR GetPushDescriptorProperties(VkInstance instance, VkPhysicalDevice gpu) { - // Find address of extension call and make the call -- assumes needed extensions are enabled. - PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR = - (PFN_vkGetPhysicalDeviceProperties2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2KHR"); - assert(vkGetPhysicalDeviceProperties2KHR != nullptr); - - // Get the push descriptor limits - auto push_descriptor_prop = lvl_init_struct<VkPhysicalDevicePushDescriptorPropertiesKHR>(); - auto prop2 = lvl_init_struct<VkPhysicalDeviceProperties2KHR>(&push_descriptor_prop); - vkGetPhysicalDeviceProperties2KHR(gpu, &prop2); - return push_descriptor_prop; -} - -// ******************************************************************************************************************** -// ******************************************************************************************************************** -// ******************************************************************************************************************** -// ******************************************************************************************************************** -TEST_F(VkLayerTest, RequiredParameter) { - TEST_DESCRIPTION("Specify VK_NULL_HANDLE, NULL, and 0 for required handle, pointer, array, and array count parameters"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "required parameter pFeatures specified as NULL"); - // Specify NULL for a pointer to a handle - // Expected to trigger an error with - // parameter_validation::validate_required_pointer - vkGetPhysicalDeviceFeatures(gpu(), NULL); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "required parameter pQueueFamilyPropertyCount specified as NULL"); - // Specify NULL for pointer to array count - // Expected to trigger an error with parameter_validation::validate_array - vkGetPhysicalDeviceQueueFamilyProperties(gpu(), NULL, NULL); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-viewportCount-arraylength"); - // Specify 0 for a required array count - // Expected to trigger an error with parameter_validation::validate_array - VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; - m_commandBuffer->SetViewport(0, 0, &viewport); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCreateImage-pCreateInfo-parameter"); - // Specify a null pImageCreateInfo struct pointer - VkImage test_image; - vkCreateImage(device(), NULL, NULL, &test_image); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-pViewports-parameter"); - // Specify NULL for a required array - // Expected to trigger an error with parameter_validation::validate_array - m_commandBuffer->SetViewport(0, 1, NULL); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "required parameter memory specified as VK_NULL_HANDLE"); - // Specify VK_NULL_HANDLE for a required handle - // Expected to trigger an error with - // parameter_validation::validate_required_handle - vkUnmapMemory(device(), VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "required parameter pFences[0] specified as VK_NULL_HANDLE"); - // Specify VK_NULL_HANDLE for a required handle array entry - // Expected to trigger an error with - // parameter_validation::validate_required_handle_array - VkFence fence = VK_NULL_HANDLE; - vkResetFences(device(), 1, &fence); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "required parameter pAllocateInfo specified as NULL"); - // Specify NULL for a required struct pointer - // Expected to trigger an error with - // parameter_validation::validate_struct_type - VkDeviceMemory memory = VK_NULL_HANDLE; - vkAllocateMemory(device(), NULL, NULL, &memory); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "value of faceMask must not be 0"); - // Specify 0 for a required VkFlags parameter - // Expected to trigger an error with parameter_validation::validate_flags - m_commandBuffer->SetStencilReference(0, 0); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "value of pSubmits[0].pWaitDstStageMask[0] must not be 0"); - // Specify 0 for a required VkFlags array entry - // Expected to trigger an error with - // parameter_validation::validate_flags_array - VkSemaphore semaphore = VK_NULL_HANDLE; - VkPipelineStageFlags stageFlags = 0; - VkSubmitInfo submitInfo = {}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.waitSemaphoreCount = 1; - submitInfo.pWaitSemaphores = &semaphore; - submitInfo.pWaitDstStageMask = &stageFlags; - vkQueueSubmit(m_device->m_queue, 1, &submitInfo, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkSubmitInfo-sType-sType"); - stageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - // Set a bogus sType and see what happens - submitInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - submitInfo.waitSemaphoreCount = 1; - submitInfo.pWaitSemaphores = &semaphore; - submitInfo.pWaitDstStageMask = &stageFlags; - vkQueueSubmit(m_device->m_queue, 1, &submitInfo, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkSubmitInfo-pWaitSemaphores-parameter"); - stageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.waitSemaphoreCount = 1; - // Set a null pointer for pWaitSemaphores - submitInfo.pWaitSemaphores = NULL; - submitInfo.pWaitDstStageMask = &stageFlags; - vkQueueSubmit(m_device->m_queue, 1, &submitInfo, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, PnextOnlyStructValidation) { - TEST_DESCRIPTION("See if checks occur on structs ONLY used in pnext chains."); - - if (!(CheckDescriptorIndexingSupportAndInitFramework(this, m_instance_extension_names, m_device_extension_names, NULL, - m_errorMonitor))) { - printf("Descriptor indexing or one of its dependencies not supported, skipping tests\n"); - return; - } - - PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = - (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR"); - ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr); - - // Create a device passing in a bad PdevFeatures2 value - auto indexing_features = lvl_init_struct<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>(); - auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&indexing_features); - vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2); - // Set one of the features values to an invalid boolean value - indexing_features.descriptorBindingUniformBufferUpdateAfterBind = 800; - - uint32_t queue_node_count; - vkGetPhysicalDeviceQueueFamilyProperties(gpu(), &queue_node_count, NULL); - VkQueueFamilyProperties *queue_props = new VkQueueFamilyProperties[queue_node_count]; - vkGetPhysicalDeviceQueueFamilyProperties(gpu(), &queue_node_count, queue_props); - float priorities[] = {1.0f}; - VkDeviceQueueCreateInfo queue_info{}; - queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_info.pNext = NULL; - queue_info.flags = 0; - queue_info.queueFamilyIndex = 0; - queue_info.queueCount = 1; - queue_info.pQueuePriorities = &priorities[0]; - VkDeviceCreateInfo dev_info = {}; - dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - dev_info.pNext = NULL; - dev_info.queueCreateInfoCount = 1; - dev_info.pQueueCreateInfos = &queue_info; - dev_info.enabledLayerCount = 0; - dev_info.ppEnabledLayerNames = NULL; - dev_info.enabledExtensionCount = m_device_extension_names.size(); - dev_info.ppEnabledExtensionNames = m_device_extension_names.data(); - dev_info.pNext = &features2; - VkDevice dev; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, "is neither VK_TRUE nor VK_FALSE"); - m_errorMonitor->SetUnexpectedError("Failed to create"); - vkCreateDevice(gpu(), &dev_info, NULL, &dev); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, ReservedParameter) { - TEST_DESCRIPTION("Specify a non-zero value for a reserved parameter"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " must be 0"); - // Specify 0 for a reserved VkFlags parameter - // Expected to trigger an error with - // parameter_validation::validate_reserved_flags - VkEvent event_handle = VK_NULL_HANDLE; - VkEventCreateInfo event_info = {}; - event_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - event_info.flags = 1; - vkCreateEvent(device(), &event_info, NULL, &event_handle); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, DebugMarkerNameTest) { - TEST_DESCRIPTION("Ensure debug marker object names are printed in debug report output"); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), "VK_LAYER_LUNARG_core_validation", VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_EXT_DEBUG_MARKER_EXTENSION_NAME); - } else { - printf("%s Debug Marker Extension not supported, skipping test\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - PFN_vkDebugMarkerSetObjectNameEXT fpvkDebugMarkerSetObjectNameEXT = - (PFN_vkDebugMarkerSetObjectNameEXT)vkGetInstanceProcAddr(instance(), "vkDebugMarkerSetObjectNameEXT"); - if (!(fpvkDebugMarkerSetObjectNameEXT)) { - printf("%s Can't find fpvkDebugMarkerSetObjectNameEXT; skipped.\n", kSkipPrefix); - return; - } - - if (DeviceSimulation()) { - printf("%sSkipping object naming test.\n", kSkipPrefix); - return; - } - - VkBuffer buffer; - VkDeviceMemory memory_1, memory_2; - std::string memory_name = "memory_name"; - - VkBufferCreateInfo buffer_create_info = {}; - buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_create_info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - buffer_create_info.size = 1; - - vkCreateBuffer(device(), &buffer_create_info, nullptr, &buffer); - - VkMemoryRequirements memRequirements; - vkGetBufferMemoryRequirements(device(), buffer, &memRequirements); - - VkMemoryAllocateInfo memory_allocate_info = {}; - memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_allocate_info.allocationSize = memRequirements.size; - memory_allocate_info.memoryTypeIndex = 0; - - vkAllocateMemory(device(), &memory_allocate_info, nullptr, &memory_1); - vkAllocateMemory(device(), &memory_allocate_info, nullptr, &memory_2); - - VkDebugMarkerObjectNameInfoEXT name_info = {}; - name_info.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT; - name_info.pNext = nullptr; - name_info.object = (uint64_t)memory_2; - name_info.objectType = VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT; - name_info.pObjectName = memory_name.c_str(); - fpvkDebugMarkerSetObjectNameEXT(device(), &name_info); - - vkBindBufferMemory(device(), buffer, memory_1, 0); - - // Test core_validation layer - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, memory_name); - vkBindBufferMemory(device(), buffer, memory_2, 0); - m_errorMonitor->VerifyFound(); - - vkFreeMemory(device(), memory_1, nullptr); - memory_1 = VK_NULL_HANDLE; - vkFreeMemory(device(), memory_2, nullptr); - memory_2 = VK_NULL_HANDLE; - vkDestroyBuffer(device(), buffer, nullptr); - buffer = VK_NULL_HANDLE; - - VkCommandBuffer commandBuffer; - std::string commandBuffer_name = "command_buffer_name"; - VkCommandPool commandpool_1; - VkCommandPool commandpool_2; - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - vkCreateCommandPool(device(), &pool_create_info, nullptr, &commandpool_1); - vkCreateCommandPool(device(), &pool_create_info, nullptr, &commandpool_2); - - VkCommandBufferAllocateInfo command_buffer_allocate_info{}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = commandpool_1; - command_buffer_allocate_info.commandBufferCount = 1; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(device(), &command_buffer_allocate_info, &commandBuffer); - - name_info.object = (uint64_t)commandBuffer; - name_info.objectType = VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT; - name_info.pObjectName = commandBuffer_name.c_str(); - fpvkDebugMarkerSetObjectNameEXT(device(), &name_info); - - VkCommandBufferBeginInfo cb_begin_Info = {}; - cb_begin_Info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - cb_begin_Info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - vkBeginCommandBuffer(commandBuffer, &cb_begin_Info); - - const VkRect2D scissor = {{-1, 0}, {16, 16}}; - const VkRect2D scissors[] = {scissor, scissor}; - - // Test parameter_validation layer - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, commandBuffer_name); - vkCmdSetScissor(commandBuffer, 1, 1, scissors); - m_errorMonitor->VerifyFound(); - - // Test object_tracker layer - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, commandBuffer_name); - vkFreeCommandBuffers(device(), commandpool_2, 1, &commandBuffer); - m_errorMonitor->VerifyFound(); - - vkDestroyCommandPool(device(), commandpool_1, NULL); - vkDestroyCommandPool(device(), commandpool_2, NULL); -} - -struct DebugUtilsLabelCheckData { - std::function<void(const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, DebugUtilsLabelCheckData *)> callback; - size_t count; -}; - -bool operator==(const VkDebugUtilsLabelEXT &rhs, const VkDebugUtilsLabelEXT &lhs) { - bool is_equal = (rhs.color[0] == lhs.color[0]) && (rhs.color[1] == lhs.color[1]) && (rhs.color[2] == lhs.color[2]) && - (rhs.color[3] == lhs.color[3]); - if (is_equal) { - if (rhs.pLabelName && lhs.pLabelName) { - is_equal = (0 == strcmp(rhs.pLabelName, lhs.pLabelName)); - } else { - is_equal = (rhs.pLabelName == nullptr) && (lhs.pLabelName == nullptr); - } - } - return is_equal; -} - -VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, - VkDebugUtilsMessageTypeFlagsEXT messageTypes, - const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData) { - auto *data = reinterpret_cast<DebugUtilsLabelCheckData *>(pUserData); - data->callback(pCallbackData, data); - return VK_FALSE; -} - -TEST_F(VkLayerTest, DebugUtilsNameTest) { - TEST_DESCRIPTION("Ensure debug utils object names are printed in debug messenger output"); - - // Skip test if extension not supported - if (InstanceExtensionSupported(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); - } else { - printf("%s Debug Utils Extension not supported, skipping test\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - ASSERT_NO_FATAL_FAILURE(InitState()); - - PFN_vkSetDebugUtilsObjectNameEXT fpvkSetDebugUtilsObjectNameEXT = - (PFN_vkSetDebugUtilsObjectNameEXT)vkGetInstanceProcAddr(instance(), "vkSetDebugUtilsObjectNameEXT"); - ASSERT_TRUE(fpvkSetDebugUtilsObjectNameEXT); // Must be extant if extension is enabled - PFN_vkCreateDebugUtilsMessengerEXT fpvkCreateDebugUtilsMessengerEXT = - (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance(), "vkCreateDebugUtilsMessengerEXT"); - ASSERT_TRUE(fpvkCreateDebugUtilsMessengerEXT); // Must be extant if extension is enabled - PFN_vkDestroyDebugUtilsMessengerEXT fpvkDestroyDebugUtilsMessengerEXT = - (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance(), "vkDestroyDebugUtilsMessengerEXT"); - ASSERT_TRUE(fpvkDestroyDebugUtilsMessengerEXT); // Must be extant if extension is enabled - PFN_vkCmdInsertDebugUtilsLabelEXT fpvkCmdInsertDebugUtilsLabelEXT = - (PFN_vkCmdInsertDebugUtilsLabelEXT)vkGetInstanceProcAddr(instance(), "vkCmdInsertDebugUtilsLabelEXT"); - ASSERT_TRUE(fpvkCmdInsertDebugUtilsLabelEXT); // Must be extant if extension is enabled - - if (DeviceSimulation()) { - printf("%sSkipping object naming test.\n", kSkipPrefix); - return; - } - - DebugUtilsLabelCheckData callback_data; - auto empty_callback = [](const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, DebugUtilsLabelCheckData *data) { - data->count++; - }; - callback_data.count = 0; - callback_data.callback = empty_callback; - - auto callback_create_info = lvl_init_struct<VkDebugUtilsMessengerCreateInfoEXT>(); - callback_create_info.messageSeverity = - VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT; - callback_create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT; - callback_create_info.pfnUserCallback = DebugUtilsCallback; - callback_create_info.pUserData = &callback_data; - VkDebugUtilsMessengerEXT my_messenger = VK_NULL_HANDLE; - fpvkCreateDebugUtilsMessengerEXT(instance(), &callback_create_info, nullptr, &my_messenger); - - VkBuffer buffer; - VkDeviceMemory memory_1, memory_2; - std::string memory_name = "memory_name"; - - VkBufferCreateInfo buffer_create_info = {}; - buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_create_info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - buffer_create_info.size = 1; - - vkCreateBuffer(device(), &buffer_create_info, nullptr, &buffer); - - VkMemoryRequirements memRequirements; - vkGetBufferMemoryRequirements(device(), buffer, &memRequirements); - - VkMemoryAllocateInfo memory_allocate_info = {}; - memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_allocate_info.allocationSize = memRequirements.size; - memory_allocate_info.memoryTypeIndex = 0; - - vkAllocateMemory(device(), &memory_allocate_info, nullptr, &memory_1); - vkAllocateMemory(device(), &memory_allocate_info, nullptr, &memory_2); - - VkDebugUtilsObjectNameInfoEXT name_info = {}; - name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; - name_info.pNext = nullptr; - name_info.objectHandle = (uint64_t)memory_2; - name_info.objectType = VK_OBJECT_TYPE_DEVICE_MEMORY; - name_info.pObjectName = memory_name.c_str(); - fpvkSetDebugUtilsObjectNameEXT(device(), &name_info); - - vkBindBufferMemory(device(), buffer, memory_1, 0); - - // Test core_validation layer - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, memory_name); - vkBindBufferMemory(device(), buffer, memory_2, 0); - m_errorMonitor->VerifyFound(); - - vkFreeMemory(device(), memory_1, nullptr); - memory_1 = VK_NULL_HANDLE; - vkFreeMemory(device(), memory_2, nullptr); - memory_2 = VK_NULL_HANDLE; - vkDestroyBuffer(device(), buffer, nullptr); - buffer = VK_NULL_HANDLE; - - VkCommandBuffer commandBuffer; - std::string commandBuffer_name = "command_buffer_name"; - VkCommandPool commandpool_1; - VkCommandPool commandpool_2; - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - vkCreateCommandPool(device(), &pool_create_info, nullptr, &commandpool_1); - vkCreateCommandPool(device(), &pool_create_info, nullptr, &commandpool_2); - - VkCommandBufferAllocateInfo command_buffer_allocate_info{}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = commandpool_1; - command_buffer_allocate_info.commandBufferCount = 1; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(device(), &command_buffer_allocate_info, &commandBuffer); - - name_info.objectHandle = (uint64_t)commandBuffer; - name_info.objectType = VK_OBJECT_TYPE_COMMAND_BUFFER; - name_info.pObjectName = commandBuffer_name.c_str(); - fpvkSetDebugUtilsObjectNameEXT(device(), &name_info); - - VkCommandBufferBeginInfo cb_begin_Info = {}; - cb_begin_Info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - cb_begin_Info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - vkBeginCommandBuffer(commandBuffer, &cb_begin_Info); - - const VkRect2D scissor = {{-1, 0}, {16, 16}}; - const VkRect2D scissors[] = {scissor, scissor}; - - auto command_label = lvl_init_struct<VkDebugUtilsLabelEXT>(); - command_label.pLabelName = "Command Label 0123"; - command_label.color[0] = 0.; - command_label.color[1] = 1.; - command_label.color[2] = 2.; - command_label.color[3] = 3.0; - bool command_label_test = false; - auto command_label_callback = [command_label, &command_label_test](const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, - DebugUtilsLabelCheckData *data) { - data->count++; - command_label_test = false; - if (pCallbackData->cmdBufLabelCount == 1) { - command_label_test = pCallbackData->pCmdBufLabels[0] == command_label; - } - }; - callback_data.callback = command_label_callback; - - fpvkCmdInsertDebugUtilsLabelEXT(commandBuffer, &command_label); - // Test parameter_validation layer - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, commandBuffer_name); - vkCmdSetScissor(commandBuffer, 1, 1, scissors); - m_errorMonitor->VerifyFound(); - - // Check the label test - if (!command_label_test) { - ADD_FAILURE() << "Command label '" << command_label.pLabelName << "' not passed to callback."; - } - - // Test object_tracker layer - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, commandBuffer_name); - vkFreeCommandBuffers(device(), commandpool_2, 1, &commandBuffer); - m_errorMonitor->VerifyFound(); - - vkDestroyCommandPool(device(), commandpool_1, NULL); - vkDestroyCommandPool(device(), commandpool_2, NULL); - fpvkDestroyDebugUtilsMessengerEXT(instance(), my_messenger, nullptr); -} - -TEST_F(VkLayerTest, InvalidStructSType) { - TEST_DESCRIPTION("Specify an invalid VkStructureType for a Vulkan structure's sType field"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "parameter pAllocateInfo->sType must be"); - // Zero struct memory, effectively setting sType to - // VK_STRUCTURE_TYPE_APPLICATION_INFO - // Expected to trigger an error with - // parameter_validation::validate_struct_type - VkMemoryAllocateInfo alloc_info = {}; - VkDeviceMemory memory = VK_NULL_HANDLE; - vkAllocateMemory(device(), &alloc_info, NULL, &memory); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "parameter pSubmits[0].sType must be"); - // Zero struct memory, effectively setting sType to - // VK_STRUCTURE_TYPE_APPLICATION_INFO - // Expected to trigger an error with - // parameter_validation::validate_struct_type_array - VkSubmitInfo submit_info = {}; - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, InvalidStructPNext) { - TEST_DESCRIPTION("Specify an invalid value for a Vulkan structure's pNext field"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, "value of pCreateInfo->pNext must be NULL"); - // Set VkMemoryAllocateInfo::pNext to a non-NULL value, when pNext must be NULL. - // Need to pick a function that has no allowed pNext structure types. - // Expected to trigger an error with parameter_validation::validate_struct_pnext - VkEvent event = VK_NULL_HANDLE; - VkEventCreateInfo event_alloc_info = {}; - // Zero-initialization will provide the correct sType - VkApplicationInfo app_info = {}; - event_alloc_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - event_alloc_info.pNext = &app_info; - vkCreateEvent(device(), &event_alloc_info, NULL, &event); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, - " chain includes a structure with unexpected VkStructureType "); - // Set VkMemoryAllocateInfo::pNext to a non-NULL value, but use - // a function that has allowed pNext structure types and specify - // a structure type that is not allowed. - // Expected to trigger an error with parameter_validation::validate_struct_pnext - VkDeviceMemory memory = VK_NULL_HANDLE; - VkMemoryAllocateInfo memory_alloc_info = {}; - memory_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_alloc_info.pNext = &app_info; - vkAllocateMemory(device(), &memory_alloc_info, NULL, &memory); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, UnrecognizedValueOutOfRange) { - ASSERT_NO_FATAL_FAILURE(Init()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "does not fall within the begin..end range of the core VkFormat enumeration tokens"); - // Specify an invalid VkFormat value - // Expected to trigger an error with - // parameter_validation::validate_ranged_enum - VkFormatProperties format_properties; - vkGetPhysicalDeviceFormatProperties(gpu(), static_cast<VkFormat>(8000), &format_properties); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, UnrecognizedValueBadMask) { - ASSERT_NO_FATAL_FAILURE(Init()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "contains flag bits that are not recognized members of"); - // Specify an invalid VkFlags bitmask value - // Expected to trigger an error with parameter_validation::validate_flags - VkImageFormatProperties image_format_properties; - vkGetPhysicalDeviceImageFormatProperties(gpu(), VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, - static_cast<VkImageUsageFlags>(1 << 25), 0, &image_format_properties); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, UnrecognizedValueBadFlag) { - ASSERT_NO_FATAL_FAILURE(Init()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "contains flag bits that are not recognized members of"); - // Specify an invalid VkFlags array entry - // Expected to trigger an error with parameter_validation::validate_flags_array - VkSemaphore semaphore; - VkSemaphoreCreateInfo semaphore_create_info{}; - semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - vkCreateSemaphore(m_device->device(), &semaphore_create_info, nullptr, &semaphore); - // `stage_flags` is set to a value which, currently, is not a defined stage flag - // `VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM` works well for this - VkPipelineStageFlags stage_flags = VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM; - // `waitSemaphoreCount` *must* be greater than 0 to perform this check - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &semaphore; - submit_info.pWaitDstStageMask = &stage_flags; - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - vkDestroySemaphore(m_device->device(), semaphore, nullptr); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, UnrecognizedValueBadBool) { - // Make sure using VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE doesn't trigger a false positive. - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME); - } else { - printf("%s VK_KHR_sampler_mirror_clamp_to_edge extension not supported, skipping test\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, "is neither VK_TRUE nor VK_FALSE"); - // Specify an invalid VkBool32 value, expecting a warning with parameter_validation::validate_bool32 - VkSampler sampler = VK_NULL_HANDLE; - VkSamplerCreateInfo sampler_info = SafeSaneSamplerCreateInfo(); - sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; - sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; - sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; - - // Not VK_TRUE or VK_FALSE - sampler_info.anisotropyEnable = 3; - vkCreateSampler(m_device->device(), &sampler_info, NULL, &sampler); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, MirrorClampToEdgeNotEnabled) { - TEST_DESCRIPTION("Validation should catch using CLAMP_TO_EDGE addressing mode if the extension is not enabled."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkSamplerCreateInfo-addressModeU-01079"); - VkSampler sampler = VK_NULL_HANDLE; - VkSamplerCreateInfo sampler_info = SafeSaneSamplerCreateInfo(); - // Set the modes to cause the error - sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; - sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; - sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; - - vkCreateSampler(m_device->device(), &sampler_info, NULL, &sampler); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, AnisotropyFeatureDisabled) { - TEST_DESCRIPTION("Validation should check anisotropy parameters are correct with samplerAnisotropy disabled."); - - // Determine if required device features are available - VkPhysicalDeviceFeatures device_features = {}; - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features)); - device_features.samplerAnisotropy = VK_FALSE; // force anisotropy off - ASSERT_NO_FATAL_FAILURE(InitState(&device_features)); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkSamplerCreateInfo-anisotropyEnable-01070"); - VkSamplerCreateInfo sampler_info = SafeSaneSamplerCreateInfo(); - // With the samplerAnisotropy disable, the sampler must not enable it. - sampler_info.anisotropyEnable = VK_TRUE; - VkSampler sampler = VK_NULL_HANDLE; - - VkResult err; - err = vkCreateSampler(m_device->device(), &sampler_info, NULL, &sampler); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == err) { - vkDestroySampler(m_device->device(), sampler, NULL); - } - sampler = VK_NULL_HANDLE; -} - -TEST_F(VkLayerTest, AnisotropyFeatureEnabled) { - TEST_DESCRIPTION("Validation must check several conditions that apply only when Anisotropy is enabled."); - - // Determine if required device features are available - VkPhysicalDeviceFeatures device_features = {}; - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features)); - - // These tests require that the device support anisotropic filtering - if (VK_TRUE != device_features.samplerAnisotropy) { - printf("%s Test requires unsupported samplerAnisotropy feature. Skipped.\n", kSkipPrefix); - return; - } - - bool cubic_support = false; - if (DeviceExtensionSupported(gpu(), nullptr, "VK_IMG_filter_cubic")) { - m_device_extension_names.push_back("VK_IMG_filter_cubic"); - cubic_support = true; - } - - VkSamplerCreateInfo sampler_info_ref = SafeSaneSamplerCreateInfo(); - sampler_info_ref.anisotropyEnable = VK_TRUE; - VkSamplerCreateInfo sampler_info = sampler_info_ref; - ASSERT_NO_FATAL_FAILURE(InitState()); - - auto do_test = [this](std::string code, const VkSamplerCreateInfo *pCreateInfo) -> void { - VkResult err; - VkSampler sampler = VK_NULL_HANDLE; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, code); - err = vkCreateSampler(m_device->device(), pCreateInfo, NULL, &sampler); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == err) { - vkDestroySampler(m_device->device(), sampler, NULL); - } - }; - - // maxAnisotropy out-of-bounds low. - sampler_info.maxAnisotropy = NearestSmaller(1.0F); - do_test("VUID-VkSamplerCreateInfo-anisotropyEnable-01071", &sampler_info); - sampler_info.maxAnisotropy = sampler_info_ref.maxAnisotropy; - - // maxAnisotropy out-of-bounds high. - sampler_info.maxAnisotropy = NearestGreater(m_device->phy().properties().limits.maxSamplerAnisotropy); - do_test("VUID-VkSamplerCreateInfo-anisotropyEnable-01071", &sampler_info); - sampler_info.maxAnisotropy = sampler_info_ref.maxAnisotropy; - - // Both anisotropy and unnormalized coords enabled - sampler_info.unnormalizedCoordinates = VK_TRUE; - // If unnormalizedCoordinates is VK_TRUE, minLod and maxLod must be zero - sampler_info.minLod = 0; - sampler_info.maxLod = 0; - do_test("VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01076", &sampler_info); - sampler_info.unnormalizedCoordinates = sampler_info_ref.unnormalizedCoordinates; - - // Both anisotropy and cubic filtering enabled - if (cubic_support) { - sampler_info.minFilter = VK_FILTER_CUBIC_IMG; - do_test("VUID-VkSamplerCreateInfo-magFilter-01081", &sampler_info); - sampler_info.minFilter = sampler_info_ref.minFilter; - - sampler_info.magFilter = VK_FILTER_CUBIC_IMG; - do_test("VUID-VkSamplerCreateInfo-magFilter-01081", &sampler_info); - sampler_info.magFilter = sampler_info_ref.magFilter; - } else { - printf("%s Test requires unsupported extension \"VK_IMG_filter_cubic\". Skipped.\n", kSkipPrefix); - } -} - -TEST_F(VkLayerTest, UnnormalizedCoordinatesEnabled) { - TEST_DESCRIPTION("Validate restrictions on sampler parameters when unnormalizedCoordinates is true."); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - VkSamplerCreateInfo sampler_info_ref = SafeSaneSamplerCreateInfo(); - sampler_info_ref.unnormalizedCoordinates = VK_TRUE; - sampler_info_ref.minLod = 0.0f; - sampler_info_ref.maxLod = 0.0f; - VkSamplerCreateInfo sampler_info = sampler_info_ref; - ASSERT_NO_FATAL_FAILURE(InitState()); - - auto do_test = [this](std::string code, const VkSamplerCreateInfo *pCreateInfo) -> void { - VkResult err; - VkSampler sampler = VK_NULL_HANDLE; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, code); - err = vkCreateSampler(m_device->device(), pCreateInfo, NULL, &sampler); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == err) { - vkDestroySampler(m_device->device(), sampler, NULL); - } - }; - - // min and mag filters must be the same - sampler_info.minFilter = VK_FILTER_NEAREST; - sampler_info.magFilter = VK_FILTER_LINEAR; - do_test("VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01072", &sampler_info); - std::swap(sampler_info.minFilter, sampler_info.magFilter); - do_test("VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01072", &sampler_info); - sampler_info = sampler_info_ref; - - // mipmapMode must be NEAREST - sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - do_test("VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01073", &sampler_info); - sampler_info = sampler_info_ref; - - // minlod and maxlod must be zero - sampler_info.maxLod = 3.14159f; - do_test("VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01074", &sampler_info); - sampler_info.minLod = 2.71828f; - do_test("VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01074", &sampler_info); - sampler_info = sampler_info_ref; - - // addressModeU and addressModeV must both be CLAMP_TO_EDGE or CLAMP_TO_BORDER - // checks all 12 invalid combinations out of 16 total combinations - const std::array<VkSamplerAddressMode, 4> kAddressModes = {{ - VK_SAMPLER_ADDRESS_MODE_REPEAT, - VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, - }}; - for (const auto umode : kAddressModes) { - for (const auto vmode : kAddressModes) { - if ((umode != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE && umode != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) || - (vmode != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE && vmode != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)) { - sampler_info.addressModeU = umode; - sampler_info.addressModeV = vmode; - do_test("VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01075", &sampler_info); - } - } - } - sampler_info = sampler_info_ref; - - // VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01076 is tested in AnisotropyFeatureEnabled above - // Since it requires checking/enabling the anisotropic filtering feature, it's easier to do it - // with the other anisotropic tests. - - // compareEnable must be VK_FALSE - sampler_info.compareEnable = VK_TRUE; - do_test("VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01077", &sampler_info); - sampler_info = sampler_info_ref; -} - -TEST_F(VkLayerTest, UnrecognizedValueMaxEnum) { - ASSERT_NO_FATAL_FAILURE(Init()); - - // Specify MAX_ENUM - VkFormatProperties format_properties; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "does not fall within the begin..end range"); - vkGetPhysicalDeviceFormatProperties(gpu(), VK_FORMAT_MAX_ENUM, &format_properties); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, UpdateBufferAlignment) { - TEST_DESCRIPTION("Check alignment parameters for vkCmdUpdateBuffer"); - uint32_t updateData[] = {1, 2, 3, 4, 5, 6, 7, 8}; - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; - VkBufferObj buffer; - buffer.init_as_dst(*m_device, (VkDeviceSize)20, reqs); - - m_commandBuffer->begin(); - // Introduce failure by using dstOffset that is not multiple of 4 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " is not a multiple of 4"); - m_commandBuffer->UpdateBuffer(buffer.handle(), 1, 4, updateData); - m_errorMonitor->VerifyFound(); - - // Introduce failure by using dataSize that is not multiple of 4 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " is not a multiple of 4"); - m_commandBuffer->UpdateBuffer(buffer.handle(), 0, 6, updateData); - m_errorMonitor->VerifyFound(); - - // Introduce failure by using dataSize that is < 0 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "must be greater than zero and less than or equal to 65536"); - m_commandBuffer->UpdateBuffer(buffer.handle(), 0, (VkDeviceSize)-44, updateData); - m_errorMonitor->VerifyFound(); - - // Introduce failure by using dataSize that is > 65536 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "must be greater than zero and less than or equal to 65536"); - m_commandBuffer->UpdateBuffer(buffer.handle(), 0, (VkDeviceSize)80000, updateData); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, FillBufferAlignment) { - TEST_DESCRIPTION("Check alignment parameters for vkCmdFillBuffer"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; - VkBufferObj buffer; - buffer.init_as_dst(*m_device, (VkDeviceSize)20, reqs); - - m_commandBuffer->begin(); - - // Introduce failure by using dstOffset that is not multiple of 4 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " is not a multiple of 4"); - m_commandBuffer->FillBuffer(buffer.handle(), 1, 4, 0x11111111); - m_errorMonitor->VerifyFound(); - - // Introduce failure by using size that is not multiple of 4 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " is not a multiple of 4"); - m_commandBuffer->FillBuffer(buffer.handle(), 0, 6, 0x11111111); - m_errorMonitor->VerifyFound(); - - // Introduce failure by using size that is zero - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "must be greater than zero"); - m_commandBuffer->FillBuffer(buffer.handle(), 0, 0, 0x11111111); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, PSOPolygonModeInvalid) { - TEST_DESCRIPTION("Attempt to use a non-solid polygon fill mode in a pipeline when this feature is not enabled."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - std::vector<const char *> device_extension_names; - auto features = m_device->phy().features(); - // Artificially disable support for non-solid fill modes - features.fillModeNonSolid = VK_FALSE; - // The sacrificial device object - VkDeviceObj test_device(0, gpu(), device_extension_names, &features); - - VkRenderpassObj render_pass(&test_device); - - const VkPipelineLayoutObj pipeline_layout(&test_device); - - VkPipelineRasterizationStateCreateInfo rs_ci = {}; - rs_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rs_ci.pNext = nullptr; - rs_ci.lineWidth = 1.0f; - rs_ci.rasterizerDiscardEnable = VK_TRUE; - - VkShaderObj vs(&test_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(&test_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - // Set polygonMode to unsupported value POINT, should fail - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "polygonMode cannot be VK_POLYGON_MODE_POINT or VK_POLYGON_MODE_LINE"); - { - VkPipelineObj pipe(&test_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - // Introduce failure by setting unsupported polygon mode - rs_ci.polygonMode = VK_POLYGON_MODE_POINT; - pipe.SetRasterization(&rs_ci); - pipe.CreateVKPipeline(pipeline_layout.handle(), render_pass.handle()); - } - m_errorMonitor->VerifyFound(); - - // Try again with polygonMode=LINE, should fail - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "polygonMode cannot be VK_POLYGON_MODE_POINT or VK_POLYGON_MODE_LINE"); - { - VkPipelineObj pipe(&test_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - // Introduce failure by setting unsupported polygon mode - rs_ci.polygonMode = VK_POLYGON_MODE_LINE; - pipe.SetRasterization(&rs_ci); - pipe.CreateVKPipeline(pipeline_layout.handle(), render_pass.handle()); - } - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, SparseBindingImageBufferCreate) { - TEST_DESCRIPTION("Create buffer/image with sparse attributes but without the sparse_binding bit set"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkBuffer buffer; - VkBufferCreateInfo buf_info = {}; - buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buf_info.pNext = NULL; - buf_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - buf_info.size = 2048; - buf_info.queueFamilyIndexCount = 0; - buf_info.pQueueFamilyIndices = NULL; - buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - if (m_device->phy().features().sparseResidencyBuffer) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferCreateInfo-flags-00918"); - - buf_info.flags = VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT; - vkCreateBuffer(m_device->device(), &buf_info, NULL, &buffer); - m_errorMonitor->VerifyFound(); - } else { - printf("%s Test requires unsupported sparseResidencyBuffer feature. Skipped.\n", kSkipPrefix); - return; - } - - if (m_device->phy().features().sparseResidencyAliased) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferCreateInfo-flags-00918"); - - buf_info.flags = VK_BUFFER_CREATE_SPARSE_ALIASED_BIT; - vkCreateBuffer(m_device->device(), &buf_info, NULL, &buffer); - m_errorMonitor->VerifyFound(); - } else { - printf("%s Test requires unsupported sparseResidencyAliased feature. Skipped.\n", kSkipPrefix); - return; - } - - VkImage image; - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; - image_create_info.extent.width = 512; - image_create_info.extent.height = 64; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - image_create_info.queueFamilyIndexCount = 0; - image_create_info.pQueueFamilyIndices = NULL; - image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - if (m_device->phy().features().sparseResidencyImage2D) { - image_create_info.flags = VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-flags-00987"); - vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - } else { - printf("%s Test requires unsupported sparseResidencyImage2D feature. Skipped.\n", kSkipPrefix); - return; - } - - if (m_device->phy().features().sparseResidencyAliased) { - image_create_info.flags = VK_IMAGE_CREATE_SPARSE_ALIASED_BIT; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-flags-00987"); - vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - } else { - printf("%s Test requires unsupported sparseResidencyAliased feature. Skipped.\n", kSkipPrefix); - return; - } -} - -TEST_F(VkLayerTest, SparseResidencyImageCreateUnsupportedTypes) { - TEST_DESCRIPTION("Create images with sparse residency with unsupported types"); - - // Determine which device feature are available - VkPhysicalDeviceFeatures device_features = {}; - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features)); - - // Mask out device features we don't want and initialize device state - device_features.sparseResidencyImage2D = VK_FALSE; - device_features.sparseResidencyImage3D = VK_FALSE; - ASSERT_NO_FATAL_FAILURE(InitState(&device_features)); - - if (!m_device->phy().features().sparseBinding) { - printf("%s Test requires unsupported sparseBinding feature. Skipped.\n", kSkipPrefix); - return; - } - - VkImage image = VK_NULL_HANDLE; - VkResult result = VK_RESULT_MAX_ENUM; - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_1D; - image_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; - image_create_info.extent.width = 512; - image_create_info.extent.height = 1; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - image_create_info.queueFamilyIndexCount = 0; - image_create_info.pQueueFamilyIndices = NULL; - image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_create_info.flags = VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT | VK_BUFFER_CREATE_SPARSE_BINDING_BIT; - - // 1D image w/ sparse residency is an error - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-imageType-00970"); - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } - - // 2D image w/ sparse residency when feature isn't available - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.extent.height = 64; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-imageType-00971"); - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } - - // 3D image w/ sparse residency when feature isn't available - image_create_info.imageType = VK_IMAGE_TYPE_3D; - image_create_info.extent.depth = 8; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-imageType-00972"); - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } -} - -TEST_F(VkLayerTest, SparseResidencyImageCreateUnsupportedSamples) { - TEST_DESCRIPTION("Create images with sparse residency with unsupported tiling or sample counts"); - - // Determine which device feature are available - VkPhysicalDeviceFeatures device_features = {}; - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features)); - - // These tests require that the device support sparse residency for 2D images - if (VK_TRUE != device_features.sparseResidencyImage2D) { - printf("%s Test requires unsupported SparseResidencyImage2D feature. Skipped.\n", kSkipPrefix); - return; - } - - // Mask out device features we don't want and initialize device state - device_features.sparseResidency2Samples = VK_FALSE; - device_features.sparseResidency4Samples = VK_FALSE; - device_features.sparseResidency8Samples = VK_FALSE; - device_features.sparseResidency16Samples = VK_FALSE; - ASSERT_NO_FATAL_FAILURE(InitState(&device_features)); - - VkImage image = VK_NULL_HANDLE; - VkResult result = VK_RESULT_MAX_ENUM; - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; - image_create_info.extent.width = 64; - image_create_info.extent.height = 64; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_LINEAR; - image_create_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - image_create_info.queueFamilyIndexCount = 0; - image_create_info.pQueueFamilyIndices = NULL; - image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_create_info.flags = VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT | VK_BUFFER_CREATE_SPARSE_BINDING_BIT; - - // 2D image w/ sparse residency and linear tiling is an error - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT then image tiling of VK_IMAGE_TILING_LINEAR is not supported"); - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - - // Multi-sample image w/ sparse residency when feature isn't available (4 flavors) - image_create_info.samples = VK_SAMPLE_COUNT_2_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-imageType-00973"); - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } - - image_create_info.samples = VK_SAMPLE_COUNT_4_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-imageType-00974"); - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } - - image_create_info.samples = VK_SAMPLE_COUNT_8_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-imageType-00975"); - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } - - image_create_info.samples = VK_SAMPLE_COUNT_16_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-imageType-00976"); - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } -} - -TEST_F(VkLayerTest, GpuValidationArrayOOB) { - TEST_DESCRIPTION( - "GPU validation: Verify detection of out-of-bounds descriptor array indexing and use of uninitialized descriptors."); - if (!VkRenderFramework::DeviceCanDraw()) { - printf("%s GPU-Assisted validation test requires a driver that can draw.\n", kSkipPrefix); - return; - } - - VkValidationFeatureEnableEXT enables[] = {VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT}; - VkValidationFeaturesEXT features = {}; - features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT; - features.enabledValidationFeatureCount = 1; - features.pEnabledValidationFeatures = enables; - bool descriptor_indexing = CheckDescriptorIndexingSupportAndInitFramework(this, m_instance_extension_names, - m_device_extension_names, &features, m_errorMonitor); - VkPhysicalDeviceFeatures2KHR features2 = {}; - auto indexing_features = lvl_init_struct<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>(); - if (descriptor_indexing) { - PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = - (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR"); - ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr); - - features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&indexing_features); - vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2); - - if (!indexing_features.runtimeDescriptorArray || !indexing_features.descriptorBindingSampledImageUpdateAfterBind || - !indexing_features.descriptorBindingPartiallyBound || !indexing_features.descriptorBindingVariableDescriptorCount) { - printf("Not all descriptor indexing features supported, skipping descriptor indexing tests\n"); - descriptor_indexing = false; - } - } - - VkCommandPoolCreateFlags pool_flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2, pool_flags)); - if (m_device->props.apiVersion < VK_API_VERSION_1_1) { - printf("%s GPU-Assisted validation test requires Vulkan 1.1+.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Make a uniform buffer to be passed to the shader that contains the invalid array index. - uint32_t qfi = 0; - VkBufferCreateInfo bci = {}; - bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bci.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - bci.size = 1024; - bci.queueFamilyIndexCount = 1; - bci.pQueueFamilyIndices = &qfi; - VkBufferObj buffer0; - VkMemoryPropertyFlags mem_props = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - buffer0.init(*m_device, bci, mem_props); - - void *layout_pnext = nullptr; - void *allocate_pnext = nullptr; - auto pool_create_flags = 0; - auto layout_create_flags = 0; - VkDescriptorBindingFlagsEXT ds_binding_flags[2] = {}; - VkDescriptorSetLayoutBindingFlagsCreateInfoEXT layout_createinfo_binding_flags[1] = {}; - if (descriptor_indexing) { - ds_binding_flags[0] = 0; - ds_binding_flags[1] = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT; - - layout_createinfo_binding_flags[0].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT; - layout_createinfo_binding_flags[0].pNext = NULL; - layout_createinfo_binding_flags[0].bindingCount = 2; - layout_createinfo_binding_flags[0].pBindingFlags = ds_binding_flags; - layout_create_flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT; - pool_create_flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT; - layout_pnext = layout_createinfo_binding_flags; - } - - // Prepare descriptors - OneOffDescriptorSet ds(m_device, - { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - {1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 6, VK_SHADER_STAGE_ALL, nullptr}, - }, - layout_create_flags, layout_pnext, pool_create_flags); - - VkDescriptorSetVariableDescriptorCountAllocateInfoEXT variable_count = {}; - uint32_t desc_counts; - if (descriptor_indexing) { - layout_create_flags = 0; - pool_create_flags = 0; - ds_binding_flags[1] = - VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT; - desc_counts = 6; // We'll reserve 8 spaces in the layout, but the descriptor will only use 6 - variable_count.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT; - variable_count.descriptorSetCount = 1; - variable_count.pDescriptorCounts = &desc_counts; - allocate_pnext = &variable_count; - } - - OneOffDescriptorSet ds_variable(m_device, - { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - {1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 8, VK_SHADER_STAGE_ALL, nullptr}, - }, - layout_create_flags, layout_pnext, pool_create_flags, allocate_pnext); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - const VkPipelineLayoutObj pipeline_layout_variable(m_device, {&ds_variable.layout_}); - VkTextureObj texture(m_device, nullptr); - VkSamplerObj sampler(m_device); - - VkDescriptorBufferInfo buffer_info[1] = {}; - buffer_info[0].buffer = buffer0.handle(); - buffer_info[0].offset = 0; - buffer_info[0].range = sizeof(uint32_t); - - VkDescriptorImageInfo image_info[6] = {}; - for (int i = 0; i < 6; i++) { - image_info[i] = texture.DescriptorImageInfo(); - image_info[i].sampler = sampler.handle(); - image_info[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } - - VkWriteDescriptorSet descriptor_writes[2] = {}; - descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_writes[0].dstSet = ds.set_; // descriptor_set; - descriptor_writes[0].dstBinding = 0; - descriptor_writes[0].descriptorCount = 1; - descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_writes[0].pBufferInfo = buffer_info; - descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_writes[1].dstSet = ds.set_; // descriptor_set; - descriptor_writes[1].dstBinding = 1; - if (descriptor_indexing) - descriptor_writes[1].descriptorCount = 5; // Intentionally don't write index 5 - else - descriptor_writes[1].descriptorCount = 6; - descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_writes[1].pImageInfo = image_info; - vkUpdateDescriptorSets(m_device->device(), 2, descriptor_writes, 0, NULL); - if (descriptor_indexing) { - descriptor_writes[0].dstSet = ds_variable.set_; - descriptor_writes[1].dstSet = ds_variable.set_; - vkUpdateDescriptorSets(m_device->device(), 2, descriptor_writes, 0, NULL); - } - - // Shader programs for array OOB test in vertex stage: - // - The vertex shader fetches the invalid index from the uniform buffer and uses it to make an invalid index into another - // array. - char const *vsSource_vert = - "#version 450\n" - "\n" - "layout(std140, set = 0, binding = 0) uniform foo { uint tex_index[1]; } uniform_index_buffer;\n" - "layout(set = 0, binding = 1) uniform sampler2D tex[6];\n" - "vec2 vertices[3];\n" - "void main(){\n" - " vertices[0] = vec2(-1.0, -1.0);\n" - " vertices[1] = vec2( 1.0, -1.0);\n" - " vertices[2] = vec2( 0.0, 1.0);\n" - " gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);\n" - " gl_Position += 1e-30 * texture(tex[uniform_index_buffer.tex_index[0]], vec2(0, 0));\n" - "}\n"; - char const *fsSource_vert = - "#version 450\n" - "\n" - "layout(set = 0, binding = 1) uniform sampler2D tex[6];\n" - "layout(location = 0) out vec4 uFragColor;\n" - "void main(){\n" - " uFragColor = texture(tex[0], vec2(0, 0));\n" - "}\n"; - - // Shader programs for array OOB test in fragment stage: - // - The vertex shader fetches the invalid index from the uniform buffer and passes it to the fragment shader. - // - The fragment shader makes the invalid array access. - char const *vsSource_frag = - "#version 450\n" - "\n" - "layout(std140, binding = 0) uniform foo { uint tex_index[1]; } uniform_index_buffer;\n" - "layout(location = 0) out flat uint tex_ind;\n" - "vec2 vertices[3];\n" - "void main(){\n" - " vertices[0] = vec2(-1.0, -1.0);\n" - " vertices[1] = vec2( 1.0, -1.0);\n" - " vertices[2] = vec2( 0.0, 1.0);\n" - " gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);\n" - " tex_ind = uniform_index_buffer.tex_index[0];\n" - "}\n"; - char const *fsSource_frag = - "#version 450\n" - "\n" - "layout(set = 0, binding = 1) uniform sampler2D tex[6];\n" - "layout(location = 0) out vec4 uFragColor;\n" - "layout(location = 0) in flat uint tex_ind;\n" - "void main(){\n" - " uFragColor = texture(tex[tex_ind], vec2(0, 0));\n" - "}\n"; - char const *fsSource_frag_runtime = - "#version 450\n" - "#extension GL_EXT_nonuniform_qualifier : enable\n" - "\n" - "layout(set = 0, binding = 1) uniform sampler2D tex[];\n" - "layout(location = 0) out vec4 uFragColor;\n" - "layout(location = 0) in flat uint tex_ind;\n" - "void main(){\n" - " uFragColor = texture(tex[tex_ind], vec2(0, 0));\n" - "}\n"; - struct TestCase { - char const *vertex_source; - char const *fragment_source; - bool debug; - bool variable_length; - uint32_t index; - char const *expected_error; - }; - - std::vector<TestCase> tests; - tests.push_back({vsSource_vert, fsSource_vert, false, false, 25, "Index of 25 used to index descriptor array of length 6."}); - tests.push_back({vsSource_frag, fsSource_frag, false, false, 25, "Index of 25 used to index descriptor array of length 6."}); -#if !defined(ANDROID) - // The Android test framework uses shaderc for online compilations. Even when configured to compile with debug info, - // shaderc seems to drop the OpLine instructions from the shader binary. This causes the following two tests to fail - // on Android platforms. Skip these tests until the shaderc issue is understood/resolved. - tests.push_back({vsSource_vert, fsSource_vert, true, false, 25, - "gl_Position += 1e-30 * texture(tex[uniform_index_buffer.tex_index[0]], vec2(0, 0));"}); - tests.push_back({vsSource_frag, fsSource_frag, true, false, 25, "uFragColor = texture(tex[tex_ind], vec2(0, 0));"}); -#endif - if (descriptor_indexing) { - tests.push_back( - {vsSource_frag, fsSource_frag_runtime, false, false, 25, "Index of 25 used to index descriptor array of length 6."}); - tests.push_back({vsSource_frag, fsSource_frag_runtime, false, false, 5, "Descriptor index 5 is uninitialized"}); - // Pick 6 below because it is less than the maximum specified, but more than the actual specified - tests.push_back( - {vsSource_frag, fsSource_frag_runtime, false, true, 6, "Index of 6 used to index descriptor array of length 6."}); - tests.push_back({vsSource_frag, fsSource_frag_runtime, false, true, 5, "Descriptor index 5 is uninitialized"}); - } - - VkViewport viewport = m_viewports[0]; - VkRect2D scissors = m_scissors[0]; - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - - for (const auto &iter : tests) { - VkResult err; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, iter.expected_error); - VkShaderObj vs(m_device, iter.vertex_source, VK_SHADER_STAGE_VERTEX_BIT, this, "main", iter.debug); - VkShaderObj fs(m_device, iter.fragment_source, VK_SHADER_STAGE_FRAGMENT_BIT, this, "main", iter.debug); - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - if (iter.variable_length) - err = pipe.CreateVKPipeline(pipeline_layout_variable.handle(), renderPass()); - else - err = pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - ASSERT_VK_SUCCESS(err); - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - if (iter.variable_length) { - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_variable.handle(), - 0, 1, &ds_variable.set_, 0, nullptr); - } else { - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &ds.set_, 0, nullptr); - } - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissors); - vkCmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); - vkCmdEndRenderPass(m_commandBuffer->handle()); - m_commandBuffer->end(); - uint32_t *data = (uint32_t *)buffer0.memory().map(); - data[0] = iter.index; - buffer0.memory().unmap(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - vkQueueWaitIdle(m_device->m_queue); - m_errorMonitor->VerifyFound(); - } - return; -} - -TEST_F(VkLayerTest, InvalidMemoryAliasing) { - TEST_DESCRIPTION( - "Create a buffer and image, allocate memory, and bind the buffer and image to memory such that they will alias."); - VkResult err; - bool pass; - ASSERT_NO_FATAL_FAILURE(Init()); - - VkBuffer buffer, buffer2; - VkImage image; - VkImage image2; - VkDeviceMemory mem; // buffer will be bound first - VkDeviceMemory mem_img; // image bound first - VkMemoryRequirements buff_mem_reqs, img_mem_reqs; - VkMemoryRequirements buff_mem_reqs2, img_mem_reqs2; - - VkBufferCreateInfo buf_info = {}; - buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buf_info.pNext = NULL; - buf_info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - buf_info.size = 256; - buf_info.queueFamilyIndexCount = 0; - buf_info.pQueueFamilyIndices = NULL; - buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - buf_info.flags = 0; - err = vkCreateBuffer(m_device->device(), &buf_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - vkGetBufferMemoryRequirements(m_device->device(), buffer, &buff_mem_reqs); - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; - image_create_info.extent.width = 64; - image_create_info.extent.height = 64; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - // Image tiling must be optimal to trigger error when aliasing linear buffer - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - image_create_info.queueFamilyIndexCount = 0; - image_create_info.pQueueFamilyIndices = NULL; - image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_create_info.flags = 0; - - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - ASSERT_VK_SUCCESS(err); - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image2); - ASSERT_VK_SUCCESS(err); - - vkGetImageMemoryRequirements(m_device->device(), image, &img_mem_reqs); - - VkMemoryAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.pNext = NULL; - alloc_info.memoryTypeIndex = 0; - // Ensure memory is big enough for both bindings - alloc_info.allocationSize = buff_mem_reqs.size + img_mem_reqs.size; - pass = m_device->phy().set_memory_type(buff_mem_reqs.memoryTypeBits & img_mem_reqs.memoryTypeBits, &alloc_info, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - if (!pass) { - printf("%s Failed to set memory type.\n", kSkipPrefix); - vkDestroyBuffer(m_device->device(), buffer, NULL); - vkDestroyImage(m_device->device(), image, NULL); - vkDestroyImage(m_device->device(), image2, NULL); - return; - } - err = vkAllocateMemory(m_device->device(), &alloc_info, NULL, &mem); - ASSERT_VK_SUCCESS(err); - err = vkBindBufferMemory(m_device->device(), buffer, mem, 0); - ASSERT_VK_SUCCESS(err); - - vkGetImageMemoryRequirements(m_device->device(), image2, &img_mem_reqs2); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, " is aliased with linear buffer 0x"); - // VALIDATION FAILURE due to image mapping overlapping buffer mapping - err = vkBindImageMemory(m_device->device(), image, mem, 0); - m_errorMonitor->VerifyFound(); - - // Now correctly bind image2 to second mem allocation before incorrectly - // aliasing buffer2 - err = vkCreateBuffer(m_device->device(), &buf_info, NULL, &buffer2); - ASSERT_VK_SUCCESS(err); - err = vkAllocateMemory(m_device->device(), &alloc_info, NULL, &mem_img); - ASSERT_VK_SUCCESS(err); - err = vkBindImageMemory(m_device->device(), image2, mem_img, 0); - ASSERT_VK_SUCCESS(err); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, "is aliased with non-linear image 0x"); - vkGetBufferMemoryRequirements(m_device->device(), buffer2, &buff_mem_reqs2); - err = vkBindBufferMemory(m_device->device(), buffer2, mem_img, 0); - m_errorMonitor->VerifyFound(); - - vkDestroyBuffer(m_device->device(), buffer, NULL); - vkDestroyBuffer(m_device->device(), buffer2, NULL); - vkDestroyImage(m_device->device(), image, NULL); - vkDestroyImage(m_device->device(), image2, NULL); - vkFreeMemory(m_device->device(), mem, NULL); - vkFreeMemory(m_device->device(), mem_img, NULL); -} - -TEST_F(VkLayerTest, InvalidMemoryMapping) { - TEST_DESCRIPTION("Attempt to map memory in a number of incorrect ways"); - VkResult err; - bool pass; - ASSERT_NO_FATAL_FAILURE(Init()); - - VkBuffer buffer; - VkDeviceMemory mem; - VkMemoryRequirements mem_reqs; - - const VkDeviceSize atom_size = m_device->props.limits.nonCoherentAtomSize; - - VkBufferCreateInfo buf_info = {}; - buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buf_info.pNext = NULL; - buf_info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - buf_info.size = 256; - buf_info.queueFamilyIndexCount = 0; - buf_info.pQueueFamilyIndices = NULL; - buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - buf_info.flags = 0; - err = vkCreateBuffer(m_device->device(), &buf_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - vkGetBufferMemoryRequirements(m_device->device(), buffer, &mem_reqs); - VkMemoryAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.pNext = NULL; - alloc_info.memoryTypeIndex = 0; - - // Ensure memory is big enough for both bindings - static const VkDeviceSize allocation_size = 0x10000; - alloc_info.allocationSize = allocation_size; - pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &alloc_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - if (!pass) { - printf("%s Failed to set memory type.\n", kSkipPrefix); - vkDestroyBuffer(m_device->device(), buffer, NULL); - return; - } - err = vkAllocateMemory(m_device->device(), &alloc_info, NULL, &mem); - ASSERT_VK_SUCCESS(err); - - uint8_t *pData; - // Attempt to map memory size 0 is invalid - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VkMapMemory: Attempting to map memory range of size zero"); - err = vkMapMemory(m_device->device(), mem, 0, 0, 0, (void **)&pData); - m_errorMonitor->VerifyFound(); - // Map memory twice - err = vkMapMemory(m_device->device(), mem, 0, mem_reqs.size, 0, (void **)&pData); - ASSERT_VK_SUCCESS(err); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VkMapMemory: Attempting to map memory on an already-mapped object "); - err = vkMapMemory(m_device->device(), mem, 0, mem_reqs.size, 0, (void **)&pData); - m_errorMonitor->VerifyFound(); - - // Unmap the memory to avoid re-map error - vkUnmapMemory(m_device->device(), mem); - // overstep allocation with VK_WHOLE_SIZE - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - " with size of VK_WHOLE_SIZE oversteps total array size 0x"); - err = vkMapMemory(m_device->device(), mem, allocation_size + 1, VK_WHOLE_SIZE, 0, (void **)&pData); - m_errorMonitor->VerifyFound(); - // overstep allocation w/o VK_WHOLE_SIZE - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " oversteps total array size 0x"); - err = vkMapMemory(m_device->device(), mem, 1, allocation_size, 0, (void **)&pData); - m_errorMonitor->VerifyFound(); - // Now error due to unmapping memory that's not mapped - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Unmapping Memory without memory being mapped: "); - vkUnmapMemory(m_device->device(), mem); - m_errorMonitor->VerifyFound(); - - // Now map memory and cause errors due to flushing invalid ranges - err = vkMapMemory(m_device->device(), mem, 4 * atom_size, VK_WHOLE_SIZE, 0, (void **)&pData); - ASSERT_VK_SUCCESS(err); - VkMappedMemoryRange mmr = {}; - mmr.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - mmr.memory = mem; - mmr.offset = atom_size; // Error b/c offset less than offset of mapped mem - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMappedMemoryRange-size-00685"); - vkFlushMappedMemoryRanges(m_device->device(), 1, &mmr); - m_errorMonitor->VerifyFound(); - - // Now flush range that oversteps mapped range - vkUnmapMemory(m_device->device(), mem); - err = vkMapMemory(m_device->device(), mem, 0, 4 * atom_size, 0, (void **)&pData); - ASSERT_VK_SUCCESS(err); - mmr.offset = atom_size; - mmr.size = 4 * atom_size; // Flushing bounds exceed mapped bounds - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMappedMemoryRange-size-00685"); - vkFlushMappedMemoryRanges(m_device->device(), 1, &mmr); - m_errorMonitor->VerifyFound(); - - // Now flush range with VK_WHOLE_SIZE that oversteps offset - vkUnmapMemory(m_device->device(), mem); - err = vkMapMemory(m_device->device(), mem, 2 * atom_size, 4 * atom_size, 0, (void **)&pData); - ASSERT_VK_SUCCESS(err); - mmr.offset = atom_size; - mmr.size = VK_WHOLE_SIZE; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMappedMemoryRange-size-00686"); - vkFlushMappedMemoryRanges(m_device->device(), 1, &mmr); - m_errorMonitor->VerifyFound(); - - // Some platforms have an atomsize of 1 which makes the test meaningless - if (atom_size > 3) { - // Now with an offset NOT a multiple of the device limit - vkUnmapMemory(m_device->device(), mem); - err = vkMapMemory(m_device->device(), mem, 0, 4 * atom_size, 0, (void **)&pData); - ASSERT_VK_SUCCESS(err); - mmr.offset = 3; // Not a multiple of atom_size - mmr.size = VK_WHOLE_SIZE; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMappedMemoryRange-offset-00687"); - vkFlushMappedMemoryRanges(m_device->device(), 1, &mmr); - m_errorMonitor->VerifyFound(); - - // Now with a size NOT a multiple of the device limit - vkUnmapMemory(m_device->device(), mem); - err = vkMapMemory(m_device->device(), mem, 0, 4 * atom_size, 0, (void **)&pData); - ASSERT_VK_SUCCESS(err); - mmr.offset = atom_size; - mmr.size = 2 * atom_size + 1; // Not a multiple of atom_size - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMappedMemoryRange-size-01390"); - vkFlushMappedMemoryRanges(m_device->device(), 1, &mmr); - m_errorMonitor->VerifyFound(); - } - - pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &alloc_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - if (!pass) { - printf("%s Failed to set memory type.\n", kSkipPrefix); - vkFreeMemory(m_device->device(), mem, NULL); - vkDestroyBuffer(m_device->device(), buffer, NULL); - return; - } - // TODO : If we can get HOST_VISIBLE w/o HOST_COHERENT we can test cases of - // kVUID_Core_MemTrack_InvalidMap in validateAndCopyNoncoherentMemoryToDriver() - - vkDestroyBuffer(m_device->device(), buffer, NULL); - vkFreeMemory(m_device->device(), mem, NULL); -} - -TEST_F(VkLayerTest, MapMemWithoutHostVisibleBit) { - TEST_DESCRIPTION("Allocate memory that is not mappable and then attempt to map it."); - VkResult err; - bool pass; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkMapMemory-memory-00682"); - ASSERT_NO_FATAL_FAILURE(Init()); - - VkMemoryAllocateInfo mem_alloc = {}; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.allocationSize = 1024; - - pass = m_device->phy().set_memory_type(0xFFFFFFFF, &mem_alloc, 0, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - if (!pass) { // If we can't find any unmappable memory this test doesn't - // make sense - printf("%s No unmappable memory types found, skipping test\n", kSkipPrefix); - return; - } - - VkDeviceMemory mem; - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &mem); - ASSERT_VK_SUCCESS(err); - - void *mappedAddress = NULL; - err = vkMapMemory(m_device->device(), mem, 0, VK_WHOLE_SIZE, 0, &mappedAddress); - m_errorMonitor->VerifyFound(); - - vkFreeMemory(m_device->device(), mem, NULL); -} - -TEST_F(VkLayerTest, RebindMemory) { - VkResult err; - bool pass; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "which has already been bound to mem object"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // Create an image, allocate memory, free it, and then try to bind it - VkImage image; - VkDeviceMemory mem1; - VkDeviceMemory mem2; - VkMemoryRequirements mem_reqs; - - const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; - const int32_t tex_width = 32; - const int32_t tex_height = 32; - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = tex_format; - image_create_info.extent.width = tex_width; - image_create_info.extent.height = tex_height; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - image_create_info.flags = 0; - - VkMemoryAllocateInfo mem_alloc = {}; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.allocationSize = 0; - mem_alloc.memoryTypeIndex = 0; - - // Introduce failure, do NOT set memProps to - // VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT - mem_alloc.memoryTypeIndex = 1; - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - ASSERT_VK_SUCCESS(err); - - vkGetImageMemoryRequirements(m_device->device(), image, &mem_reqs); - - mem_alloc.allocationSize = mem_reqs.size; - pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &mem_alloc, 0); - ASSERT_TRUE(pass); - - // allocate 2 memory objects - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &mem1); - ASSERT_VK_SUCCESS(err); - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &mem2); - ASSERT_VK_SUCCESS(err); - - // Bind first memory object to Image object - err = vkBindImageMemory(m_device->device(), image, mem1, 0); - ASSERT_VK_SUCCESS(err); - - // Introduce validation failure, try to bind a different memory object to - // the same image object - err = vkBindImageMemory(m_device->device(), image, mem2, 0); - - m_errorMonitor->VerifyFound(); - - vkDestroyImage(m_device->device(), image, NULL); - vkFreeMemory(m_device->device(), mem1, NULL); - vkFreeMemory(m_device->device(), mem2, NULL); -} - -TEST_F(VkLayerTest, QueryMemoryCommitmentWithoutLazyProperty) { - TEST_DESCRIPTION("Attempt to query memory commitment on memory without lazy allocation"); - ASSERT_NO_FATAL_FAILURE(Init()); - - auto image_ci = vk_testing::Image::create_info(); - image_ci.imageType = VK_IMAGE_TYPE_2D; - image_ci.format = VK_FORMAT_B8G8R8A8_UNORM; - image_ci.extent.width = 32; - image_ci.extent.height = 32; - image_ci.tiling = VK_IMAGE_TILING_OPTIMAL; - image_ci.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - vk_testing::Image image; - image.init_no_mem(*m_device, image_ci); - - auto mem_reqs = image.memory_requirements(); - // memory_type_index is set to 0 here, but is set properly below - auto image_alloc_info = vk_testing::DeviceMemory::alloc_info(mem_reqs.size, 0); - - bool pass; - // the last argument is the "forbid" argument for set_memory_type, disallowing - // that particular memory type rather than requiring it - pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &image_alloc_info, 0, VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT); - if (!pass) { - printf("%s Failed to set memory type.\n", kSkipPrefix); - return; - } - vk_testing::DeviceMemory mem; - mem.init(*m_device, image_alloc_info); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkGetDeviceMemoryCommitment-memory-00690"); - VkDeviceSize size; - vkGetDeviceMemoryCommitment(m_device->device(), mem.handle(), &size); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, SubmitSignaledFence) { - vk_testing::Fence testFence; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "submitted in SIGNALED state. Fences must be reset before being submitted"); - - VkFenceCreateInfo fenceInfo = {}; - fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fenceInfo.pNext = NULL; - fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - m_commandBuffer->begin(); - m_commandBuffer->ClearAllBuffers(m_renderTargets, m_clear_color, nullptr, m_depth_clear_color, m_stencil_clear_color); - m_commandBuffer->end(); - - testFence.init(*m_device, fenceInfo); - - VkSubmitInfo submit_info; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.pNext = NULL; - submit_info.waitSemaphoreCount = 0; - submit_info.pWaitSemaphores = NULL; - submit_info.pWaitDstStageMask = NULL; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - submit_info.signalSemaphoreCount = 0; - submit_info.pSignalSemaphores = NULL; - - vkQueueSubmit(m_device->m_queue, 1, &submit_info, testFence.handle()); - vkQueueWaitIdle(m_device->m_queue); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, InvalidUsageBits) { - TEST_DESCRIPTION( - "Specify wrong usage for image then create conflicting view of image Initialize buffer with wrong usage then perform copy " - "expecting errors from both the image and the buffer (2 calls)"); - - ASSERT_NO_FATAL_FAILURE(Init()); - auto format = FindSupportedDepthStencilFormat(gpu()); - if (!format) { - printf("%s No Depth + Stencil format found. Skipped.\n", kSkipPrefix); - return; - } - - VkImageObj image(m_device); - // Initialize image with transfer source usage - image.Init(128, 128, 1, format, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - VkImageView dsv; - VkImageViewCreateInfo dsvci = {}; - dsvci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - dsvci.image = image.handle(); - dsvci.viewType = VK_IMAGE_VIEW_TYPE_2D; - dsvci.format = format; - dsvci.subresourceRange.layerCount = 1; - dsvci.subresourceRange.baseMipLevel = 0; - dsvci.subresourceRange.levelCount = 1; - dsvci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - - // Create a view with depth / stencil aspect for image with different usage - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Invalid usage flag for Image "); - vkCreateImageView(m_device->device(), &dsvci, NULL, &dsv); - m_errorMonitor->VerifyFound(); - - // Initialize buffer with TRANSFER_DST usage - VkBufferObj buffer; - VkMemoryPropertyFlags reqs = 0; - buffer.init_as_dst(*m_device, 128 * 128, reqs); - VkBufferImageCopy region = {}; - region.bufferRowLength = 128; - region.bufferImageHeight = 128; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - region.imageSubresource.layerCount = 1; - region.imageExtent.height = 16; - region.imageExtent.width = 16; - region.imageExtent.depth = 1; - - // Buffer usage not set to TRANSFER_SRC and image usage not set to TRANSFER_DST - m_commandBuffer->begin(); - - // two separate errors from this call: - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyBufferToImage-dstImage-00177"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyBufferToImage-srcBuffer-00174"); - - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, - ®ion); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, LeakAnObject) { - VkResult err; - - TEST_DESCRIPTION("Create a fence and destroy its device without first destroying the fence."); - - // Note that we have to create a new device since destroying the - // framework's device causes Teardown() to fail and just calling Teardown - // will destroy the errorMonitor. - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "has not been destroyed."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - vk_testing::QueueCreateInfoArray queue_info(m_device->queue_props); - - // The sacrificial device object - VkDevice testDevice; - VkDeviceCreateInfo device_create_info = {}; - auto features = m_device->phy().features(); - device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - device_create_info.pNext = NULL; - device_create_info.queueCreateInfoCount = queue_info.size(); - device_create_info.pQueueCreateInfos = queue_info.data(); - device_create_info.enabledLayerCount = 0; - device_create_info.ppEnabledLayerNames = NULL; - device_create_info.pEnabledFeatures = &features; - err = vkCreateDevice(gpu(), &device_create_info, NULL, &testDevice); - ASSERT_VK_SUCCESS(err); - - VkFence fence; - VkFenceCreateInfo fence_create_info = {}; - fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fence_create_info.pNext = NULL; - fence_create_info.flags = 0; - err = vkCreateFence(testDevice, &fence_create_info, NULL, &fence); - ASSERT_VK_SUCCESS(err); - - // Induce failure by not calling vkDestroyFence - vkDestroyDevice(testDevice, NULL); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, InvalidCommandPoolConsistency) { - TEST_DESCRIPTION("Allocate command buffers from one command pool and attempt to delete them from another."); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "FreeCommandBuffers is attempting to free Command Buffer"); - - ASSERT_NO_FATAL_FAILURE(Init()); - VkCommandPool command_pool_one; - VkCommandPool command_pool_two; - - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - - vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool_one); - - vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool_two); - - VkCommandBuffer cb; - VkCommandBufferAllocateInfo command_buffer_allocate_info{}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = command_pool_one; - command_buffer_allocate_info.commandBufferCount = 1; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, &cb); - - vkFreeCommandBuffers(m_device->device(), command_pool_two, 1, &cb); - - m_errorMonitor->VerifyFound(); - - vkDestroyCommandPool(m_device->device(), command_pool_one, NULL); - vkDestroyCommandPool(m_device->device(), command_pool_two, NULL); -} - -TEST_F(VkLayerTest, InvalidDescriptorPoolConsistency) { - VkResult err; - - TEST_DESCRIPTION("Allocate descriptor sets from one DS pool and attempt to delete them from another."); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "FreeDescriptorSets is attempting to free descriptorSet"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_SAMPLER; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.flags = 0; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool bad_pool; - err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &bad_pool); - ASSERT_VK_SUCCESS(err); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - err = vkFreeDescriptorSets(m_device->device(), bad_pool, 1, &ds.set_); - - m_errorMonitor->VerifyFound(); - - vkDestroyDescriptorPool(m_device->device(), bad_pool, NULL); -} - -TEST_F(VkLayerTest, CreateUnknownObject) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkGetImageMemoryRequirements-image-parameter"); - - TEST_DESCRIPTION("Pass an invalid image object handle into a Vulkan API call."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // Pass bogus handle into GetImageMemoryRequirements - VkMemoryRequirements mem_reqs; - uint64_t fakeImageHandle = 0xCADECADE; - VkImage fauxImage = reinterpret_cast<VkImage &>(fakeImageHandle); - - vkGetImageMemoryRequirements(m_device->device(), fauxImage, &mem_reqs); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, UseObjectWithWrongDevice) { - TEST_DESCRIPTION( - "Try to destroy a render pass object using a device other than the one it was created on. This should generate a distinct " - "error from the invalid handle error."); - // Create first device and renderpass - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Create second device - float priorities[] = {1.0f}; - VkDeviceQueueCreateInfo queue_info{}; - queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_info.pNext = NULL; - queue_info.flags = 0; - queue_info.queueFamilyIndex = 0; - queue_info.queueCount = 1; - queue_info.pQueuePriorities = &priorities[0]; - - VkDeviceCreateInfo device_create_info = {}; - auto features = m_device->phy().features(); - device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - device_create_info.pNext = NULL; - device_create_info.queueCreateInfoCount = 1; - device_create_info.pQueueCreateInfos = &queue_info; - device_create_info.enabledLayerCount = 0; - device_create_info.ppEnabledLayerNames = NULL; - device_create_info.pEnabledFeatures = &features; - - VkDevice second_device; - ASSERT_VK_SUCCESS(vkCreateDevice(gpu(), &device_create_info, NULL, &second_device)); - - // Try to destroy the renderpass from the first device using the second device - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkDestroyRenderPass-renderPass-parent"); - vkDestroyRenderPass(second_device, m_renderPass, NULL); - m_errorMonitor->VerifyFound(); - - vkDestroyDevice(second_device, NULL); -} - -TEST_F(VkLayerTest, PipelineNotBound) { - TEST_DESCRIPTION("Pass in an invalid pipeline object handle into a Vulkan API call."); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindPipeline-pipeline-parameter"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkPipeline badPipeline = (VkPipeline)((size_t)0xbaadb1be); - - m_commandBuffer->begin(); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, badPipeline); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, PipelineWrongBindPointGraphics) { - TEST_DESCRIPTION("Bind a compute pipeline in the graphics bind point"); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindPipeline-pipelineBindPoint-00779"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - // Create a minimal compute pipeline - std::string cs_text = "#version 450\nvoid main() {}\n"; // minimal no-op shader - VkShaderObj cs_obj(m_device, cs_text.c_str(), VK_SHADER_STAGE_COMPUTE_BIT, this); - - VkComputePipelineCreateInfo pipeline_info = {}; - pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; - pipeline_info.layout = descriptorSet.GetPipelineLayout(); - pipeline_info.basePipelineHandle = VK_NULL_HANDLE; - pipeline_info.basePipelineIndex = -1; - pipeline_info.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - pipeline_info.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; - pipeline_info.stage.pName = "main"; - pipeline_info.stage.module = cs_obj.handle(); - VkPipeline cs_pipeline; - vkCreateComputePipelines(device(), VK_NULL_HANDLE, 1, &pipeline_info, nullptr, &cs_pipeline); - - m_commandBuffer->begin(); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, cs_pipeline); - - m_errorMonitor->VerifyFound(); - - // Clean up - vkDestroyPipeline(device(), cs_pipeline, nullptr); -} - -TEST_F(VkLayerTest, PipelineWrongBindPointCompute) { - TEST_DESCRIPTION("Bind a graphics pipeline in the compute bind point"); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindPipeline-pipelineBindPoint-00780"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - pipe.AddShader(&vs); - - VkGraphicsPipelineCreateInfo info = {}; - pipe.InitGraphicsPipelineCreateInfo(&info); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_commandBuffer->begin(); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipe.handle()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, PipelineWrongBindPointRayTracing) { - TEST_DESCRIPTION("Bind a graphics pipeline in the ray-tracing bind point"); - - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if (DeviceExtensionSupported(gpu(), nullptr, VK_NV_RAY_TRACING_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_NV_RAY_TRACING_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - } else { - printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_NV_RAY_TRACING_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindPipeline-pipelineBindPoint-02392"); - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - if (!EnableDeviceProfileLayer()) { - printf("%s Failed to enable device profile layer.\n", kSkipPrefix); - return; - } - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - pipe.AddShader(&vs); - - VkGraphicsPipelineCreateInfo info = {}; - pipe.InitGraphicsPipelineCreateInfo(&info); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_commandBuffer->begin(); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, pipe.handle()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, BindImageInvalidMemoryType) { - VkResult err; - - TEST_DESCRIPTION("Test validation check for an invalid memory type index during bind[Buffer|Image]Memory time"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // Create an image, allocate memory, set a bad typeIndex and then try to - // bind it - VkImage image; - VkDeviceMemory mem; - VkMemoryRequirements mem_reqs; - const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; - const int32_t tex_width = 32; - const int32_t tex_height = 32; - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = tex_format; - image_create_info.extent.width = tex_width; - image_create_info.extent.height = tex_height; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - image_create_info.flags = 0; - - VkMemoryAllocateInfo mem_alloc = {}; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.allocationSize = 0; - mem_alloc.memoryTypeIndex = 0; - - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - ASSERT_VK_SUCCESS(err); - - vkGetImageMemoryRequirements(m_device->device(), image, &mem_reqs); - mem_alloc.allocationSize = mem_reqs.size; - - // Introduce Failure, select invalid TypeIndex - VkPhysicalDeviceMemoryProperties memory_info; - - vkGetPhysicalDeviceMemoryProperties(gpu(), &memory_info); - unsigned int i; - for (i = 0; i < memory_info.memoryTypeCount; i++) { - if ((mem_reqs.memoryTypeBits & (1 << i)) == 0) { - mem_alloc.memoryTypeIndex = i; - break; - } - } - if (i >= memory_info.memoryTypeCount) { - printf("%s No invalid memory type index could be found; skipped.\n", kSkipPrefix); - vkDestroyImage(m_device->device(), image, NULL); - return; - } - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "for this object type are not compatible with the memory"); - - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &mem); - ASSERT_VK_SUCCESS(err); - - err = vkBindImageMemory(m_device->device(), image, mem, 0); - (void)err; - - m_errorMonitor->VerifyFound(); - - vkDestroyImage(m_device->device(), image, NULL); - vkFreeMemory(m_device->device(), mem, NULL); -} - -TEST_F(VkLayerTest, BindInvalidMemory) { - VkResult err; - bool pass; - - ASSERT_NO_FATAL_FAILURE(Init()); - - const VkFormat tex_format = VK_FORMAT_R8G8B8A8_UNORM; - const int32_t tex_width = 256; - const int32_t tex_height = 256; - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = tex_format; - image_create_info.extent.width = tex_width; - image_create_info.extent.height = tex_height; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - image_create_info.flags = 0; - - VkBufferCreateInfo buffer_create_info = {}; - buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_create_info.pNext = NULL; - buffer_create_info.flags = 0; - buffer_create_info.size = 4 * 1024 * 1024; - buffer_create_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - // Create an image/buffer, allocate memory, free it, and then try to bind it - { - VkImage image = VK_NULL_HANDLE; - VkBuffer buffer = VK_NULL_HANDLE; - err = vkCreateImage(device(), &image_create_info, NULL, &image); - ASSERT_VK_SUCCESS(err); - err = vkCreateBuffer(device(), &buffer_create_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - VkMemoryRequirements image_mem_reqs = {}, buffer_mem_reqs = {}; - vkGetImageMemoryRequirements(device(), image, &image_mem_reqs); - vkGetBufferMemoryRequirements(device(), buffer, &buffer_mem_reqs); - - VkMemoryAllocateInfo image_mem_alloc = {}, buffer_mem_alloc = {}; - image_mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - image_mem_alloc.allocationSize = image_mem_reqs.size; - pass = m_device->phy().set_memory_type(image_mem_reqs.memoryTypeBits, &image_mem_alloc, 0); - ASSERT_TRUE(pass); - buffer_mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - buffer_mem_alloc.allocationSize = buffer_mem_reqs.size; - pass = m_device->phy().set_memory_type(buffer_mem_reqs.memoryTypeBits, &buffer_mem_alloc, 0); - ASSERT_TRUE(pass); - - VkDeviceMemory image_mem = VK_NULL_HANDLE, buffer_mem = VK_NULL_HANDLE; - err = vkAllocateMemory(device(), &image_mem_alloc, NULL, &image_mem); - ASSERT_VK_SUCCESS(err); - err = vkAllocateMemory(device(), &buffer_mem_alloc, NULL, &buffer_mem); - ASSERT_VK_SUCCESS(err); - - vkFreeMemory(device(), image_mem, NULL); - vkFreeMemory(device(), buffer_mem, NULL); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindImageMemory-memory-parameter"); - err = vkBindImageMemory(device(), image, image_mem, 0); - (void)err; // This may very well return an error. - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindBufferMemory-memory-parameter"); - err = vkBindBufferMemory(device(), buffer, buffer_mem, 0); - (void)err; // This may very well return an error. - m_errorMonitor->VerifyFound(); - - vkDestroyImage(m_device->device(), image, NULL); - vkDestroyBuffer(m_device->device(), buffer, NULL); - } - - // Try to bind memory to an object that already has a memory binding - { - VkImage image = VK_NULL_HANDLE; - err = vkCreateImage(device(), &image_create_info, NULL, &image); - ASSERT_VK_SUCCESS(err); - VkBuffer buffer = VK_NULL_HANDLE; - err = vkCreateBuffer(device(), &buffer_create_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - VkMemoryRequirements image_mem_reqs = {}, buffer_mem_reqs = {}; - vkGetImageMemoryRequirements(device(), image, &image_mem_reqs); - vkGetBufferMemoryRequirements(device(), buffer, &buffer_mem_reqs); - VkMemoryAllocateInfo image_alloc_info = {}, buffer_alloc_info = {}; - image_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - image_alloc_info.allocationSize = image_mem_reqs.size; - buffer_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - buffer_alloc_info.allocationSize = buffer_mem_reqs.size; - pass = m_device->phy().set_memory_type(image_mem_reqs.memoryTypeBits, &image_alloc_info, 0); - ASSERT_TRUE(pass); - pass = m_device->phy().set_memory_type(buffer_mem_reqs.memoryTypeBits, &buffer_alloc_info, 0); - ASSERT_TRUE(pass); - VkDeviceMemory image_mem, buffer_mem; - err = vkAllocateMemory(device(), &image_alloc_info, NULL, &image_mem); - ASSERT_VK_SUCCESS(err); - err = vkAllocateMemory(device(), &buffer_alloc_info, NULL, &buffer_mem); - ASSERT_VK_SUCCESS(err); - - err = vkBindImageMemory(device(), image, image_mem, 0); - ASSERT_VK_SUCCESS(err); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindImageMemory-image-01044"); - err = vkBindImageMemory(device(), image, image_mem, 0); - (void)err; // This may very well return an error. - m_errorMonitor->VerifyFound(); - - err = vkBindBufferMemory(device(), buffer, buffer_mem, 0); - ASSERT_VK_SUCCESS(err); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindBufferMemory-buffer-01029"); - err = vkBindBufferMemory(device(), buffer, buffer_mem, 0); - (void)err; // This may very well return an error. - m_errorMonitor->VerifyFound(); - - vkFreeMemory(device(), image_mem, NULL); - vkFreeMemory(device(), buffer_mem, NULL); - vkDestroyImage(device(), image, NULL); - vkDestroyBuffer(device(), buffer, NULL); - } - - // Try to bind memory to an object with an invalid memoryOffset - { - VkImage image = VK_NULL_HANDLE; - err = vkCreateImage(device(), &image_create_info, NULL, &image); - ASSERT_VK_SUCCESS(err); - VkBuffer buffer = VK_NULL_HANDLE; - err = vkCreateBuffer(device(), &buffer_create_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - VkMemoryRequirements image_mem_reqs = {}, buffer_mem_reqs = {}; - vkGetImageMemoryRequirements(device(), image, &image_mem_reqs); - vkGetBufferMemoryRequirements(device(), buffer, &buffer_mem_reqs); - VkMemoryAllocateInfo image_alloc_info = {}, buffer_alloc_info = {}; - image_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - // Leave some extra space for alignment wiggle room - image_alloc_info.allocationSize = image_mem_reqs.size + image_mem_reqs.alignment; - buffer_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - buffer_alloc_info.allocationSize = buffer_mem_reqs.size + buffer_mem_reqs.alignment; - pass = m_device->phy().set_memory_type(image_mem_reqs.memoryTypeBits, &image_alloc_info, 0); - ASSERT_TRUE(pass); - pass = m_device->phy().set_memory_type(buffer_mem_reqs.memoryTypeBits, &buffer_alloc_info, 0); - ASSERT_TRUE(pass); - VkDeviceMemory image_mem, buffer_mem; - err = vkAllocateMemory(device(), &image_alloc_info, NULL, &image_mem); - ASSERT_VK_SUCCESS(err); - err = vkAllocateMemory(device(), &buffer_alloc_info, NULL, &buffer_mem); - ASSERT_VK_SUCCESS(err); - - // Test unaligned memory offset - { - if (image_mem_reqs.alignment > 1) { - VkDeviceSize image_offset = 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindImageMemory-memoryOffset-01048"); - err = vkBindImageMemory(device(), image, image_mem, image_offset); - (void)err; // This may very well return an error. - m_errorMonitor->VerifyFound(); - } - - if (buffer_mem_reqs.alignment > 1) { - VkDeviceSize buffer_offset = 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindBufferMemory-memoryOffset-01036"); - err = vkBindBufferMemory(device(), buffer, buffer_mem, buffer_offset); - (void)err; // This may very well return an error. - m_errorMonitor->VerifyFound(); - } - } - - // Test memory offsets outside the memory allocation - { - VkDeviceSize image_offset = - (image_alloc_info.allocationSize + image_mem_reqs.alignment) & ~(image_mem_reqs.alignment - 1); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindImageMemory-memoryOffset-01046"); - err = vkBindImageMemory(device(), image, image_mem, image_offset); - (void)err; // This may very well return an error. - m_errorMonitor->VerifyFound(); - - VkDeviceSize buffer_offset = - (buffer_alloc_info.allocationSize + buffer_mem_reqs.alignment) & ~(buffer_mem_reqs.alignment - 1); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindBufferMemory-memoryOffset-01031"); - err = vkBindBufferMemory(device(), buffer, buffer_mem, buffer_offset); - (void)err; // This may very well return an error. - m_errorMonitor->VerifyFound(); - } - - // Test memory offsets within the memory allocation, but which leave too little memory for - // the resource. - { - VkDeviceSize image_offset = (image_mem_reqs.size - 1) & ~(image_mem_reqs.alignment - 1); - if ((image_offset > 0) && (image_mem_reqs.size < (image_alloc_info.allocationSize - image_mem_reqs.alignment))) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindImageMemory-size-01049"); - err = vkBindImageMemory(device(), image, image_mem, image_offset); - (void)err; // This may very well return an error. - m_errorMonitor->VerifyFound(); - } - - VkDeviceSize buffer_offset = (buffer_mem_reqs.size - 1) & ~(buffer_mem_reqs.alignment - 1); - if (buffer_offset > 0) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindBufferMemory-size-01037"); - err = vkBindBufferMemory(device(), buffer, buffer_mem, buffer_offset); - (void)err; // This may very well return an error. - m_errorMonitor->VerifyFound(); - } - } - - vkFreeMemory(device(), image_mem, NULL); - vkFreeMemory(device(), buffer_mem, NULL); - vkDestroyImage(device(), image, NULL); - vkDestroyBuffer(device(), buffer, NULL); - } - - // Try to bind memory to an object with an invalid memory type - { - VkImage image = VK_NULL_HANDLE; - err = vkCreateImage(device(), &image_create_info, NULL, &image); - ASSERT_VK_SUCCESS(err); - VkBuffer buffer = VK_NULL_HANDLE; - err = vkCreateBuffer(device(), &buffer_create_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - VkMemoryRequirements image_mem_reqs = {}, buffer_mem_reqs = {}; - vkGetImageMemoryRequirements(device(), image, &image_mem_reqs); - vkGetBufferMemoryRequirements(device(), buffer, &buffer_mem_reqs); - VkMemoryAllocateInfo image_alloc_info = {}, buffer_alloc_info = {}; - image_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - image_alloc_info.allocationSize = image_mem_reqs.size; - buffer_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - buffer_alloc_info.allocationSize = buffer_mem_reqs.size; - // Create a mask of available memory types *not* supported by these resources, - // and try to use one of them. - VkPhysicalDeviceMemoryProperties memory_properties = {}; - vkGetPhysicalDeviceMemoryProperties(m_device->phy().handle(), &memory_properties); - VkDeviceMemory image_mem, buffer_mem; - - uint32_t image_unsupported_mem_type_bits = ((1 << memory_properties.memoryTypeCount) - 1) & ~image_mem_reqs.memoryTypeBits; - if (image_unsupported_mem_type_bits != 0) { - pass = m_device->phy().set_memory_type(image_unsupported_mem_type_bits, &image_alloc_info, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(device(), &image_alloc_info, NULL, &image_mem); - ASSERT_VK_SUCCESS(err); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindImageMemory-memory-01047"); - err = vkBindImageMemory(device(), image, image_mem, 0); - (void)err; // This may very well return an error. - m_errorMonitor->VerifyFound(); - vkFreeMemory(device(), image_mem, NULL); - } - - uint32_t buffer_unsupported_mem_type_bits = - ((1 << memory_properties.memoryTypeCount) - 1) & ~buffer_mem_reqs.memoryTypeBits; - if (buffer_unsupported_mem_type_bits != 0) { - pass = m_device->phy().set_memory_type(buffer_unsupported_mem_type_bits, &buffer_alloc_info, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(device(), &buffer_alloc_info, NULL, &buffer_mem); - ASSERT_VK_SUCCESS(err); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindBufferMemory-memory-01035"); - err = vkBindBufferMemory(device(), buffer, buffer_mem, 0); - (void)err; // This may very well return an error. - m_errorMonitor->VerifyFound(); - vkFreeMemory(device(), buffer_mem, NULL); - } - - vkDestroyImage(device(), image, NULL); - vkDestroyBuffer(device(), buffer, NULL); - } - - // Try to bind memory to an image created with sparse memory flags - { - VkImageCreateInfo sparse_image_create_info = image_create_info; - sparse_image_create_info.flags |= VK_IMAGE_CREATE_SPARSE_BINDING_BIT; - VkImageFormatProperties image_format_properties = {}; - err = vkGetPhysicalDeviceImageFormatProperties(m_device->phy().handle(), sparse_image_create_info.format, - sparse_image_create_info.imageType, sparse_image_create_info.tiling, - sparse_image_create_info.usage, sparse_image_create_info.flags, - &image_format_properties); - if (!m_device->phy().features().sparseResidencyImage2D || err == VK_ERROR_FORMAT_NOT_SUPPORTED) { - // most likely means sparse formats aren't supported here; skip this test. - } else { - ASSERT_VK_SUCCESS(err); - if (image_format_properties.maxExtent.width == 0) { - printf("%s Sparse image format not supported; skipped.\n", kSkipPrefix); - return; - } else { - VkImage sparse_image = VK_NULL_HANDLE; - err = vkCreateImage(m_device->device(), &sparse_image_create_info, NULL, &sparse_image); - ASSERT_VK_SUCCESS(err); - VkMemoryRequirements sparse_mem_reqs = {}; - vkGetImageMemoryRequirements(m_device->device(), sparse_image, &sparse_mem_reqs); - if (sparse_mem_reqs.memoryTypeBits != 0) { - VkMemoryAllocateInfo sparse_mem_alloc = {}; - sparse_mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - sparse_mem_alloc.pNext = NULL; - sparse_mem_alloc.allocationSize = sparse_mem_reqs.size; - sparse_mem_alloc.memoryTypeIndex = 0; - pass = m_device->phy().set_memory_type(sparse_mem_reqs.memoryTypeBits, &sparse_mem_alloc, 0); - ASSERT_TRUE(pass); - VkDeviceMemory sparse_mem = VK_NULL_HANDLE; - err = vkAllocateMemory(m_device->device(), &sparse_mem_alloc, NULL, &sparse_mem); - ASSERT_VK_SUCCESS(err); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindImageMemory-image-01045"); - err = vkBindImageMemory(m_device->device(), sparse_image, sparse_mem, 0); - // This may very well return an error. - (void)err; - m_errorMonitor->VerifyFound(); - vkFreeMemory(m_device->device(), sparse_mem, NULL); - } - vkDestroyImage(m_device->device(), sparse_image, NULL); - } - } - } - - // Try to bind memory to a buffer created with sparse memory flags - { - VkBufferCreateInfo sparse_buffer_create_info = buffer_create_info; - sparse_buffer_create_info.flags |= VK_IMAGE_CREATE_SPARSE_BINDING_BIT; - if (!m_device->phy().features().sparseResidencyBuffer) { - // most likely means sparse formats aren't supported here; skip this test. - } else { - VkBuffer sparse_buffer = VK_NULL_HANDLE; - err = vkCreateBuffer(m_device->device(), &sparse_buffer_create_info, NULL, &sparse_buffer); - ASSERT_VK_SUCCESS(err); - VkMemoryRequirements sparse_mem_reqs = {}; - vkGetBufferMemoryRequirements(m_device->device(), sparse_buffer, &sparse_mem_reqs); - if (sparse_mem_reqs.memoryTypeBits != 0) { - VkMemoryAllocateInfo sparse_mem_alloc = {}; - sparse_mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - sparse_mem_alloc.pNext = NULL; - sparse_mem_alloc.allocationSize = sparse_mem_reqs.size; - sparse_mem_alloc.memoryTypeIndex = 0; - pass = m_device->phy().set_memory_type(sparse_mem_reqs.memoryTypeBits, &sparse_mem_alloc, 0); - ASSERT_TRUE(pass); - VkDeviceMemory sparse_mem = VK_NULL_HANDLE; - err = vkAllocateMemory(m_device->device(), &sparse_mem_alloc, NULL, &sparse_mem); - ASSERT_VK_SUCCESS(err); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindBufferMemory-buffer-01030"); - err = vkBindBufferMemory(m_device->device(), sparse_buffer, sparse_mem, 0); - // This may very well return an error. - (void)err; - m_errorMonitor->VerifyFound(); - vkFreeMemory(m_device->device(), sparse_mem, NULL); - } - vkDestroyBuffer(m_device->device(), sparse_buffer, NULL); - } - } -} - -TEST_F(VkLayerTest, BindMemoryToDestroyedObject) { - VkResult err; - bool pass; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindImageMemory-image-parameter"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // Create an image object, allocate memory, destroy the object and then try - // to bind it - VkImage image; - VkDeviceMemory mem; - VkMemoryRequirements mem_reqs; - - const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; - const int32_t tex_width = 32; - const int32_t tex_height = 32; - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = tex_format; - image_create_info.extent.width = tex_width; - image_create_info.extent.height = tex_height; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - image_create_info.flags = 0; - - VkMemoryAllocateInfo mem_alloc = {}; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.allocationSize = 0; - mem_alloc.memoryTypeIndex = 0; - - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - ASSERT_VK_SUCCESS(err); - - vkGetImageMemoryRequirements(m_device->device(), image, &mem_reqs); - - mem_alloc.allocationSize = mem_reqs.size; - pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &mem_alloc, 0); - ASSERT_TRUE(pass); - - // Allocate memory - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &mem); - ASSERT_VK_SUCCESS(err); - - // Introduce validation failure, destroy Image object before binding - vkDestroyImage(m_device->device(), image, NULL); - ASSERT_VK_SUCCESS(err); - - // Now Try to bind memory to this destroyed object - err = vkBindImageMemory(m_device->device(), image, mem, 0); - // This may very well return an error. - (void)err; - - m_errorMonitor->VerifyFound(); - - vkFreeMemory(m_device->device(), mem, NULL); -} - -TEST_F(VkLayerTest, ExceedMemoryAllocationCount) { - VkResult err = VK_SUCCESS; - const int max_mems = 32; - VkDeviceMemory mems[max_mems + 1]; - - if (!EnableDeviceProfileLayer()) { - printf("%s Failed to enable device profile layer.\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - PFN_vkSetPhysicalDeviceLimitsEXT fpvkSetPhysicalDeviceLimitsEXT = - (PFN_vkSetPhysicalDeviceLimitsEXT)vkGetInstanceProcAddr(instance(), "vkSetPhysicalDeviceLimitsEXT"); - PFN_vkGetOriginalPhysicalDeviceLimitsEXT fpvkGetOriginalPhysicalDeviceLimitsEXT = - (PFN_vkGetOriginalPhysicalDeviceLimitsEXT)vkGetInstanceProcAddr(instance(), "vkGetOriginalPhysicalDeviceLimitsEXT"); - - if (!(fpvkSetPhysicalDeviceLimitsEXT) || !(fpvkGetOriginalPhysicalDeviceLimitsEXT)) { - printf("%s Can't find device_profile_api functions; skipped.\n", kSkipPrefix); - return; - } - VkPhysicalDeviceProperties props; - fpvkGetOriginalPhysicalDeviceLimitsEXT(gpu(), &props.limits); - if (props.limits.maxMemoryAllocationCount > max_mems) { - props.limits.maxMemoryAllocationCount = max_mems; - fpvkSetPhysicalDeviceLimitsEXT(gpu(), &props.limits); - } - ASSERT_NO_FATAL_FAILURE(InitState()); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Number of currently valid memory objects is not less than the maximum allowed"); - - VkMemoryAllocateInfo mem_alloc = {}; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.memoryTypeIndex = 0; - mem_alloc.allocationSize = 4; - - int i; - for (i = 0; i <= max_mems; i++) { - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &mems[i]); - if (err != VK_SUCCESS) { - break; - } - } - m_errorMonitor->VerifyFound(); - - for (int j = 0; j < i; j++) { - vkFreeMemory(m_device->device(), mems[j], NULL); - } -} - -TEST_F(VkLayerTest, CreatePipelineBadVertexAttributeFormat) { - TEST_DESCRIPTION("Test that pipeline validation catches invalid vertex attribute formats"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkVertexInputBindingDescription input_binding; - memset(&input_binding, 0, sizeof(input_binding)); - - VkVertexInputAttributeDescription input_attribs; - memset(&input_attribs, 0, sizeof(input_attribs)); - - // Pick a really bad format for this purpose and make sure it should fail - input_attribs.format = VK_FORMAT_BC2_UNORM_BLOCK; - VkFormatProperties format_props = m_device->format_properties(input_attribs.format); - if ((format_props.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != 0) { - printf("%s Format unsuitable for test; skipped.\n", kSkipPrefix); - return; - } - - input_attribs.location = 0; - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkVertexInputAttributeDescription-format-00623"); - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - pipe.AddVertexInputBindings(&input_binding, 1); - pipe.AddVertexInputAttribs(&input_attribs, 1); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, ImageSampleCounts) { - TEST_DESCRIPTION("Use bad sample counts in image transfer calls to trigger validation errors."); - ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - - VkMemoryPropertyFlags reqs = 0; - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM; - image_create_info.extent.width = 256; - image_create_info.extent.height = 256; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.flags = 0; - - VkImageBlit blit_region = {}; - blit_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit_region.srcSubresource.baseArrayLayer = 0; - blit_region.srcSubresource.layerCount = 1; - blit_region.srcSubresource.mipLevel = 0; - blit_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit_region.dstSubresource.baseArrayLayer = 0; - blit_region.dstSubresource.layerCount = 1; - blit_region.dstSubresource.mipLevel = 0; - blit_region.srcOffsets[0] = {0, 0, 0}; - blit_region.srcOffsets[1] = {256, 256, 1}; - blit_region.dstOffsets[0] = {0, 0, 0}; - blit_region.dstOffsets[1] = {128, 128, 1}; - - // Create two images, the source with sampleCount = 4, and attempt to blit - // between them - { - image_create_info.samples = VK_SAMPLE_COUNT_4_BIT; - image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - VkImageObj src_image(m_device); - src_image.init(&image_create_info); - src_image.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - VkImageObj dst_image(m_device); - dst_image.init(&image_create_info); - dst_image.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - m_commandBuffer->begin(); - // TODO: These 2 VUs are redundant - expect one of them to go away - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-00233"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-00228"); - vkCmdBlitImage(m_commandBuffer->handle(), src_image.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image.handle(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit_region, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - m_commandBuffer->end(); - } - - // Create two images, the dest with sampleCount = 4, and attempt to blit - // between them - { - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - VkImageObj src_image(m_device); - src_image.init(&image_create_info); - src_image.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - image_create_info.samples = VK_SAMPLE_COUNT_4_BIT; - image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - VkImageObj dst_image(m_device); - dst_image.init(&image_create_info); - dst_image.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - m_commandBuffer->begin(); - // TODO: These 2 VUs are redundant - expect one of them to go away - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-dstImage-00234"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-00228"); - vkCmdBlitImage(m_commandBuffer->handle(), src_image.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image.handle(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit_region, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - m_commandBuffer->end(); - } - - VkBufferImageCopy copy_region = {}; - copy_region.bufferRowLength = 128; - copy_region.bufferImageHeight = 128; - copy_region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.imageSubresource.layerCount = 1; - copy_region.imageExtent.height = 64; - copy_region.imageExtent.width = 64; - copy_region.imageExtent.depth = 1; - - // Create src buffer and dst image with sampleCount = 4 and attempt to copy - // buffer to image - { - VkBufferObj src_buffer; - src_buffer.init_as_src(*m_device, 128 * 128 * 4, reqs); - image_create_info.samples = VK_SAMPLE_COUNT_4_BIT; - image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - VkImageObj dst_image(m_device); - dst_image.init(&image_create_info); - dst_image.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - m_commandBuffer->begin(); - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "was created with a sample count of VK_SAMPLE_COUNT_4_BIT but must be VK_SAMPLE_COUNT_1_BIT"); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), src_buffer.handle(), dst_image.handle(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region); - m_errorMonitor->VerifyFound(); - m_commandBuffer->end(); - } - - // Create dst buffer and src image with sampleCount = 4 and attempt to copy - // image to buffer - { - VkBufferObj dst_buffer; - dst_buffer.init_as_dst(*m_device, 128 * 128 * 4, reqs); - image_create_info.samples = VK_SAMPLE_COUNT_4_BIT; - 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_commandBuffer->begin(); - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "was created with a sample count of VK_SAMPLE_COUNT_4_BIT but must be VK_SAMPLE_COUNT_1_BIT"); - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), src_image.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - dst_buffer.handle(), 1, ©_region); - m_errorMonitor->VerifyFound(); - m_commandBuffer->end(); - } -} - -TEST_F(VkLayerTest, BlitImageFormatTypes) { - ASSERT_NO_FATAL_FAILURE(Init()); - - VkFormat f_unsigned = VK_FORMAT_R8G8B8A8_UINT; - VkFormat f_signed = VK_FORMAT_R8G8B8A8_SINT; - VkFormat f_float = VK_FORMAT_R32_SFLOAT; - VkFormat f_depth = VK_FORMAT_D32_SFLOAT_S8_UINT; - VkFormat f_depth2 = VK_FORMAT_D32_SFLOAT; - - if (!ImageFormatIsSupported(gpu(), f_unsigned, VK_IMAGE_TILING_OPTIMAL) || - !ImageFormatIsSupported(gpu(), f_signed, VK_IMAGE_TILING_OPTIMAL) || - !ImageFormatIsSupported(gpu(), f_float, VK_IMAGE_TILING_OPTIMAL) || - !ImageFormatIsSupported(gpu(), f_depth, VK_IMAGE_TILING_OPTIMAL) || - !ImageFormatIsSupported(gpu(), f_depth2, VK_IMAGE_TILING_OPTIMAL)) { - printf("%s Requested formats not supported - BlitImageFormatTypes skipped.\n", kSkipPrefix); - return; - } - - // Note any missing feature bits - bool usrc = !ImageFormatAndFeaturesSupported(gpu(), f_unsigned, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_SRC_BIT); - bool udst = !ImageFormatAndFeaturesSupported(gpu(), f_unsigned, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_DST_BIT); - bool ssrc = !ImageFormatAndFeaturesSupported(gpu(), f_signed, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_SRC_BIT); - bool sdst = !ImageFormatAndFeaturesSupported(gpu(), f_signed, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_DST_BIT); - bool fsrc = !ImageFormatAndFeaturesSupported(gpu(), f_float, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_SRC_BIT); - bool fdst = !ImageFormatAndFeaturesSupported(gpu(), f_float, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_DST_BIT); - bool d1dst = !ImageFormatAndFeaturesSupported(gpu(), f_depth, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_DST_BIT); - bool d2src = !ImageFormatAndFeaturesSupported(gpu(), f_depth2, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_SRC_BIT); - - VkImageObj unsigned_image(m_device); - unsigned_image.Init(64, 64, 1, f_unsigned, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(unsigned_image.initialized()); - unsigned_image.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL); - - VkImageObj signed_image(m_device); - signed_image.Init(64, 64, 1, f_signed, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(signed_image.initialized()); - signed_image.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL); - - VkImageObj float_image(m_device); - float_image.Init(64, 64, 1, f_float, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL, - 0); - ASSERT_TRUE(float_image.initialized()); - float_image.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL); - - VkImageObj depth_image(m_device); - depth_image.Init(64, 64, 1, f_depth, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL, - 0); - ASSERT_TRUE(depth_image.initialized()); - depth_image.SetLayout(VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_LAYOUT_GENERAL); - - VkImageObj depth_image2(m_device); - depth_image2.Init(64, 64, 1, f_depth2, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(depth_image2.initialized()); - depth_image2.SetLayout(VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_LAYOUT_GENERAL); - - VkImageBlit blitRegion = {}; - blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blitRegion.srcSubresource.baseArrayLayer = 0; - blitRegion.srcSubresource.layerCount = 1; - blitRegion.srcSubresource.mipLevel = 0; - blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blitRegion.dstSubresource.baseArrayLayer = 0; - blitRegion.dstSubresource.layerCount = 1; - blitRegion.dstSubresource.mipLevel = 0; - blitRegion.srcOffsets[0] = {0, 0, 0}; - blitRegion.srcOffsets[1] = {64, 64, 1}; - blitRegion.dstOffsets[0] = {0, 0, 0}; - blitRegion.dstOffsets[1] = {32, 32, 1}; - - m_commandBuffer->begin(); - - // Unsigned int vs not an int - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-00230"); - if (usrc) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-01999"); - if (fdst) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-dstImage-02000"); - vkCmdBlitImage(m_commandBuffer->handle(), unsigned_image.image(), unsigned_image.Layout(), float_image.image(), - float_image.Layout(), 1, &blitRegion, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-00230"); - if (fsrc) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-01999"); - if (udst) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-dstImage-02000"); - vkCmdBlitImage(m_commandBuffer->handle(), float_image.image(), float_image.Layout(), unsigned_image.image(), - unsigned_image.Layout(), 1, &blitRegion, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - // Signed int vs not an int, - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-00229"); - if (ssrc) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-01999"); - if (fdst) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-dstImage-02000"); - vkCmdBlitImage(m_commandBuffer->handle(), signed_image.image(), signed_image.Layout(), float_image.image(), - float_image.Layout(), 1, &blitRegion, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-00229"); - if (fsrc) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-01999"); - if (sdst) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-dstImage-02000"); - vkCmdBlitImage(m_commandBuffer->handle(), float_image.image(), float_image.Layout(), signed_image.image(), - signed_image.Layout(), 1, &blitRegion, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - // Signed vs Unsigned int - generates both VUs - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-00229"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-00230"); - if (ssrc) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-01999"); - if (udst) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-dstImage-02000"); - vkCmdBlitImage(m_commandBuffer->handle(), signed_image.image(), signed_image.Layout(), unsigned_image.image(), - unsigned_image.Layout(), 1, &blitRegion, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-00229"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-00230"); - if (usrc) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-01999"); - if (sdst) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-dstImage-02000"); - vkCmdBlitImage(m_commandBuffer->handle(), unsigned_image.image(), unsigned_image.Layout(), signed_image.image(), - signed_image.Layout(), 1, &blitRegion, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - // Depth vs any non-identical depth format - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-00231"); - blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (d2src) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-01999"); - if (d1dst) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-dstImage-02000"); - vkCmdBlitImage(m_commandBuffer->handle(), depth_image2.image(), depth_image2.Layout(), depth_image.image(), - depth_image.Layout(), 1, &blitRegion, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, BlitImageFilters) { - bool cubic_support = false; - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, "VK_IMG_filter_cubic")) { - m_device_extension_names.push_back("VK_IMG_filter_cubic"); - cubic_support = true; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkFormat fmt = VK_FORMAT_R8_UINT; - if (!ImageFormatIsSupported(gpu(), fmt, VK_IMAGE_TILING_OPTIMAL)) { - printf("%s No R8_UINT format support - BlitImageFilters skipped.\n", kSkipPrefix); - return; - } - - // Create 2D images - VkImageObj src2D(m_device); - VkImageObj dst2D(m_device); - src2D.Init(64, 64, 1, fmt, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - dst2D.Init(64, 64, 1, fmt, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(src2D.initialized()); - ASSERT_TRUE(dst2D.initialized()); - src2D.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL); - dst2D.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL); - - // Create 3D image - VkImageCreateInfo ci; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_3D; - ci.format = fmt; - ci.extent = {64, 64, 4}; - ci.mipLevels = 1; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.tiling = VK_IMAGE_TILING_OPTIMAL; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.queueFamilyIndexCount = 0; - ci.pQueueFamilyIndices = NULL; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkImageObj src3D(m_device); - src3D.init(&ci); - ASSERT_TRUE(src3D.initialized()); - - VkImageBlit blitRegion = {}; - blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blitRegion.srcSubresource.baseArrayLayer = 0; - blitRegion.srcSubresource.layerCount = 1; - blitRegion.srcSubresource.mipLevel = 0; - blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blitRegion.dstSubresource.baseArrayLayer = 0; - blitRegion.dstSubresource.layerCount = 1; - blitRegion.dstSubresource.mipLevel = 0; - blitRegion.srcOffsets[0] = {0, 0, 0}; - blitRegion.srcOffsets[1] = {48, 48, 1}; - blitRegion.dstOffsets[0] = {0, 0, 0}; - blitRegion.dstOffsets[1] = {64, 64, 1}; - - m_commandBuffer->begin(); - - // UINT format should not support linear filtering, but check to be sure - if (!ImageFormatAndFeaturesSupported(gpu(), fmt, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-filter-02001"); - vkCmdBlitImage(m_commandBuffer->handle(), src2D.image(), src2D.Layout(), dst2D.image(), dst2D.Layout(), 1, &blitRegion, - VK_FILTER_LINEAR); - m_errorMonitor->VerifyFound(); - } - - if (cubic_support && !ImageFormatAndFeaturesSupported(gpu(), fmt, VK_IMAGE_TILING_OPTIMAL, - VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG)) { - // Invalid filter CUBIC_IMG - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-filter-02002"); - vkCmdBlitImage(m_commandBuffer->handle(), src3D.image(), src3D.Layout(), dst2D.image(), dst2D.Layout(), 1, &blitRegion, - VK_FILTER_CUBIC_IMG); - m_errorMonitor->VerifyFound(); - - // Invalid filter CUBIC_IMG + invalid 2D source image - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-filter-02002"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-filter-00237"); - vkCmdBlitImage(m_commandBuffer->handle(), src2D.image(), src2D.Layout(), dst2D.image(), dst2D.Layout(), 1, &blitRegion, - VK_FILTER_CUBIC_IMG); - m_errorMonitor->VerifyFound(); - } - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, BlitImageLayout) { - TEST_DESCRIPTION("Incorrect vkCmdBlitImage layouts"); - - ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - - VkResult err; - VkFormat fmt = VK_FORMAT_R8G8B8A8_UNORM; - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - - // Create images - VkImageObj img_src_transfer(m_device); - VkImageObj img_dst_transfer(m_device); - VkImageObj img_general(m_device); - VkImageObj img_color(m_device); - - img_src_transfer.InitNoLayout(64, 64, 1, fmt, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - img_dst_transfer.InitNoLayout(64, 64, 1, fmt, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - img_general.InitNoLayout(64, 64, 1, fmt, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - img_color.InitNoLayout(64, 64, 1, fmt, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - - ASSERT_TRUE(img_src_transfer.initialized()); - ASSERT_TRUE(img_dst_transfer.initialized()); - ASSERT_TRUE(img_general.initialized()); - ASSERT_TRUE(img_color.initialized()); - - img_src_transfer.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - img_dst_transfer.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - img_general.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL); - img_color.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - VkImageBlit blit_region = {}; - blit_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit_region.srcSubresource.baseArrayLayer = 0; - blit_region.srcSubresource.layerCount = 1; - blit_region.srcSubresource.mipLevel = 0; - blit_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit_region.dstSubresource.baseArrayLayer = 0; - blit_region.dstSubresource.layerCount = 1; - blit_region.dstSubresource.mipLevel = 0; - blit_region.srcOffsets[0] = {0, 0, 0}; - blit_region.srcOffsets[1] = {48, 48, 1}; - blit_region.dstOffsets[0] = {0, 0, 0}; - blit_region.dstOffsets[1] = {64, 64, 1}; - - m_commandBuffer->begin(); - - // Illegal srcImageLayout - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImageLayout-00222"); - vkCmdBlitImage(m_commandBuffer->handle(), img_src_transfer.image(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - img_dst_transfer.image(), img_dst_transfer.Layout(), 1, &blit_region, VK_FILTER_LINEAR); - m_errorMonitor->VerifyFound(); - - // Illegal destImageLayout - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-dstImageLayout-00227"); - vkCmdBlitImage(m_commandBuffer->handle(), img_src_transfer.image(), img_src_transfer.Layout(), img_dst_transfer.image(), - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1, &blit_region, VK_FILTER_LINEAR); - - m_commandBuffer->end(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - - err = vkQueueWaitIdle(m_device->m_queue); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->reset(0); - m_commandBuffer->begin(); - - // Source image in invalid layout at start of the CB - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout"); - vkCmdBlitImage(m_commandBuffer->handle(), img_src_transfer.image(), img_src_transfer.Layout(), img_color.image(), - VK_IMAGE_LAYOUT_GENERAL, 1, &blit_region, VK_FILTER_LINEAR); - - m_commandBuffer->end(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - err = vkQueueWaitIdle(m_device->m_queue); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->reset(0); - m_commandBuffer->begin(); - - // Destination image in invalid layout at start of the CB - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout"); - vkCmdBlitImage(m_commandBuffer->handle(), img_color.image(), VK_IMAGE_LAYOUT_GENERAL, img_dst_transfer.image(), - img_dst_transfer.Layout(), 1, &blit_region, VK_FILTER_LINEAR); - - m_commandBuffer->end(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - err = vkQueueWaitIdle(m_device->m_queue); - ASSERT_VK_SUCCESS(err); - - // Source image in invalid layout in the middle of CB - m_commandBuffer->reset(0); - m_commandBuffer->begin(); - - VkImageMemoryBarrier img_barrier = {}; - img_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - img_barrier.pNext = nullptr; - img_barrier.srcAccessMask = 0; - img_barrier.dstAccessMask = 0; - img_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - img_barrier.image = img_general.handle(); - img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - img_barrier.subresourceRange.baseArrayLayer = 0; - img_barrier.subresourceRange.baseMipLevel = 0; - img_barrier.subresourceRange.layerCount = 1; - img_barrier.subresourceRange.levelCount = 1; - - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, - nullptr, 0, nullptr, 1, &img_barrier); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImageLayout-00221"); - vkCmdBlitImage(m_commandBuffer->handle(), img_general.image(), VK_IMAGE_LAYOUT_GENERAL, img_dst_transfer.image(), - img_dst_transfer.Layout(), 1, &blit_region, VK_FILTER_LINEAR); - - m_commandBuffer->end(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - err = vkQueueWaitIdle(m_device->m_queue); - ASSERT_VK_SUCCESS(err); - - // Destination image in invalid layout in the middle of CB - m_commandBuffer->reset(0); - m_commandBuffer->begin(); - - img_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - img_barrier.image = img_dst_transfer.handle(); - - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, - nullptr, 0, nullptr, 1, &img_barrier); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-dstImageLayout-00226"); - vkCmdBlitImage(m_commandBuffer->handle(), img_src_transfer.image(), img_src_transfer.Layout(), img_dst_transfer.image(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit_region, VK_FILTER_LINEAR); - - m_commandBuffer->end(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - err = vkQueueWaitIdle(m_device->m_queue); - ASSERT_VK_SUCCESS(err); -} - -TEST_F(VkLayerTest, BlitImageOffsets) { - ASSERT_NO_FATAL_FAILURE(Init()); - - VkFormat fmt = VK_FORMAT_R8G8B8A8_UNORM; - if (!ImageFormatAndFeaturesSupported(gpu(), fmt, VK_IMAGE_TILING_OPTIMAL, - VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT)) { - printf("%s No blit feature bits - BlitImageOffsets skipped.\n", kSkipPrefix); - return; - } - - VkImageCreateInfo ci; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_1D; - ci.format = fmt; - ci.extent = {64, 1, 1}; - ci.mipLevels = 1; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.tiling = VK_IMAGE_TILING_OPTIMAL; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.queueFamilyIndexCount = 0; - ci.pQueueFamilyIndices = NULL; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkImageObj image_1D(m_device); - image_1D.init(&ci); - ASSERT_TRUE(image_1D.initialized()); - - ci.imageType = VK_IMAGE_TYPE_2D; - ci.extent = {64, 64, 1}; - VkImageObj image_2D(m_device); - image_2D.init(&ci); - ASSERT_TRUE(image_2D.initialized()); - - ci.imageType = VK_IMAGE_TYPE_3D; - ci.extent = {64, 64, 64}; - VkImageObj image_3D(m_device); - image_3D.init(&ci); - ASSERT_TRUE(image_3D.initialized()); - - VkImageBlit blit_region = {}; - blit_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit_region.srcSubresource.baseArrayLayer = 0; - blit_region.srcSubresource.layerCount = 1; - blit_region.srcSubresource.mipLevel = 0; - blit_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit_region.dstSubresource.baseArrayLayer = 0; - blit_region.dstSubresource.layerCount = 1; - blit_region.dstSubresource.mipLevel = 0; - - m_commandBuffer->begin(); - - // 1D, with src/dest y offsets other than (0,1) - blit_region.srcOffsets[0] = {0, 1, 0}; - blit_region.srcOffsets[1] = {30, 1, 1}; - blit_region.dstOffsets[0] = {32, 0, 0}; - blit_region.dstOffsets[1] = {64, 1, 1}; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageBlit-srcImage-00245"); - vkCmdBlitImage(m_commandBuffer->handle(), image_1D.image(), image_1D.Layout(), image_1D.image(), image_1D.Layout(), 1, - &blit_region, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - blit_region.srcOffsets[0] = {0, 0, 0}; - blit_region.dstOffsets[0] = {32, 1, 0}; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageBlit-dstImage-00250"); - vkCmdBlitImage(m_commandBuffer->handle(), image_1D.image(), image_1D.Layout(), image_1D.image(), image_1D.Layout(), 1, - &blit_region, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - // 2D, with src/dest z offsets other than (0,1) - blit_region.srcOffsets[0] = {0, 0, 1}; - blit_region.srcOffsets[1] = {24, 31, 1}; - blit_region.dstOffsets[0] = {32, 32, 0}; - blit_region.dstOffsets[1] = {64, 64, 1}; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageBlit-srcImage-00247"); - vkCmdBlitImage(m_commandBuffer->handle(), image_2D.image(), image_2D.Layout(), image_2D.image(), image_2D.Layout(), 1, - &blit_region, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - blit_region.srcOffsets[0] = {0, 0, 0}; - blit_region.dstOffsets[0] = {32, 32, 1}; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageBlit-dstImage-00252"); - vkCmdBlitImage(m_commandBuffer->handle(), image_2D.image(), image_2D.Layout(), image_2D.image(), image_2D.Layout(), 1, - &blit_region, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - // Source offsets exceeding source image dimensions - blit_region.srcOffsets[0] = {0, 0, 0}; - blit_region.srcOffsets[1] = {65, 64, 1}; // src x - blit_region.dstOffsets[0] = {0, 0, 0}; - blit_region.dstOffsets[1] = {64, 64, 1}; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageBlit-srcOffset-00243"); // x - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-pRegions-00215"); // src region - vkCmdBlitImage(m_commandBuffer->handle(), image_3D.image(), image_3D.Layout(), image_2D.image(), image_2D.Layout(), 1, - &blit_region, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - blit_region.srcOffsets[1] = {64, 65, 1}; // src y - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageBlit-srcOffset-00244"); // y - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-pRegions-00215"); // src region - vkCmdBlitImage(m_commandBuffer->handle(), image_3D.image(), image_3D.Layout(), image_2D.image(), image_2D.Layout(), 1, - &blit_region, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - blit_region.srcOffsets[0] = {0, 0, 65}; // src z - blit_region.srcOffsets[1] = {64, 64, 64}; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageBlit-srcOffset-00246"); // z - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-pRegions-00215"); // src region - vkCmdBlitImage(m_commandBuffer->handle(), image_3D.image(), image_3D.Layout(), image_2D.image(), image_2D.Layout(), 1, - &blit_region, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - // Dest offsets exceeding source image dimensions - blit_region.srcOffsets[0] = {0, 0, 0}; - blit_region.srcOffsets[1] = {64, 64, 1}; - blit_region.dstOffsets[0] = {96, 64, 32}; // dst x - blit_region.dstOffsets[1] = {64, 0, 33}; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageBlit-dstOffset-00248"); // x - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-pRegions-00216"); // dst region - vkCmdBlitImage(m_commandBuffer->handle(), image_2D.image(), image_2D.Layout(), image_3D.image(), image_3D.Layout(), 1, - &blit_region, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - blit_region.dstOffsets[0] = {0, 65, 32}; // dst y - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageBlit-dstOffset-00249"); // y - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-pRegions-00216"); // dst region - vkCmdBlitImage(m_commandBuffer->handle(), image_2D.image(), image_2D.Layout(), image_3D.image(), image_3D.Layout(), 1, - &blit_region, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - blit_region.dstOffsets[0] = {0, 64, 65}; // dst z - blit_region.dstOffsets[1] = {64, 0, 64}; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageBlit-dstOffset-00251"); // z - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-pRegions-00216"); // dst region - vkCmdBlitImage(m_commandBuffer->handle(), image_2D.image(), image_2D.Layout(), image_3D.image(), image_3D.Layout(), 1, - &blit_region, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, MiscBlitImageTests) { - ASSERT_NO_FATAL_FAILURE(Init()); - - VkFormat f_color = VK_FORMAT_R32_SFLOAT; // Need features ..BLIT_SRC_BIT & ..BLIT_DST_BIT - - if (!ImageFormatAndFeaturesSupported(gpu(), f_color, VK_IMAGE_TILING_OPTIMAL, - VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT)) { - printf("%s Requested format features unavailable - MiscBlitImageTests skipped.\n", kSkipPrefix); - return; - } - - VkImageCreateInfo ci; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_2D; - ci.format = f_color; - ci.extent = {64, 64, 1}; - ci.mipLevels = 1; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.tiling = VK_IMAGE_TILING_OPTIMAL; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.queueFamilyIndexCount = 0; - ci.pQueueFamilyIndices = NULL; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - // 2D color image - VkImageObj color_img(m_device); - color_img.init(&ci); - ASSERT_TRUE(color_img.initialized()); - - // 2D multi-sample image - ci.samples = VK_SAMPLE_COUNT_4_BIT; - VkImageObj ms_img(m_device); - ms_img.init(&ci); - ASSERT_TRUE(ms_img.initialized()); - - // 3D color image - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.imageType = VK_IMAGE_TYPE_3D; - ci.extent = {64, 64, 8}; - VkImageObj color_3D_img(m_device); - color_3D_img.init(&ci); - ASSERT_TRUE(color_3D_img.initialized()); - - VkImageBlit blitRegion = {}; - blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blitRegion.srcSubresource.baseArrayLayer = 0; - blitRegion.srcSubresource.layerCount = 1; - blitRegion.srcSubresource.mipLevel = 0; - blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blitRegion.dstSubresource.baseArrayLayer = 0; - blitRegion.dstSubresource.layerCount = 1; - blitRegion.dstSubresource.mipLevel = 0; - blitRegion.srcOffsets[0] = {0, 0, 0}; - blitRegion.srcOffsets[1] = {16, 16, 1}; - blitRegion.dstOffsets[0] = {32, 32, 0}; - blitRegion.dstOffsets[1] = {64, 64, 1}; - - m_commandBuffer->begin(); - - // Blit with aspectMask errors - blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageBlit-aspectMask-00241"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageBlit-aspectMask-00242"); - vkCmdBlitImage(m_commandBuffer->handle(), color_img.image(), color_img.Layout(), color_img.image(), color_img.Layout(), 1, - &blitRegion, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - // Blit with invalid src mip level - blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blitRegion.srcSubresource.mipLevel = ci.mipLevels; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdBlitImage-srcSubresource-01705"); // invalid srcSubresource.mipLevel - // Redundant unavoidable errors - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageBlit-srcOffset-00243"); // out-of-bounds srcOffset.x - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageBlit-srcOffset-00244"); // out-of-bounds srcOffset.y - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageBlit-srcOffset-00246"); // out-of-bounds srcOffset.z - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdBlitImage-pRegions-00215"); // region not contained within src image - vkCmdBlitImage(m_commandBuffer->handle(), color_img.image(), color_img.Layout(), color_img.image(), color_img.Layout(), 1, - &blitRegion, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - // Blit with invalid dst mip level - blitRegion.srcSubresource.mipLevel = 0; - blitRegion.dstSubresource.mipLevel = ci.mipLevels; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdBlitImage-dstSubresource-01706"); // invalid dstSubresource.mipLevel - // Redundant unavoidable errors - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageBlit-dstOffset-00248"); // out-of-bounds dstOffset.x - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageBlit-dstOffset-00249"); // out-of-bounds dstOffset.y - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageBlit-dstOffset-00251"); // out-of-bounds dstOffset.z - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdBlitImage-pRegions-00216"); // region not contained within dst image - vkCmdBlitImage(m_commandBuffer->handle(), color_img.image(), color_img.Layout(), color_img.image(), color_img.Layout(), 1, - &blitRegion, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - // Blit with invalid src array layer - blitRegion.dstSubresource.mipLevel = 0; - blitRegion.srcSubresource.baseArrayLayer = ci.arrayLayers; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdBlitImage-srcSubresource-01707"); // invalid srcSubresource layer range - vkCmdBlitImage(m_commandBuffer->handle(), color_img.image(), color_img.Layout(), color_img.image(), color_img.Layout(), 1, - &blitRegion, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - // Blit with invalid dst array layer - blitRegion.srcSubresource.baseArrayLayer = 0; - blitRegion.dstSubresource.baseArrayLayer = ci.arrayLayers; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdBlitImage-dstSubresource-01708"); // invalid dstSubresource layer range - // Redundant unavoidable errors - vkCmdBlitImage(m_commandBuffer->handle(), color_img.image(), color_img.Layout(), color_img.image(), color_img.Layout(), 1, - &blitRegion, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - blitRegion.dstSubresource.baseArrayLayer = 0; - - // Blit multi-sample image - // TODO: redundant VUs, one (1c8) or two (1d2 & 1d4) should be eliminated. - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-00228"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-srcImage-00233"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-dstImage-00234"); - vkCmdBlitImage(m_commandBuffer->handle(), ms_img.image(), ms_img.Layout(), ms_img.image(), ms_img.Layout(), 1, &blitRegion, - VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - // Blit 3D with baseArrayLayer != 0 or layerCount != 1 - blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blitRegion.srcSubresource.baseArrayLayer = 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageBlit-srcImage-00240"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdBlitImage-srcSubresource-01707"); // base+count > total layer count - vkCmdBlitImage(m_commandBuffer->handle(), color_3D_img.image(), color_3D_img.Layout(), color_3D_img.image(), - color_3D_img.Layout(), 1, &blitRegion, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - blitRegion.srcSubresource.baseArrayLayer = 0; - blitRegion.srcSubresource.layerCount = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageBlit-srcImage-00240"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageSubresourceLayers-layerCount-01700"); // layer count == 0 (src) - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageBlit-layerCount-00239"); // src/dst layer count mismatch - vkCmdBlitImage(m_commandBuffer->handle(), color_3D_img.image(), color_3D_img.Layout(), color_3D_img.image(), - color_3D_img.Layout(), 1, &blitRegion, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, BlitToDepthImageTests) { - ASSERT_NO_FATAL_FAILURE(Init()); - - // Need feature ..BLIT_SRC_BIT but not ..BLIT_DST_BIT - // TODO: provide more choices here; supporting D32_SFLOAT as BLIT_DST isn't unheard of. - VkFormat f_depth = VK_FORMAT_D32_SFLOAT; - - if (!ImageFormatAndFeaturesSupported(gpu(), f_depth, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_SRC_BIT) || - ImageFormatAndFeaturesSupported(gpu(), f_depth, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_BLIT_DST_BIT)) { - printf("%s Requested format features unavailable - BlitToDepthImageTests skipped.\n", kSkipPrefix); - return; - } - - VkImageCreateInfo ci; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_2D; - ci.format = f_depth; - ci.extent = {64, 64, 1}; - ci.mipLevels = 1; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.tiling = VK_IMAGE_TILING_OPTIMAL; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.queueFamilyIndexCount = 0; - ci.pQueueFamilyIndices = NULL; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - // 2D depth image - VkImageObj depth_img(m_device); - depth_img.init(&ci); - ASSERT_TRUE(depth_img.initialized()); - - VkImageBlit blitRegion = {}; - blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blitRegion.srcSubresource.baseArrayLayer = 0; - blitRegion.srcSubresource.layerCount = 1; - blitRegion.srcSubresource.mipLevel = 0; - blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blitRegion.dstSubresource.baseArrayLayer = 0; - blitRegion.dstSubresource.layerCount = 1; - blitRegion.dstSubresource.mipLevel = 0; - blitRegion.srcOffsets[0] = {0, 0, 0}; - blitRegion.srcOffsets[1] = {16, 16, 1}; - blitRegion.dstOffsets[0] = {32, 32, 0}; - blitRegion.dstOffsets[1] = {64, 64, 1}; - - m_commandBuffer->begin(); - - // Blit depth image - has SRC_BIT but not DST_BIT - blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBlitImage-dstImage-02000"); - vkCmdBlitImage(m_commandBuffer->handle(), depth_img.image(), depth_img.Layout(), depth_img.image(), depth_img.Layout(), 1, - &blitRegion, VK_FILTER_NEAREST); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, MinImageTransferGranularity) { - TEST_DESCRIPTION("Tests for validation of Queue Family property minImageTransferGranularity."); - ASSERT_NO_FATAL_FAILURE(Init()); - - auto queue_family_properties = m_device->phy().queue_properties(); - auto large_granularity_family = - std::find_if(queue_family_properties.begin(), queue_family_properties.end(), [](VkQueueFamilyProperties family_properties) { - VkExtent3D family_granularity = family_properties.minImageTransferGranularity; - // We need a queue family that supports copy operations and has a large enough minImageTransferGranularity for the tests - // below to make sense. - return (family_properties.queueFlags & VK_QUEUE_TRANSFER_BIT || family_properties.queueFlags & VK_QUEUE_GRAPHICS_BIT || - family_properties.queueFlags & VK_QUEUE_COMPUTE_BIT) && - family_granularity.depth >= 4 && family_granularity.width >= 4 && family_granularity.height >= 4; - }); - - if (large_granularity_family == queue_family_properties.end()) { - printf("%s No queue family has a large enough granularity for this test to be meaningful, skipping test\n", kSkipPrefix); - return; - } - const size_t queue_family_index = std::distance(queue_family_properties.begin(), large_granularity_family); - VkExtent3D granularity = queue_family_properties[queue_family_index].minImageTransferGranularity; - VkCommandPoolObj command_pool(m_device, queue_family_index, 0); - - // Create two images of different types and try to copy between them - VkImage srcImage; - VkImage dstImage; - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_3D; - image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM; - image_create_info.extent.width = granularity.width * 2; - image_create_info.extent.height = granularity.height * 2; - image_create_info.extent.depth = granularity.depth * 2; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - image_create_info.flags = 0; - - VkImageObj src_image_obj(m_device); - src_image_obj.init(&image_create_info); - ASSERT_TRUE(src_image_obj.initialized()); - srcImage = src_image_obj.handle(); - - image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - - VkImageObj dst_image_obj(m_device); - dst_image_obj.init(&image_create_info); - ASSERT_TRUE(dst_image_obj.initialized()); - dstImage = dst_image_obj.handle(); - - VkCommandBufferObj command_buffer(m_device, &command_pool); - ASSERT_TRUE(command_buffer.initialized()); - command_buffer.begin(); - - VkImageCopy copyRegion; - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.srcSubresource.mipLevel = 0; - copyRegion.srcSubresource.baseArrayLayer = 0; - copyRegion.srcSubresource.layerCount = 1; - copyRegion.srcOffset.x = 0; - copyRegion.srcOffset.y = 0; - copyRegion.srcOffset.z = 0; - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.dstSubresource.mipLevel = 0; - copyRegion.dstSubresource.baseArrayLayer = 0; - copyRegion.dstSubresource.layerCount = 1; - copyRegion.dstOffset.x = 0; - copyRegion.dstOffset.y = 0; - copyRegion.dstOffset.z = 0; - copyRegion.extent.width = granularity.width; - copyRegion.extent.height = granularity.height; - copyRegion.extent.depth = granularity.depth; - - // Introduce failure by setting srcOffset to a bad granularity value - copyRegion.srcOffset.y = 3; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImage-srcOffset-01783"); // srcOffset image transfer granularity - command_buffer.CopyImage(srcImage, VK_IMAGE_LAYOUT_GENERAL, dstImage, VK_IMAGE_LAYOUT_GENERAL, 1, ©Region); - m_errorMonitor->VerifyFound(); - - // Introduce failure by setting extent to a granularity value that is bad - // for both the source and destination image. - copyRegion.srcOffset.y = 0; - copyRegion.extent.width = 3; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImage-srcOffset-01783"); // src extent image transfer granularity - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImage-dstOffset-01784"); // dst extent image transfer granularity - command_buffer.CopyImage(srcImage, VK_IMAGE_LAYOUT_GENERAL, dstImage, VK_IMAGE_LAYOUT_GENERAL, 1, ©Region); - m_errorMonitor->VerifyFound(); - - // Now do some buffer/image copies - VkBufferObj buffer; - VkMemoryPropertyFlags reqs = 0; - buffer.init_as_src_and_dst(*m_device, 8 * granularity.height * granularity.width * granularity.depth, reqs); - VkBufferImageCopy region = {}; - region.bufferOffset = 0; - region.bufferRowLength = 0; - region.bufferImageHeight = 0; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.layerCount = 1; - region.imageExtent.height = granularity.height; - region.imageExtent.width = granularity.width; - region.imageExtent.depth = granularity.depth; - region.imageOffset.x = 0; - region.imageOffset.y = 0; - region.imageOffset.z = 0; - - // Introduce failure by setting imageExtent to a bad granularity value - region.imageExtent.width = 3; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImageToBuffer-imageOffset-01794"); // image transfer granularity - vkCmdCopyImageToBuffer(command_buffer.handle(), srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer.handle(), 1, ®ion); - m_errorMonitor->VerifyFound(); - region.imageExtent.width = granularity.width; - - // Introduce failure by setting imageOffset to a bad granularity value - region.imageOffset.z = 3; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyBufferToImage-imageOffset-01793"); // image transfer granularity - vkCmdCopyBufferToImage(command_buffer.handle(), buffer.handle(), dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - m_errorMonitor->VerifyFound(); - - command_buffer.end(); -} - -TEST_F(VkLayerTest, MismatchedQueueFamiliesOnSubmit) { - TEST_DESCRIPTION( - "Submit command buffer created using one queue family and attempt to submit them on a queue created in a different queue " - "family."); - - ASSERT_NO_FATAL_FAILURE(Init()); // assumes it initializes all queue families on vkCreateDevice - - // This test is meaningless unless we have multiple queue families - auto queue_family_properties = m_device->phy().queue_properties(); - std::vector<uint32_t> queue_families; - for (uint32_t i = 0; i < queue_family_properties.size(); ++i) - if (queue_family_properties[i].queueCount > 0) queue_families.push_back(i); - - if (queue_families.size() < 2) { - printf("%s Device only has one queue family; skipped.\n", kSkipPrefix); - return; - } - - const uint32_t queue_family = queue_families[0]; - - const uint32_t other_queue_family = queue_families[1]; - VkQueue other_queue; - vkGetDeviceQueue(m_device->device(), other_queue_family, 0, &other_queue); - - VkCommandPoolObj cmd_pool(m_device, queue_family); - VkCommandBufferObj cmd_buff(m_device, &cmd_pool); - - cmd_buff.begin(); - cmd_buff.end(); - - // Submit on the wrong queue - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &cmd_buff.handle(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkQueueSubmit-pCommandBuffers-00074"); - vkQueueSubmit(other_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, DrawWithPipelineIncompatibleWithSubpass) { - TEST_DESCRIPTION("Use a pipeline for the wrong subpass in a render pass instance"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // A renderpass with two subpasses, both writing the same attachment. - VkAttachmentDescription attach[] = { - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - }; - VkAttachmentReference ref = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - VkSubpassDescription subpasses[] = { - {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &ref, nullptr, nullptr, 0, nullptr}, - {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &ref, nullptr, nullptr, 0, nullptr}, - }; - VkSubpassDependency dep = {0, - 1, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_DEPENDENCY_BY_REGION_BIT}; - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, attach, 2, subpasses, 1, &dep}; - VkRenderPass rp; - VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - - VkImageObj image(m_device); - image.InitNoLayout(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - VkImageView imageView = image.targetView(VK_FORMAT_R8G8B8A8_UNORM); - - VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 1, &imageView, 32, 32, 1}; - VkFramebuffer fb; - err = vkCreateFramebuffer(m_device->device(), &fbci, nullptr, &fb); - ASSERT_VK_SUCCESS(err); - - char const *vsSource = - "#version 450\n" - "void main() { gl_Position = vec4(1); }\n"; - char const *fsSource = - "#version 450\n" - "layout(location=0) out vec4 color;\n" - "void main() { color = vec4(1); }\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; - m_viewports.push_back(viewport); - pipe.SetViewport(m_viewports); - VkRect2D rect = {}; - m_scissors.push_back(rect); - pipe.SetScissor(m_scissors); - - const VkPipelineLayoutObj pl(m_device); - pipe.CreateVKPipeline(pl.handle(), rp); - - m_commandBuffer->begin(); - - VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - nullptr, - rp, - fb, - {{ - 0, - 0, - }, - {32, 32}}, - 0, - nullptr}; - - // subtest 1: bind in the wrong subpass - vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE); - vkCmdNextSubpass(m_commandBuffer->handle(), VK_SUBPASS_CONTENTS_INLINE); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "built for subpass 0 but used in subpass 1"); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); - m_errorMonitor->VerifyFound(); - - vkCmdEndRenderPass(m_commandBuffer->handle()); - - // subtest 2: bind in correct subpass, then transition to next subpass - vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdNextSubpass(m_commandBuffer->handle(), VK_SUBPASS_CONTENTS_INLINE); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "built for subpass 0 but used in subpass 1"); - vkCmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); - m_errorMonitor->VerifyFound(); - - vkCmdEndRenderPass(m_commandBuffer->handle()); - - m_commandBuffer->end(); - - vkDestroyFramebuffer(m_device->device(), fb, nullptr); - vkDestroyRenderPass(m_device->device(), rp, nullptr); -} - -TEST_F(VkLayerTest, ImageBarrierSubpassConflicts) { - TEST_DESCRIPTION("Add a pipeline barrier within a subpass that has conflicting state"); - ASSERT_NO_FATAL_FAILURE(Init()); - - // A renderpass with a single subpass that declared a self-dependency - VkAttachmentDescription attach[] = { - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - }; - VkAttachmentReference ref = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - VkSubpassDescription subpasses[] = { - {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &ref, nullptr, nullptr, 0, nullptr}, - }; - VkSubpassDependency dep = {0, - 0, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_DEPENDENCY_BY_REGION_BIT}; - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, attach, 1, subpasses, 1, &dep}; - VkRenderPass rp; - VkRenderPass rp_noselfdep; - - VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - rpci.dependencyCount = 0; - rpci.pDependencies = nullptr; - err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp_noselfdep); - ASSERT_VK_SUCCESS(err); - - VkImageObj image(m_device); - image.InitNoLayout(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - VkImageView imageView = image.targetView(VK_FORMAT_R8G8B8A8_UNORM); - - VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 1, &imageView, 32, 32, 1}; - VkFramebuffer fb; - err = vkCreateFramebuffer(m_device->device(), &fbci, nullptr, &fb); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-pDependencies-02285"); - m_commandBuffer->begin(); - VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - nullptr, - rp_noselfdep, - fb, - {{ - 0, - 0, - }, - {32, 32}}, - 0, - nullptr}; - - vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE); - VkMemoryBarrier mem_barrier = {}; - mem_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; - mem_barrier.pNext = NULL; - mem_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; - mem_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 1, - &mem_barrier, 0, nullptr, 0, nullptr); - m_errorMonitor->VerifyFound(); - vkCmdEndRenderPass(m_commandBuffer->handle()); - - rpbi.renderPass = rp; - vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE); - VkImageMemoryBarrier img_barrier = {}; - img_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - img_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - img_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - img_barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - img_barrier.image = image.handle(); - img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - img_barrier.subresourceRange.baseArrayLayer = 0; - img_barrier.subresourceRange.baseMipLevel = 0; - img_barrier.subresourceRange.layerCount = 1; - img_barrier.subresourceRange.levelCount = 1; - // Mis-match src stage mask - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-pDependencies-02285"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-pDependencies-02285"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - // Now mis-match dst stage mask - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-pDependencies-02285"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-pDependencies-02285"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_HOST_BIT, - VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - // Set srcQueueFamilyIndex to something other than IGNORED - img_barrier.srcQueueFamilyIndex = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-srcQueueFamilyIndex-01182"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - // Mis-match mem barrier src access mask - mem_barrier = {}; - mem_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; - mem_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - mem_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-pDependencies-02285"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-pDependencies-02285"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 1, &mem_barrier, 0, nullptr, 0, - nullptr); - m_errorMonitor->VerifyFound(); - // Mis-match mem barrier dst access mask. Also set srcAccessMask to 0 which should not cause an error - mem_barrier.srcAccessMask = 0; - mem_barrier.dstAccessMask = VK_ACCESS_HOST_WRITE_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-pDependencies-02285"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-pDependencies-02285"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 1, &mem_barrier, 0, nullptr, 0, - nullptr); - m_errorMonitor->VerifyFound(); - // Mis-match image barrier src access mask - img_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-pDependencies-02285"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-pDependencies-02285"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - // Mis-match image barrier dst access mask - img_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - img_barrier.dstAccessMask = VK_ACCESS_HOST_WRITE_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-pDependencies-02285"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-pDependencies-02285"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - // Mis-match dependencyFlags - img_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-pDependencies-02285"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0 /* wrong */, 0, nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - // Send non-zero bufferMemoryBarrierCount - // Construct a valid BufferMemoryBarrier to avoid any parameter errors - // First we need a valid buffer to reference - VkBufferObj buffer; - VkMemoryPropertyFlags mem_reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; - buffer.init_as_src_and_dst(*m_device, 256, mem_reqs); - VkBufferMemoryBarrier bmb = {}; - bmb.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - bmb.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; - bmb.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - bmb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - bmb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - bmb.buffer = buffer.handle(); - bmb.offset = 0; - bmb.size = VK_WHOLE_SIZE; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-bufferMemoryBarrierCount-01178"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 1, &bmb, 0, - nullptr); - m_errorMonitor->VerifyFound(); - // Add image barrier w/ image handle that's not in framebuffer - VkImageObj lone_image(m_device); - lone_image.InitNoLayout(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - img_barrier.image = lone_image.handle(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-image-02635"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - // Have image barrier with mis-matched layouts - img_barrier.image = image.handle(); - img_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-oldLayout-01181"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - - img_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-oldLayout-02636"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - vkCmdEndRenderPass(m_commandBuffer->handle()); - - vkDestroyFramebuffer(m_device->device(), fb, nullptr); - vkDestroyRenderPass(m_device->device(), rp, nullptr); - vkDestroyRenderPass(m_device->device(), rp_noselfdep, nullptr); -} - -TEST_F(VkLayerTest, InvalidSecondaryCommandBufferBarrier) { - TEST_DESCRIPTION("Add an invalid image barrier in a secondary command buffer"); - ASSERT_NO_FATAL_FAILURE(Init()); - - // A renderpass with a single subpass that declared a self-dependency - VkAttachmentDescription attach[] = { - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - }; - VkAttachmentReference ref = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - VkSubpassDescription subpasses[] = { - {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &ref, nullptr, nullptr, 0, nullptr}, - }; - VkSubpassDependency dep = {0, - 0, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_ACCESS_SHADER_WRITE_BIT, - VK_ACCESS_SHADER_WRITE_BIT, - VK_DEPENDENCY_BY_REGION_BIT}; - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, attach, 1, subpasses, 1, &dep}; - VkRenderPass rp; - - VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - - VkImageObj image(m_device); - image.Init(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - VkImageView imageView = image.targetView(VK_FORMAT_R8G8B8A8_UNORM); - // Second image that img_barrier will incorrectly use - VkImageObj image2(m_device); - image2.Init(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - - VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 1, &imageView, 32, 32, 1}; - VkFramebuffer fb; - err = vkCreateFramebuffer(m_device->device(), &fbci, nullptr, &fb); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - - VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - nullptr, - rp, - fb, - {{ - 0, - 0, - }, - {32, 32}}, - 0, - nullptr}; - - vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); - - VkCommandPoolObj pool(m_device, m_device->graphics_queue_node_index_, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); - VkCommandBufferObj secondary(m_device, &pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); - - VkCommandBufferInheritanceInfo cbii = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, - nullptr, - rp, - 0, - VK_NULL_HANDLE, // Set to NULL FB handle intentionally to flesh out any errors - VK_FALSE, - 0, - 0}; - VkCommandBufferBeginInfo cbbi = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, - &cbii}; - vkBeginCommandBuffer(secondary.handle(), &cbbi); - VkImageMemoryBarrier img_barrier = {}; - img_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - img_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - img_barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - img_barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - img_barrier.image = image2.handle(); // Image mis-matches with FB image - img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - img_barrier.subresourceRange.baseArrayLayer = 0; - img_barrier.subresourceRange.baseMipLevel = 0; - img_barrier.subresourceRange.layerCount = 1; - img_barrier.subresourceRange.levelCount = 1; - vkCmdPipelineBarrier(secondary.handle(), VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier); - secondary.end(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-image-02635"); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary.handle()); - m_errorMonitor->VerifyFound(); - - vkDestroyFramebuffer(m_device->device(), fb, nullptr); - vkDestroyRenderPass(m_device->device(), rp, nullptr); -} - -TEST_F(VkLayerTest, ImageBarrierSubpassConflict) { - TEST_DESCRIPTION("Check case where subpass index references different image from image barrier"); - ASSERT_NO_FATAL_FAILURE(Init()); - - // Create RP/FB combo where subpass has incorrect index attachment, this is 2nd half of "VUID-vkCmdPipelineBarrier-image-02635" - VkAttachmentDescription attach[] = { - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - }; - // ref attachment points to wrong attachment index compared to img_barrier below - VkAttachmentReference ref = {1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - VkSubpassDescription subpasses[] = { - {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &ref, nullptr, nullptr, 0, nullptr}, - }; - VkSubpassDependency dep = {0, - 0, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_DEPENDENCY_BY_REGION_BIT}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 2, attach, 1, subpasses, 1, &dep}; - VkRenderPass rp; - - VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - - VkImageObj image(m_device); - image.InitNoLayout(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - VkImageView imageView = image.targetView(VK_FORMAT_R8G8B8A8_UNORM); - VkImageObj image2(m_device); - image2.InitNoLayout(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - VkImageView imageView2 = image2.targetView(VK_FORMAT_R8G8B8A8_UNORM); - // re-use imageView from start of test - VkImageView iv_array[2] = {imageView, imageView2}; - - VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 2, iv_array, 32, 32, 1}; - VkFramebuffer fb; - err = vkCreateFramebuffer(m_device->device(), &fbci, nullptr, &fb); - ASSERT_VK_SUCCESS(err); - - VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - nullptr, - rp, - fb, - {{ - 0, - 0, - }, - {32, 32}}, - 0, - nullptr}; - - VkImageMemoryBarrier img_barrier = {}; - img_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - img_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - img_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - img_barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - img_barrier.image = image.handle(); /* barrier references image from attachment index 0 */ - img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - img_barrier.subresourceRange.baseArrayLayer = 0; - img_barrier.subresourceRange.baseMipLevel = 0; - img_barrier.subresourceRange.layerCount = 1; - img_barrier.subresourceRange.levelCount = 1; - m_commandBuffer->begin(); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-image-02635"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - - vkDestroyFramebuffer(m_device->device(), fb, nullptr); - vkDestroyRenderPass(m_device->device(), rp, nullptr); -} - -TEST_F(VkLayerTest, TemporaryExternalSemaphore) { -#ifdef _WIN32 - const auto extension_name = VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME; - const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR; -#else - const auto extension_name = VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME; - const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; -#endif - // Check for external semaphore instance extensions - if (InstanceExtensionSupported(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME); - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s External semaphore extension not supported, skipping test\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - // Check for external semaphore device extensions - if (DeviceExtensionSupported(gpu(), nullptr, extension_name)) { - m_device_extension_names.push_back(extension_name); - m_device_extension_names.push_back(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME); - } else { - printf("%s External semaphore extension not supported, skipping test\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - // Check for external semaphore import and export capability - VkPhysicalDeviceExternalSemaphoreInfoKHR esi = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR, nullptr, - handle_type}; - VkExternalSemaphorePropertiesKHR esp = {VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR, nullptr}; - auto vkGetPhysicalDeviceExternalSemaphorePropertiesKHR = - (PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)vkGetInstanceProcAddr( - instance(), "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR"); - vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(gpu(), &esi, &esp); - - if (!(esp.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR) || - !(esp.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR)) { - printf("%s External semaphore does not support importing and exporting, skipping test\n", kSkipPrefix); - return; - } - - VkResult err; - - // Create a semaphore to export payload from - VkExportSemaphoreCreateInfoKHR esci = {VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR, nullptr, handle_type}; - VkSemaphoreCreateInfo sci = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &esci, 0}; - - VkSemaphore export_semaphore; - err = vkCreateSemaphore(m_device->device(), &sci, nullptr, &export_semaphore); - ASSERT_VK_SUCCESS(err); - - // Create a semaphore to import payload into - sci.pNext = nullptr; - VkSemaphore import_semaphore; - err = vkCreateSemaphore(m_device->device(), &sci, nullptr, &import_semaphore); - ASSERT_VK_SUCCESS(err); - -#ifdef _WIN32 - // Export semaphore payload to an opaque handle - HANDLE handle = nullptr; - VkSemaphoreGetWin32HandleInfoKHR ghi = {VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR, nullptr, export_semaphore, - handle_type}; - auto vkGetSemaphoreWin32HandleKHR = - (PFN_vkGetSemaphoreWin32HandleKHR)vkGetDeviceProcAddr(m_device->device(), "vkGetSemaphoreWin32HandleKHR"); - err = vkGetSemaphoreWin32HandleKHR(m_device->device(), &ghi, &handle); - ASSERT_VK_SUCCESS(err); - - // Import opaque handle exported above *temporarily* - VkImportSemaphoreWin32HandleInfoKHR ihi = {VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR, - nullptr, - import_semaphore, - VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR, - handle_type, - handle, - nullptr}; - auto vkImportSemaphoreWin32HandleKHR = - (PFN_vkImportSemaphoreWin32HandleKHR)vkGetDeviceProcAddr(m_device->device(), "vkImportSemaphoreWin32HandleKHR"); - err = vkImportSemaphoreWin32HandleKHR(m_device->device(), &ihi); - ASSERT_VK_SUCCESS(err); -#else - // Export semaphore payload to an opaque handle - int fd = 0; - VkSemaphoreGetFdInfoKHR ghi = {VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, nullptr, export_semaphore, handle_type}; - auto vkGetSemaphoreFdKHR = (PFN_vkGetSemaphoreFdKHR)vkGetDeviceProcAddr(m_device->device(), "vkGetSemaphoreFdKHR"); - err = vkGetSemaphoreFdKHR(m_device->device(), &ghi, &fd); - ASSERT_VK_SUCCESS(err); - - // Import opaque handle exported above *temporarily* - VkImportSemaphoreFdInfoKHR ihi = {VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, nullptr, import_semaphore, - VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR, handle_type, fd}; - auto vkImportSemaphoreFdKHR = (PFN_vkImportSemaphoreFdKHR)vkGetDeviceProcAddr(m_device->device(), "vkImportSemaphoreFdKHR"); - err = vkImportSemaphoreFdKHR(m_device->device(), &ihi); - ASSERT_VK_SUCCESS(err); -#endif - - // Wait on the imported semaphore twice in vkQueueSubmit, the second wait should be an error - VkPipelineStageFlags flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - VkSubmitInfo si[] = { - {VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, 0, nullptr, &flags, 0, nullptr, 1, &export_semaphore}, - {VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, 1, &import_semaphore, &flags, 0, nullptr, 0, nullptr}, - {VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, 0, nullptr, &flags, 0, nullptr, 1, &export_semaphore}, - {VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, 1, &import_semaphore, &flags, 0, nullptr, 0, nullptr}, - }; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "has no way to be signaled"); - vkQueueSubmit(m_device->m_queue, 4, si, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - - // Wait on the imported semaphore twice in vkQueueBindSparse, the second wait should be an error - VkBindSparseInfo bi[] = { - {VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 1, &export_semaphore}, - {VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, nullptr, 1, &import_semaphore, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr}, - {VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 1, &export_semaphore}, - {VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, nullptr, 1, &import_semaphore, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr}, - }; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "has no way to be signaled"); - vkQueueBindSparse(m_device->m_queue, 4, bi, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - - // Cleanup - err = vkQueueWaitIdle(m_device->m_queue); - ASSERT_VK_SUCCESS(err); - vkDestroySemaphore(m_device->device(), export_semaphore, nullptr); - vkDestroySemaphore(m_device->device(), import_semaphore, nullptr); -} - -TEST_F(VkLayerTest, TemporaryExternalFence) { -#ifdef _WIN32 - const auto extension_name = VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME; - const auto handle_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR; -#else - const auto extension_name = VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME; - const auto handle_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; -#endif - // Check for external fence instance extensions - if (InstanceExtensionSupported(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME); - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s External fence extension not supported, skipping test\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - // Check for external fence device extensions - if (DeviceExtensionSupported(gpu(), nullptr, extension_name)) { - m_device_extension_names.push_back(extension_name); - m_device_extension_names.push_back(VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME); - } else { - printf("%s External fence extension not supported, skipping test\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - // Check for external fence import and export capability - VkPhysicalDeviceExternalFenceInfoKHR efi = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR, nullptr, handle_type}; - VkExternalFencePropertiesKHR efp = {VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR, nullptr}; - auto vkGetPhysicalDeviceExternalFencePropertiesKHR = (PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)vkGetInstanceProcAddr( - instance(), "vkGetPhysicalDeviceExternalFencePropertiesKHR"); - vkGetPhysicalDeviceExternalFencePropertiesKHR(gpu(), &efi, &efp); - - if (!(efp.externalFenceFeatures & VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR) || - !(efp.externalFenceFeatures & VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR)) { - printf("%s External fence does not support importing and exporting, skipping test\n", kSkipPrefix); - return; - } - - VkResult err; - - // Create a fence to export payload from - VkFence export_fence; - { - VkExportFenceCreateInfoKHR efci = {VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR, nullptr, handle_type}; - VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, &efci, 0}; - err = vkCreateFence(m_device->device(), &fci, nullptr, &export_fence); - ASSERT_VK_SUCCESS(err); - } - - // Create a fence to import payload into - VkFence import_fence; - { - VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, 0}; - err = vkCreateFence(m_device->device(), &fci, nullptr, &import_fence); - ASSERT_VK_SUCCESS(err); - } - -#ifdef _WIN32 - // Export fence payload to an opaque handle - HANDLE handle = nullptr; - { - VkFenceGetWin32HandleInfoKHR ghi = {VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR, nullptr, export_fence, handle_type}; - auto vkGetFenceWin32HandleKHR = - (PFN_vkGetFenceWin32HandleKHR)vkGetDeviceProcAddr(m_device->device(), "vkGetFenceWin32HandleKHR"); - err = vkGetFenceWin32HandleKHR(m_device->device(), &ghi, &handle); - ASSERT_VK_SUCCESS(err); - } - - // Import opaque handle exported above - { - VkImportFenceWin32HandleInfoKHR ifi = {VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR, - nullptr, - import_fence, - VK_FENCE_IMPORT_TEMPORARY_BIT_KHR, - handle_type, - handle, - nullptr}; - auto vkImportFenceWin32HandleKHR = - (PFN_vkImportFenceWin32HandleKHR)vkGetDeviceProcAddr(m_device->device(), "vkImportFenceWin32HandleKHR"); - err = vkImportFenceWin32HandleKHR(m_device->device(), &ifi); - ASSERT_VK_SUCCESS(err); - } -#else - // Export fence payload to an opaque handle - int fd = 0; - { - VkFenceGetFdInfoKHR gfi = {VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR, nullptr, export_fence, handle_type}; - auto vkGetFenceFdKHR = (PFN_vkGetFenceFdKHR)vkGetDeviceProcAddr(m_device->device(), "vkGetFenceFdKHR"); - err = vkGetFenceFdKHR(m_device->device(), &gfi, &fd); - ASSERT_VK_SUCCESS(err); - } - - // Import opaque handle exported above - { - VkImportFenceFdInfoKHR ifi = {VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR, nullptr, import_fence, - VK_FENCE_IMPORT_TEMPORARY_BIT_KHR, handle_type, fd}; - auto vkImportFenceFdKHR = (PFN_vkImportFenceFdKHR)vkGetDeviceProcAddr(m_device->device(), "vkImportFenceFdKHR"); - err = vkImportFenceFdKHR(m_device->device(), &ifi); - ASSERT_VK_SUCCESS(err); - } -#endif - - // Undo the temporary import - vkResetFences(m_device->device(), 1, &import_fence); - - // Signal the previously imported fence twice, the second signal should produce a validation error - vkQueueSubmit(m_device->m_queue, 0, nullptr, import_fence); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "is already in use by another submission."); - vkQueueSubmit(m_device->m_queue, 0, nullptr, import_fence); - m_errorMonitor->VerifyFound(); - - // Cleanup - err = vkQueueWaitIdle(m_device->m_queue); - ASSERT_VK_SUCCESS(err); - vkDestroyFence(m_device->device(), export_fence, nullptr); - vkDestroyFence(m_device->device(), import_fence, nullptr); -} - -TEST_F(VkPositiveLayerTest, SecondaryCommandBufferBarrier) { - TEST_DESCRIPTION("Add a pipeline barrier in a secondary command buffer"); - ASSERT_NO_FATAL_FAILURE(Init()); - - m_errorMonitor->ExpectSuccess(); - - // A renderpass with a single subpass that declared a self-dependency - VkAttachmentDescription attach[] = { - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - }; - VkAttachmentReference ref = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - VkSubpassDescription subpasses[] = { - {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &ref, nullptr, nullptr, 0, nullptr}, - }; - VkSubpassDependency dep = {0, - 0, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_ACCESS_SHADER_WRITE_BIT, - VK_ACCESS_SHADER_WRITE_BIT, - VK_DEPENDENCY_BY_REGION_BIT}; - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, attach, 1, subpasses, 1, &dep}; - VkRenderPass rp; - - VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - - VkImageObj image(m_device); - image.Init(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - VkImageView imageView = image.targetView(VK_FORMAT_R8G8B8A8_UNORM); - - VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 1, &imageView, 32, 32, 1}; - VkFramebuffer fb; - err = vkCreateFramebuffer(m_device->device(), &fbci, nullptr, &fb); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - - VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - nullptr, - rp, - fb, - {{ - 0, - 0, - }, - {32, 32}}, - 0, - nullptr}; - - vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); - - VkCommandPoolObj pool(m_device, m_device->graphics_queue_node_index_, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); - VkCommandBufferObj secondary(m_device, &pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); - - VkCommandBufferInheritanceInfo cbii = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, - nullptr, - rp, - 0, - VK_NULL_HANDLE, // Set to NULL FB handle intentionally to flesh out any errors - VK_FALSE, - 0, - 0}; - VkCommandBufferBeginInfo cbbi = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, - &cbii}; - vkBeginCommandBuffer(secondary.handle(), &cbbi); - VkMemoryBarrier mem_barrier = {}; - mem_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; - mem_barrier.pNext = NULL; - mem_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - mem_barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - vkCmdPipelineBarrier(secondary.handle(), VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_DEPENDENCY_BY_REGION_BIT, 1, &mem_barrier, 0, nullptr, 0, nullptr); - VkImageMemoryBarrier img_barrier = {}; - img_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - img_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - img_barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - img_barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - img_barrier.image = image.handle(); - img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - img_barrier.subresourceRange.baseArrayLayer = 0; - img_barrier.subresourceRange.baseMipLevel = 0; - img_barrier.subresourceRange.layerCount = 1; - img_barrier.subresourceRange.levelCount = 1; - vkCmdPipelineBarrier(secondary.handle(), VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier); - secondary.end(); - - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary.handle()); - vkCmdEndRenderPass(m_commandBuffer->handle()); - m_commandBuffer->end(); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - vkQueueWaitIdle(m_device->m_queue); - - vkDestroyFramebuffer(m_device->device(), fb, nullptr); - vkDestroyRenderPass(m_device->device(), rp, nullptr); - m_errorMonitor->VerifyNotFound(); -} - -static void TestRenderPassCreate(ErrorMonitor *error_monitor, const VkDevice device, const VkRenderPassCreateInfo *create_info, - bool rp2Supported, const char *rp1_vuid, const char *rp2_vuid) { - VkRenderPass render_pass = VK_NULL_HANDLE; - VkResult err; - - if (rp1_vuid) { - error_monitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, rp1_vuid); - err = vkCreateRenderPass(device, create_info, nullptr, &render_pass); - if (err == VK_SUCCESS) vkDestroyRenderPass(device, render_pass, nullptr); - error_monitor->VerifyFound(); - } - - if (rp2Supported && rp2_vuid) { - PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR = - (PFN_vkCreateRenderPass2KHR)vkGetDeviceProcAddr(device, "vkCreateRenderPass2KHR"); - safe_VkRenderPassCreateInfo2KHR create_info2; - ConvertVkRenderPassCreateInfoToV2KHR(create_info, &create_info2); - - error_monitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, rp2_vuid); - err = vkCreateRenderPass2KHR(device, create_info2.ptr(), nullptr, &render_pass); - if (err == VK_SUCCESS) vkDestroyRenderPass(device, render_pass, nullptr); - error_monitor->VerifyFound(); - } -} - -TEST_F(VkLayerTest, RenderPassCreateAttachmentIndexOutOfRange) { - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - ASSERT_NO_FATAL_FAILURE(InitState()); - - // There are no attachments, but refer to attachment 0. - VkAttachmentReference ref = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - VkSubpassDescription subpasses[] = { - {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &ref, nullptr, nullptr, 0, nullptr}, - }; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 0, nullptr, 1, subpasses, 0, nullptr}; - - // "... must be less than the total number of attachments ..." - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkRenderPassCreateInfo-attachment-00834", - "VUID-VkRenderPassCreateInfo2KHR-attachment-03051"); -} - -TEST_F(VkLayerTest, RenderPassCreateAttachmentReadOnlyButCleared) { - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - bool maintenance2Supported = rp2Supported; - - // Check for VK_KHR_maintenance2 - if (!rp2Supported && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE2_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME); - maintenance2Supported = true; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - - if (m_device->props.apiVersion < VK_API_VERSION_1_1) { - maintenance2Supported = true; - } - - VkAttachmentDescription description = {0, - VK_FORMAT_D32_SFLOAT_S8_UINT, - VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_CLEAR, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_CLEAR, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_GENERAL}; - - VkAttachmentReference depth_stencil_ref = {0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL}; - - VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, &depth_stencil_ref, 0, - nullptr}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &description, 1, &subpass, 0, nullptr}; - - // VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL but depth cleared - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkRenderPassCreateInfo-pAttachments-00836", - "VUID-VkRenderPassCreateInfo2KHR-pAttachments-02522"); - - if (maintenance2Supported) { - // VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL but depth cleared - depth_stencil_ref.layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, - "VUID-VkRenderPassCreateInfo-pAttachments-01566", nullptr); - - // VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL but depth cleared - depth_stencil_ref.layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, - "VUID-VkRenderPassCreateInfo-pAttachments-01567", nullptr); - } -} - -TEST_F(VkLayerTest, RenderPassCreateAttachmentMismatchingLayoutsColor) { - TEST_DESCRIPTION("Attachment is used simultaneously as two color attachments with different layouts."); - - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkAttachmentDescription attach[] = { - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - }; - VkAttachmentReference refs[] = { - {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - {0, VK_IMAGE_LAYOUT_GENERAL}, - }; - VkSubpassDescription subpasses[] = { - {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 2, refs, nullptr, nullptr, 0, nullptr}, - }; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, attach, 1, subpasses, 0, nullptr}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, - "subpass 0 already uses attachment 0 with a different image layout", - "subpass 0 already uses attachment 0 with a different image layout"); -} - -TEST_F(VkLayerTest, RenderPassCreateAttachmentDescriptionInvalidFinalLayout) { - TEST_DESCRIPTION("VkAttachmentDescription's finalLayout must not be UNDEFINED or PREINITIALIZED"); - - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkAttachmentDescription attach_desc = {}; - attach_desc.format = VK_FORMAT_R8G8B8A8_UNORM; - attach_desc.samples = VK_SAMPLE_COUNT_1_BIT; - attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attach_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attach_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attach_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attach_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attach_desc.finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VkAttachmentReference attach_ref = {}; - attach_ref.attachment = 0; - attach_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &attach_ref; - VkRenderPassCreateInfo rpci = {}; - rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - rpci.attachmentCount = 1; - rpci.pAttachments = &attach_desc; - rpci.subpassCount = 1; - rpci.pSubpasses = &subpass; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-finalLayout-00843", - "VUID-VkAttachmentDescription2KHR-finalLayout-03061"); - - attach_desc.finalLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-finalLayout-00843", - "VUID-VkAttachmentDescription2KHR-finalLayout-03061"); -} - -TEST_F(VkLayerTest, RenderPassCreateAttachmentsMisc) { - TEST_DESCRIPTION( - "Ensure that CreateRenderPass produces the expected validation errors when a subpass's attachments violate the valid usage " - "conditions."); - - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - ASSERT_NO_FATAL_FAILURE(InitState()); - - std::vector<VkAttachmentDescription> attachments = { - // input attachments - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_4_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL}, - // color attachments - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_4_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_4_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - // depth attachment - {0, VK_FORMAT_D24_UNORM_S8_UINT, VK_SAMPLE_COUNT_4_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}, - // resolve attachment - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - // preserve attachments - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_4_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - }; - - std::vector<VkAttachmentReference> input = { - {0, VK_IMAGE_LAYOUT_GENERAL}, - }; - std::vector<VkAttachmentReference> color = { - {1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - {2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - }; - VkAttachmentReference depth = {3, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}; - std::vector<VkAttachmentReference> resolve = { - {4, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - {VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - }; - std::vector<uint32_t> preserve = {5}; - - VkSubpassDescription subpass = {0, - VK_PIPELINE_BIND_POINT_GRAPHICS, - (uint32_t)input.size(), - input.data(), - (uint32_t)color.size(), - color.data(), - resolve.data(), - &depth, - (uint32_t)preserve.size(), - preserve.data()}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - nullptr, - 0, - (uint32_t)attachments.size(), - attachments.data(), - 1, - &subpass, - 0, - nullptr}; - - // Test too many color attachments - { - std::vector<VkAttachmentReference> too_many_colors(m_device->props.limits.maxColorAttachments + 1, color[0]); - subpass.colorAttachmentCount = (uint32_t)too_many_colors.size(); - subpass.pColorAttachments = too_many_colors.data(); - subpass.pResolveAttachments = NULL; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, - "VUID-VkSubpassDescription-colorAttachmentCount-00845", - "VUID-VkSubpassDescription2KHR-colorAttachmentCount-03063"); - - subpass.colorAttachmentCount = (uint32_t)color.size(); - subpass.pColorAttachments = color.data(); - subpass.pResolveAttachments = resolve.data(); - } - - // Test sample count mismatch between color buffers - attachments[subpass.pColorAttachments[1].attachment].samples = VK_SAMPLE_COUNT_8_BIT; - depth.attachment = VK_ATTACHMENT_UNUSED; // Avoids triggering 01418 - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, - "VUID-VkSubpassDescription-pColorAttachments-01417", - "VUID-VkSubpassDescription2KHR-pColorAttachments-03069"); - - depth.attachment = 3; - attachments[subpass.pColorAttachments[1].attachment].samples = attachments[subpass.pColorAttachments[0].attachment].samples; - - // Test sample count mismatch between color buffers and depth buffer - attachments[subpass.pDepthStencilAttachment->attachment].samples = VK_SAMPLE_COUNT_8_BIT; - subpass.colorAttachmentCount = 1; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, - "VUID-VkSubpassDescription-pDepthStencilAttachment-01418", - "VUID-VkSubpassDescription2KHR-pDepthStencilAttachment-03071"); - - attachments[subpass.pDepthStencilAttachment->attachment].samples = attachments[subpass.pColorAttachments[0].attachment].samples; - subpass.colorAttachmentCount = (uint32_t)color.size(); - - // Test resolve attachment with UNUSED color attachment - color[0].attachment = VK_ATTACHMENT_UNUSED; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, - "VUID-VkSubpassDescription-pResolveAttachments-00847", - "VUID-VkSubpassDescription2KHR-pResolveAttachments-03065"); - - color[0].attachment = 1; - - // Test resolve from a single-sampled color attachment - attachments[subpass.pColorAttachments[0].attachment].samples = VK_SAMPLE_COUNT_1_BIT; - subpass.colorAttachmentCount = 1; // avoid mismatch (00337), and avoid double report - subpass.pDepthStencilAttachment = nullptr; // avoid mismatch (01418) - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, - "VUID-VkSubpassDescription-pResolveAttachments-00848", - "VUID-VkSubpassDescription2KHR-pResolveAttachments-03066"); - - attachments[subpass.pColorAttachments[0].attachment].samples = VK_SAMPLE_COUNT_4_BIT; - subpass.colorAttachmentCount = (uint32_t)color.size(); - subpass.pDepthStencilAttachment = &depth; - - // Test resolve to a multi-sampled resolve attachment - attachments[subpass.pResolveAttachments[0].attachment].samples = VK_SAMPLE_COUNT_4_BIT; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, - "VUID-VkSubpassDescription-pResolveAttachments-00849", - "VUID-VkSubpassDescription2KHR-pResolveAttachments-03067"); - - attachments[subpass.pResolveAttachments[0].attachment].samples = VK_SAMPLE_COUNT_1_BIT; - - // Test with color/resolve format mismatch - attachments[subpass.pColorAttachments[0].attachment].format = VK_FORMAT_R8G8B8A8_SRGB; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, - "VUID-VkSubpassDescription-pResolveAttachments-00850", - "VUID-VkSubpassDescription2KHR-pResolveAttachments-03068"); - - attachments[subpass.pColorAttachments[0].attachment].format = attachments[subpass.pResolveAttachments[0].attachment].format; - - // Test for UNUSED preserve attachments - preserve[0] = VK_ATTACHMENT_UNUSED; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDescription-attachment-00853", - "VUID-VkSubpassDescription2KHR-attachment-03073"); - - preserve[0] = 5; - // Test for preserve attachments used elsewhere in the subpass - color[0].attachment = preserve[0]; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, - "VUID-VkSubpassDescription-pPreserveAttachments-00854", - "VUID-VkSubpassDescription2KHR-pPreserveAttachments-03074"); - - color[0].attachment = 1; - input[0].attachment = 0; - input[0].layout = VK_IMAGE_LAYOUT_GENERAL; - - // Test for attachment used first as input with loadOp=CLEAR - { - std::vector<VkSubpassDescription> subpasses = {subpass, subpass, subpass}; - subpasses[0].inputAttachmentCount = 0; - subpasses[1].inputAttachmentCount = 0; - attachments[input[0].attachment].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - VkRenderPassCreateInfo rpci_multipass = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - nullptr, - 0, - (uint32_t)attachments.size(), - attachments.data(), - (uint32_t)subpasses.size(), - subpasses.data(), - 0, - nullptr}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci_multipass, rp2Supported, - "VUID-VkSubpassDescription-loadOp-00846", "VUID-VkSubpassDescription2KHR-loadOp-03064"); - - attachments[input[0].attachment].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - } -} - -TEST_F(VkLayerTest, RenderPassCreateAttachmentReferenceInvalidLayout) { - TEST_DESCRIPTION("Attachment reference uses PREINITIALIZED or UNDEFINED layouts"); - - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkAttachmentDescription attach[] = { - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - }; - VkAttachmentReference refs[] = { - {0, VK_IMAGE_LAYOUT_UNDEFINED}, - }; - VkSubpassDescription subpasses[] = { - {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, refs, nullptr, nullptr, 0, nullptr}, - }; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, attach, 1, subpasses, 0, nullptr}; - - // Use UNDEFINED layout - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentReference-layout-00857", - "VUID-VkAttachmentReference2KHR-layout-03077"); - - // Use PREINITIALIZED layout - refs[0].layout = VK_IMAGE_LAYOUT_PREINITIALIZED; - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentReference-layout-00857", - "VUID-VkAttachmentReference2KHR-layout-03077"); -} - -TEST_F(VkLayerTest, RenderPassCreateOverlappingCorrelationMasks) { - TEST_DESCRIPTION("Create a subpass with overlapping correlation masks"); - - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - - if (!rp2Supported) { - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MULTIVIEW_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME); - } else { - printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_MULTIVIEW_EXTENSION_NAME); - return; - } - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr}; - uint32_t viewMasks[] = {0x3u}; - uint32_t correlationMasks[] = {0x1u, 0x3u}; - VkRenderPassMultiviewCreateInfo rpmvci = { - VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, nullptr, 1, viewMasks, 0, nullptr, 2, correlationMasks}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpmvci, 0, 0, nullptr, 1, &subpass, 0, nullptr}; - - // Correlation masks must not overlap - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, - "VUID-VkRenderPassMultiviewCreateInfo-pCorrelationMasks-00841", - "VUID-VkRenderPassCreateInfo2KHR-pCorrelatedViewMasks-03056"); - - // Check for more specific "don't set any correlation masks when multiview is not enabled" - if (rp2Supported) { - PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR = - (PFN_vkCreateRenderPass2KHR)vkGetDeviceProcAddr(m_device->device(), "vkCreateRenderPass2KHR"); - - viewMasks[0] = 0; - correlationMasks[0] = 0; - correlationMasks[1] = 0; - safe_VkRenderPassCreateInfo2KHR safe_rpci2; - ConvertVkRenderPassCreateInfoToV2KHR(&rpci, &safe_rpci2); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkRenderPassCreateInfo2KHR-viewMask-03057"); - VkRenderPass rp; - VkResult err = vkCreateRenderPass2KHR(m_device->device(), safe_rpci2.ptr(), nullptr, &rp); - if (err == VK_SUCCESS) vkDestroyRenderPass(m_device->device(), rp, nullptr); - m_errorMonitor->VerifyFound(); - } -} - -TEST_F(VkLayerTest, RenderPassCreateInvalidViewMasks) { - TEST_DESCRIPTION("Create a subpass with the wrong number of view masks, or inconsistent setting of view masks"); - - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - - if (!rp2Supported) { - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MULTIVIEW_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME); - } else { - printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_MULTIVIEW_EXTENSION_NAME); - return; - } - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkSubpassDescription subpasses[] = { - {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr}, - {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr}, - }; - uint32_t viewMasks[] = {0x3u, 0u}; - VkRenderPassMultiviewCreateInfo rpmvci = { - VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, nullptr, 1, viewMasks, 0, nullptr, 0, nullptr}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpmvci, 0, 0, nullptr, 2, subpasses, 0, nullptr}; - - // Not enough view masks - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkRenderPassCreateInfo-pNext-01928", - "VUID-VkRenderPassCreateInfo2KHR-viewMask-03058"); -} - -TEST_F(VkLayerTest, RenderPassCreateInvalidInputAttachmentReferences) { - TEST_DESCRIPTION("Create a subpass with the meta data aspect mask set for an input attachment"); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE2_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME); - } else { - printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_MAINTENANCE2_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkAttachmentDescription attach = {0, - VK_FORMAT_R8G8B8A8_UNORM, - VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}; - VkAttachmentReference ref = {0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}; - - VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &ref, 0, nullptr, nullptr, nullptr, 0, nullptr}; - VkInputAttachmentAspectReference iaar = {0, 0, VK_IMAGE_ASPECT_METADATA_BIT}; - VkRenderPassInputAttachmentAspectCreateInfo rpiaaci = {VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO, - nullptr, 1, &iaar}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpiaaci, 0, 1, &attach, 1, &subpass, 0, nullptr}; - - // Invalid meta data aspect - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkRenderPassCreateInfo-pNext-01963"); // Cannot/should not avoid getting this one too - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkInputAttachmentAspectReference-aspectMask-01964", - nullptr); - - // Aspect not present - iaar.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkRenderPassCreateInfo-pNext-01963", nullptr); - - // Invalid subpass index - iaar.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - iaar.subpass = 1; - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkRenderPassCreateInfo-pNext-01926", nullptr); - iaar.subpass = 0; - - // Invalid input attachment index - iaar.inputAttachmentIndex = 1; - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkRenderPassCreateInfo-pNext-01927", nullptr); -} - -TEST_F(VkLayerTest, RenderPassCreateSubpassNonGraphicsPipeline) { - TEST_DESCRIPTION("Create a subpass with the compute pipeline bind point"); - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkSubpassDescription subpasses[] = { - {0, VK_PIPELINE_BIND_POINT_COMPUTE, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr}, - }; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 0, nullptr, 1, subpasses, 0, nullptr}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, - "VUID-VkSubpassDescription-pipelineBindPoint-00844", - "VUID-VkSubpassDescription2KHR-pipelineBindPoint-03062"); -} - -TEST_F(VkLayerTest, RenderPassCreateSubpassMissingAttributesBitMultiviewNVX) { - TEST_DESCRIPTION("Create a subpass with the VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX flag missing"); - - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if (DeviceExtensionSupported(gpu(), nullptr, VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME) && - DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MULTIVIEW_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME); - } else { - printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME); - return; - } - - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkSubpassDescription subpasses[] = { - {VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, - nullptr, 0, nullptr}, - }; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 0, nullptr, 1, subpasses, 0, nullptr}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDescription-flags-00856", - "VUID-VkSubpassDescription2KHR-flags-03076"); -} - -TEST_F(VkLayerTest, RenderPassCreate2SubpassInvalidInputAttachmentParameters) { - TEST_DESCRIPTION("Create a subpass with parameters in the input attachment ref which are invalid"); - - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - - if (!rp2Supported) { - printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - - PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR = - rp2Supported ? (PFN_vkCreateRenderPass2KHR)vkGetDeviceProcAddr(m_device->device(), "vkCreateRenderPass2KHR") : nullptr; - - VkResult err; - - VkAttachmentReference2KHR reference = {VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR, nullptr, VK_ATTACHMENT_UNUSED, - VK_IMAGE_LAYOUT_UNDEFINED, 0}; - VkSubpassDescription2KHR subpass = {VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR, - nullptr, - 0, - VK_PIPELINE_BIND_POINT_GRAPHICS, - 0, - 1, - &reference, - 0, - nullptr, - nullptr, - nullptr, - 0, - nullptr}; - - VkRenderPassCreateInfo2KHR rpci2 = { - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR, nullptr, 0, 0, nullptr, 1, &subpass, 0, nullptr, 0, nullptr}; - VkRenderPass rp; - - // Test for aspect mask of 0 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkSubpassDescription2KHR-aspectMask-03176"); - err = vkCreateRenderPass2KHR(m_device->device(), &rpci2, nullptr, &rp); - if (err == VK_SUCCESS) vkDestroyRenderPass(m_device->device(), rp, nullptr); - m_errorMonitor->VerifyFound(); - - // Test for invalid aspect mask bits - reference.aspectMask |= VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkSubpassDescription2KHR-aspectMask-03175"); - err = vkCreateRenderPass2KHR(m_device->device(), &rpci2, nullptr, &rp); - if (err == VK_SUCCESS) vkDestroyRenderPass(m_device->device(), rp, nullptr); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, RenderPassCreateInvalidSubpassDependencies) { - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - bool multiviewSupported = rp2Supported; - - if (!rp2Supported && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MULTIVIEW_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME); - multiviewSupported = true; - } - - // Add a device features struct enabling NO features - VkPhysicalDeviceFeatures features = {0}; - ASSERT_NO_FATAL_FAILURE(InitState(&features)); - - if (m_device->props.apiVersion >= VK_API_VERSION_1_1) { - multiviewSupported = true; - } - - // Create two dummy subpasses - VkSubpassDescription subpasses[] = { - {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr}, - {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr}, - }; - - VkSubpassDependency dependency; - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 0, nullptr, 2, subpasses, 1, &dependency}; - // dependency = { 0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0 }; - - // Source subpass is not EXTERNAL, so source stage mask must not include HOST - dependency = {0, 1, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDependency-srcSubpass-00858", - "VUID-VkSubpassDependency2KHR-srcSubpass-03078"); - - // Destination subpass is not EXTERNAL, so destination stage mask must not include HOST - dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0, 0}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDependency-dstSubpass-00859", - "VUID-VkSubpassDependency2KHR-dstSubpass-03079"); - - // Geometry shaders not enabled source - dependency = {0, 1, VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDependency-srcStageMask-00860", - "VUID-VkSubpassDependency2KHR-srcStageMask-03080"); - - // Geometry shaders not enabled destination - dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, 0, 0, 0}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDependency-dstStageMask-00861", - "VUID-VkSubpassDependency2KHR-dstStageMask-03081"); - - // Tessellation not enabled source - dependency = {0, 1, VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDependency-srcStageMask-00862", - "VUID-VkSubpassDependency2KHR-srcStageMask-03082"); - - // Tessellation not enabled destination - dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, 0, 0, 0}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDependency-dstStageMask-00863", - "VUID-VkSubpassDependency2KHR-dstStageMask-03083"); - - // Potential cyclical dependency - dependency = {1, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDependency-srcSubpass-00864", - "VUID-VkSubpassDependency2KHR-srcSubpass-03084"); - - // EXTERNAL to EXTERNAL dependency - dependency = { - VK_SUBPASS_EXTERNAL, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDependency-srcSubpass-00865", - "VUID-VkSubpassDependency2KHR-srcSubpass-03085"); - - // Source compute stage not part of subpass 0's GRAPHICS pipeline - dependency = {0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, 0}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkRenderPassCreateInfo-pDependencies-00837", - "VUID-VkRenderPassCreateInfo2KHR-pDependencies-03054"); - - // Destination compute stage not part of subpass 0's GRAPHICS pipeline - dependency = {VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, 0}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkRenderPassCreateInfo-pDependencies-00838", - "VUID-VkRenderPassCreateInfo2KHR-pDependencies-03055"); - - // Non graphics stage in self dependency - dependency = {0, 0, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, 0}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDependency-srcSubpass-01989", - "VUID-VkSubpassDependency2KHR-srcSubpass-02244"); - - // Logically later source stages in self dependency - dependency = {0, 0, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, 0}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDependency-srcSubpass-00867", - "VUID-VkSubpassDependency2KHR-srcSubpass-03087"); - - // Source access mask mismatch with source stage mask - dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_ACCESS_UNIFORM_READ_BIT, 0, 0}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDependency-srcAccessMask-00868", - "VUID-VkSubpassDependency2KHR-srcAccessMask-03088"); - - // Destination access mask mismatch with destination stage mask - dependency = { - 0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 0}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDependency-dstAccessMask-00869", - "VUID-VkSubpassDependency2KHR-dstAccessMask-03089"); - - if (multiviewSupported) { - // VIEW_LOCAL_BIT but multiview is not enabled - dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, 0, VK_DEPENDENCY_VIEW_LOCAL_BIT}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, nullptr, - "VUID-VkRenderPassCreateInfo2KHR-viewMask-03059"); - - // Enable multiview - uint32_t pViewMasks[2] = {0x3u, 0x3u}; - int32_t pViewOffsets[2] = {0, 0}; - VkRenderPassMultiviewCreateInfo rpmvci = { - VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, nullptr, 2, pViewMasks, 0, nullptr, 0, nullptr}; - rpci.pNext = &rpmvci; - - // Excessive view offsets - dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, 0, VK_DEPENDENCY_VIEW_LOCAL_BIT}; - rpmvci.pViewOffsets = pViewOffsets; - rpmvci.dependencyCount = 2; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkRenderPassCreateInfo-pNext-01929", nullptr); - - rpmvci.dependencyCount = 0; - - // View offset with subpass self dependency - dependency = {0, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, 0, VK_DEPENDENCY_VIEW_LOCAL_BIT}; - rpmvci.pViewOffsets = pViewOffsets; - pViewOffsets[0] = 1; - rpmvci.dependencyCount = 1; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkRenderPassCreateInfo-pNext-01930", nullptr); - - rpmvci.dependencyCount = 0; - - // View offset with no view local bit - if (rp2Supported) { - dependency = {0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0}; - rpmvci.pViewOffsets = pViewOffsets; - pViewOffsets[0] = 1; - rpmvci.dependencyCount = 1; - - safe_VkRenderPassCreateInfo2KHR safe_rpci2; - ConvertVkRenderPassCreateInfoToV2KHR(&rpci, &safe_rpci2); - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, nullptr, - "VUID-VkSubpassDependency2KHR-dependencyFlags-03092"); - - rpmvci.dependencyCount = 0; - } - - // EXTERNAL subpass with VIEW_LOCAL_BIT - source subpass - dependency = {VK_SUBPASS_EXTERNAL, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, - VK_DEPENDENCY_VIEW_LOCAL_BIT}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, - "VUID-VkSubpassDependency-dependencyFlags-02520", - "VUID-VkSubpassDependency2KHR-dependencyFlags-03090"); - - // EXTERNAL subpass with VIEW_LOCAL_BIT - destination subpass - dependency = {0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, - 0, VK_DEPENDENCY_VIEW_LOCAL_BIT}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, - "VUID-VkSubpassDependency-dependencyFlags-02521", - "VUID-VkSubpassDependency2KHR-dependencyFlags-03091"); - - // Multiple views but no view local bit in self-dependency - dependency = {0, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0}; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDependency-srcSubpass-00872", - "VUID-VkRenderPassCreateInfo2KHR-pDependencies-03060"); - } -} - -TEST_F(VkLayerTest, RenderPassCreateInvalidMixedAttachmentSamplesAMD) { - TEST_DESCRIPTION("Verify error messages for supported and unsupported sample counts in render pass attachments."); - - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if (DeviceExtensionSupported(gpu(), nullptr, VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME); - } else { - printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME); - return; - } - - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - - ASSERT_NO_FATAL_FAILURE(InitState()); - - std::vector<VkAttachmentDescription> attachments; - - { - VkAttachmentDescription att = {}; - att.format = VK_FORMAT_R8G8B8A8_UNORM; - att.samples = VK_SAMPLE_COUNT_1_BIT; - att.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - att.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - att.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - att.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - attachments.push_back(att); - - att.format = VK_FORMAT_D16_UNORM; - att.samples = VK_SAMPLE_COUNT_4_BIT; - att.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - att.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - att.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - att.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - attachments.push_back(att); - } - - VkAttachmentReference color_ref = {}; - color_ref.attachment = 0; - color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkAttachmentReference depth_ref = {}; - depth_ref.attachment = 1; - depth_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &color_ref; - subpass.pDepthStencilAttachment = &depth_ref; - - VkRenderPassCreateInfo rpci = {}; - rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - rpci.attachmentCount = attachments.size(); - rpci.pAttachments = attachments.data(); - rpci.subpassCount = 1; - rpci.pSubpasses = &subpass; - - m_errorMonitor->ExpectSuccess(); - - VkRenderPass rp; - VkResult err; - - err = vkCreateRenderPass(device(), &rpci, NULL, &rp); - m_errorMonitor->VerifyNotFound(); - if (err == VK_SUCCESS) vkDestroyRenderPass(m_device->device(), rp, nullptr); - - // Expect an error message for invalid sample counts - attachments[0].samples = VK_SAMPLE_COUNT_4_BIT; - attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; - - TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, - "VUID-VkSubpassDescription-pColorAttachments-01506", - "VUID-VkSubpassDescription2KHR-pColorAttachments-03070"); -} - -static void TestRenderPassBegin(ErrorMonitor *error_monitor, const VkDevice device, const VkCommandBuffer command_buffer, - const VkRenderPassBeginInfo *begin_info, bool rp2Supported, const char *rp1_vuid, - const char *rp2_vuid) { - VkCommandBufferBeginInfo cmd_begin_info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr}; - - if (rp1_vuid) { - vkBeginCommandBuffer(command_buffer, &cmd_begin_info); - error_monitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, rp1_vuid); - vkCmdBeginRenderPass(command_buffer, begin_info, VK_SUBPASS_CONTENTS_INLINE); - error_monitor->VerifyFound(); - vkResetCommandBuffer(command_buffer, 0); - } - if (rp2Supported && rp2_vuid) { - PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR = - (PFN_vkCmdBeginRenderPass2KHR)vkGetDeviceProcAddr(device, "vkCmdBeginRenderPass2KHR"); - VkSubpassBeginInfoKHR subpass_begin_info = {VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR, nullptr, VK_SUBPASS_CONTENTS_INLINE}; - vkBeginCommandBuffer(command_buffer, &cmd_begin_info); - error_monitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, rp2_vuid); - vkCmdBeginRenderPass2KHR(command_buffer, begin_info, &subpass_begin_info); - error_monitor->VerifyFound(); - vkResetCommandBuffer(command_buffer, 0); - } -} - -TEST_F(VkLayerTest, RenderPassBeginInvalidRenderArea) { - TEST_DESCRIPTION("Generate INVALID_RENDER_AREA error by beginning renderpass with extent outside of framebuffer"); - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Framebuffer for render target is 256x256, exceed that for INVALID_RENDER_AREA - m_renderPassBeginInfo.renderArea.extent.width = 257; - m_renderPassBeginInfo.renderArea.extent.height = 257; - - TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &m_renderPassBeginInfo, rp2Supported, - "Cannot execute a render pass with renderArea not within the bound of the framebuffer.", - "Cannot execute a render pass with renderArea not within the bound of the framebuffer."); -} - -TEST_F(VkLayerTest, RenderPassBeginWithinRenderPass) { - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR = nullptr; - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - ASSERT_NO_FATAL_FAILURE(InitState()); - - if (rp2Supported) { - vkCmdBeginRenderPass2KHR = - (PFN_vkCmdBeginRenderPass2KHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdBeginRenderPass2KHR"); - } - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Bind a BeginRenderPass within an active RenderPass - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - // Just use a dummy Renderpass - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBeginRenderPass-renderpass"); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - m_errorMonitor->VerifyFound(); - - if (rp2Supported) { - VkSubpassBeginInfoKHR subpassBeginInfo = {VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR, nullptr, VK_SUBPASS_CONTENTS_INLINE}; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBeginRenderPass2KHR-renderpass"); - vkCmdBeginRenderPass2KHR(m_commandBuffer->handle(), &m_renderPassBeginInfo, &subpassBeginInfo); - m_errorMonitor->VerifyFound(); - } -} - -TEST_F(VkLayerTest, RenderPassBeginIncompatibleFramebufferRenderPass) { - TEST_DESCRIPTION("Test that renderpass begin is compatible with the framebuffer renderpass "); - - ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - - // Create a depth stencil image view - VkImageObj image(m_device); - - image.Init(128, 128, 1, VK_FORMAT_D16_UNORM, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(image.initialized()); - - VkImageView dsv; - VkImageViewCreateInfo dsvci = {}; - dsvci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - dsvci.pNext = nullptr; - dsvci.image = image.handle(); - dsvci.viewType = VK_IMAGE_VIEW_TYPE_2D; - dsvci.format = VK_FORMAT_D16_UNORM; - dsvci.subresourceRange.layerCount = 1; - dsvci.subresourceRange.baseMipLevel = 0; - dsvci.subresourceRange.levelCount = 1; - dsvci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - vkCreateImageView(m_device->device(), &dsvci, NULL, &dsv); - - // Create a renderPass with a single attachment that uses loadOp CLEAR - VkAttachmentDescription description = {0, - VK_FORMAT_D16_UNORM, - VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_LOAD, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_CLEAR, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_GENERAL}; - - VkAttachmentReference depth_stencil_ref = {0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}; - - VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, &depth_stencil_ref, 0, - nullptr}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &description, 1, &subpass, 0, nullptr}; - VkRenderPass rp1, rp2; - - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp1); - subpass.pDepthStencilAttachment = nullptr; - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp2); - - // Create a framebuffer - - VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp1, 1, &dsv, 128, 128, 1}; - VkFramebuffer fb; - - vkCreateFramebuffer(m_device->handle(), &fbci, nullptr, &fb); - - VkRenderPassBeginInfo rp_begin = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, rp2, fb, {{0, 0}, {128, 128}}, 0, nullptr}; - - TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, false, - "VUID-VkRenderPassBeginInfo-renderPass-00904", nullptr); - - vkDestroyRenderPass(m_device->device(), rp1, nullptr); - vkDestroyRenderPass(m_device->device(), rp2, nullptr); - vkDestroyFramebuffer(m_device->device(), fb, nullptr); - vkDestroyImageView(m_device->device(), dsv, nullptr); -} - -TEST_F(VkLayerTest, RenderPassBeginLayoutsFramebufferImageUsageMismatches) { - TEST_DESCRIPTION( - "Test that renderpass initial/final layouts match up with the usage bits set for each attachment of the framebuffer"); - - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - bool maintenance2Supported = rp2Supported; - - // Check for VK_KHR_maintenance2 - if (!rp2Supported && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE2_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME); - maintenance2Supported = true; - } - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - - if (m_device->props.apiVersion >= VK_API_VERSION_1_1) { - maintenance2Supported = true; - } - - // Create an input attachment view - VkImageObj iai(m_device); - - iai.InitNoLayout(128, 128, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(iai.initialized()); - - VkImageView iav; - VkImageViewCreateInfo iavci = {}; - iavci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - iavci.pNext = nullptr; - iavci.image = iai.handle(); - iavci.viewType = VK_IMAGE_VIEW_TYPE_2D; - iavci.format = VK_FORMAT_R8G8B8A8_UNORM; - iavci.subresourceRange.layerCount = 1; - iavci.subresourceRange.baseMipLevel = 0; - iavci.subresourceRange.levelCount = 1; - iavci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - vkCreateImageView(m_device->device(), &iavci, NULL, &iav); - - // Create a color attachment view - VkImageObj cai(m_device); - - cai.InitNoLayout(128, 128, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(cai.initialized()); - - VkImageView cav; - VkImageViewCreateInfo cavci = {}; - cavci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - cavci.pNext = nullptr; - cavci.image = cai.handle(); - cavci.viewType = VK_IMAGE_VIEW_TYPE_2D; - cavci.format = VK_FORMAT_R8G8B8A8_UNORM; - cavci.subresourceRange.layerCount = 1; - cavci.subresourceRange.baseMipLevel = 0; - cavci.subresourceRange.levelCount = 1; - cavci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - vkCreateImageView(m_device->device(), &cavci, NULL, &cav); - - // Create a renderPass with those attachments - VkAttachmentDescription descriptions[] = { - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL}, - {1, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL}}; - - VkAttachmentReference input_ref = {0, VK_IMAGE_LAYOUT_GENERAL}; - VkAttachmentReference color_ref = {1, VK_IMAGE_LAYOUT_GENERAL}; - - VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &input_ref, 1, &color_ref, nullptr, nullptr, 0, nullptr}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 2, descriptions, 1, &subpass, 0, nullptr}; - - VkRenderPass rp; - - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - - // Create a framebuffer - - VkImageView views[] = {iav, cav}; - - VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 2, views, 128, 128, 1}; - VkFramebuffer fb; - - vkCreateFramebuffer(m_device->handle(), &fbci, nullptr, &fb); - - VkRenderPassBeginInfo rp_begin = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, rp, fb, {{0, 0}, {128, 128}}, 0, nullptr}; - - VkRenderPass rp_invalid; - - // Initial layout is VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but attachment doesn't support IMAGE_USAGE_COLOR_ATTACHMENT_BIT - descriptions[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_invalid); - rp_begin.renderPass = rp_invalid; - TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported, - "VUID-vkCmdBeginRenderPass-initialLayout-00895", "VUID-vkCmdBeginRenderPass2KHR-initialLayout-03094"); - - vkDestroyRenderPass(m_device->handle(), rp_invalid, nullptr); - - // Initial layout is VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL but attachment doesn't support VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT - // / VK_IMAGE_USAGE_SAMPLED_BIT - descriptions[0].initialLayout = VK_IMAGE_LAYOUT_GENERAL; - descriptions[1].initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_invalid); - rp_begin.renderPass = rp_invalid; - - TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported, - "VUID-vkCmdBeginRenderPass-initialLayout-00897", "VUID-vkCmdBeginRenderPass2KHR-initialLayout-03097"); - - vkDestroyRenderPass(m_device->handle(), rp_invalid, nullptr); - descriptions[1].initialLayout = VK_IMAGE_LAYOUT_GENERAL; - - // Initial layout is VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL but attachment doesn't support VK_IMAGE_USAGE_TRANSFER_SRC_BIT - descriptions[0].initialLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_invalid); - rp_begin.renderPass = rp_invalid; - - TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported, - "VUID-vkCmdBeginRenderPass-initialLayout-00898", "VUID-vkCmdBeginRenderPass2KHR-initialLayout-03098"); - - vkDestroyRenderPass(m_device->handle(), rp_invalid, nullptr); - - // Initial layout is VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL but attachment doesn't support VK_IMAGE_USAGE_TRANSFER_DST_BIT - descriptions[0].initialLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_invalid); - rp_begin.renderPass = rp_invalid; - - TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported, - "VUID-vkCmdBeginRenderPass-initialLayout-00899", "VUID-vkCmdBeginRenderPass2KHR-initialLayout-03099"); - - vkDestroyRenderPass(m_device->handle(), rp_invalid, nullptr); - - // Initial layout is VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL but attachment doesn't support - // VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT - descriptions[0].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_invalid); - rp_begin.renderPass = rp_invalid; - const char *initial_layout_vuid_rp1 = - maintenance2Supported ? "VUID-vkCmdBeginRenderPass-initialLayout-01758" : "VUID-vkCmdBeginRenderPass-initialLayout-00896"; - - TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported, - initial_layout_vuid_rp1, "VUID-vkCmdBeginRenderPass2KHR-initialLayout-03096"); - - vkDestroyRenderPass(m_device->handle(), rp_invalid, nullptr); - - // Initial layout is VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL but attachment doesn't support - // VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT - descriptions[0].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_invalid); - rp_begin.renderPass = rp_invalid; - - TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported, - initial_layout_vuid_rp1, "VUID-vkCmdBeginRenderPass2KHR-initialLayout-03096"); - - vkDestroyRenderPass(m_device->handle(), rp_invalid, nullptr); - - if (maintenance2Supported || rp2Supported) { - // Initial layout is VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL but attachment doesn't support - // VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT - descriptions[0].initialLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL; - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_invalid); - rp_begin.renderPass = rp_invalid; - - TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported, - "VUID-vkCmdBeginRenderPass-initialLayout-01758", "VUID-vkCmdBeginRenderPass2KHR-initialLayout-03096"); - - vkDestroyRenderPass(m_device->handle(), rp_invalid, nullptr); - - // Initial layout is VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL but attachment doesn't support - // VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT - descriptions[0].initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL; - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_invalid); - rp_begin.renderPass = rp_invalid; - - TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported, - "VUID-vkCmdBeginRenderPass-initialLayout-01758", "VUID-vkCmdBeginRenderPass2KHR-initialLayout-03096"); - - vkDestroyRenderPass(m_device->handle(), rp_invalid, nullptr); - } - - vkDestroyRenderPass(m_device->device(), rp, nullptr); - vkDestroyFramebuffer(m_device->device(), fb, nullptr); - vkDestroyImageView(m_device->device(), iav, nullptr); - vkDestroyImageView(m_device->device(), cav, nullptr); -} - -TEST_F(VkLayerTest, RenderPassBeginClearOpMismatch) { - TEST_DESCRIPTION( - "Begin a renderPass where clearValueCount is less than the number of renderPass attachments that use " - "loadOp VK_ATTACHMENT_LOAD_OP_CLEAR."); - - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Create a renderPass with a single attachment that uses loadOp CLEAR - VkAttachmentReference attach = {}; - attach.layout = VK_IMAGE_LAYOUT_GENERAL; - VkSubpassDescription subpass = {}; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &attach; - VkRenderPassCreateInfo rpci = {}; - rpci.subpassCount = 1; - rpci.pSubpasses = &subpass; - rpci.attachmentCount = 1; - VkAttachmentDescription attach_desc = {}; - attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM; - // Set loadOp to CLEAR - attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attach_desc.samples = VK_SAMPLE_COUNT_1_BIT; - attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL; - rpci.pAttachments = &attach_desc; - rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - VkRenderPass rp; - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - - VkRenderPassBeginInfo rp_begin = {}; - rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - rp_begin.pNext = NULL; - rp_begin.renderPass = renderPass(); - rp_begin.framebuffer = framebuffer(); - rp_begin.clearValueCount = 0; // Should be 1 - - TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported, - "VUID-VkRenderPassBeginInfo-clearValueCount-00902", "VUID-VkRenderPassBeginInfo-clearValueCount-00902"); - - vkDestroyRenderPass(m_device->device(), rp, NULL); -} - -TEST_F(VkLayerTest, RenderPassBeginSampleLocationsInvalidIndicesEXT) { - TEST_DESCRIPTION("Test that attachment indices and subpass indices specifed by sample locations structures are valid"); - - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME); - } else { - printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - - // Create a depth stencil image view - VkImageObj image(m_device); - - image.Init(128, 128, 1, VK_FORMAT_D16_UNORM, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(image.initialized()); - - VkImageView dsv; - VkImageViewCreateInfo dsvci = {}; - dsvci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - dsvci.pNext = nullptr; - dsvci.image = image.handle(); - dsvci.viewType = VK_IMAGE_VIEW_TYPE_2D; - dsvci.format = VK_FORMAT_D16_UNORM; - dsvci.subresourceRange.layerCount = 1; - dsvci.subresourceRange.baseMipLevel = 0; - dsvci.subresourceRange.levelCount = 1; - dsvci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - vkCreateImageView(m_device->device(), &dsvci, NULL, &dsv); - - // Create a renderPass with a single attachment that uses loadOp CLEAR - VkAttachmentDescription description = {0, - VK_FORMAT_D16_UNORM, - VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_LOAD, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_CLEAR, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_GENERAL}; - - VkAttachmentReference depth_stencil_ref = {0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}; - - VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, &depth_stencil_ref, 0, - nullptr}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &description, 1, &subpass, 0, nullptr}; - VkRenderPass rp; - - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - - // Create a framebuffer - - VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 1, &dsv, 128, 128, 1}; - VkFramebuffer fb; - - vkCreateFramebuffer(m_device->handle(), &fbci, nullptr, &fb); - - VkSampleLocationEXT sample_location = {0.5, 0.5}; - - VkSampleLocationsInfoEXT sample_locations_info = { - VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT, nullptr, VK_SAMPLE_COUNT_1_BIT, {1, 1}, 1, &sample_location}; - - VkAttachmentSampleLocationsEXT attachment_sample_locations = {0, sample_locations_info}; - VkSubpassSampleLocationsEXT subpass_sample_locations = {0, sample_locations_info}; - - VkRenderPassSampleLocationsBeginInfoEXT rp_sl_begin = {VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT, - nullptr, - 1, - &attachment_sample_locations, - 1, - &subpass_sample_locations}; - - VkRenderPassBeginInfo rp_begin = { - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, &rp_sl_begin, rp, fb, {{0, 0}, {128, 128}}, 0, nullptr}; - - attachment_sample_locations.attachmentIndex = 1; - TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, false, - "VUID-VkAttachmentSampleLocationsEXT-attachmentIndex-01531", nullptr); - attachment_sample_locations.attachmentIndex = 0; - - subpass_sample_locations.subpassIndex = 1; - TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, false, - "VUID-VkSubpassSampleLocationsEXT-subpassIndex-01532", nullptr); - subpass_sample_locations.subpassIndex = 0; - - vkDestroyRenderPass(m_device->device(), rp, nullptr); - vkDestroyFramebuffer(m_device->device(), fb, nullptr); - vkDestroyImageView(m_device->device(), dsv, nullptr); -} - -TEST_F(VkLayerTest, RenderPassNextSubpassExcessive) { - TEST_DESCRIPTION("Test that an error is produced when CmdNextSubpass is called too many times in a renderpass instance"); - - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - PFN_vkCmdNextSubpass2KHR vkCmdNextSubpass2KHR = nullptr; - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - ASSERT_NO_FATAL_FAILURE(InitState()); - - if (rp2Supported) { - vkCmdNextSubpass2KHR = (PFN_vkCmdNextSubpass2KHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdNextSubpass2KHR"); - } - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdNextSubpass-None-00909"); - vkCmdNextSubpass(m_commandBuffer->handle(), VK_SUBPASS_CONTENTS_INLINE); - m_errorMonitor->VerifyFound(); - - if (rp2Supported) { - VkSubpassBeginInfoKHR subpassBeginInfo = {VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR, nullptr, VK_SUBPASS_CONTENTS_INLINE}; - VkSubpassEndInfoKHR subpassEndInfo = {VK_STRUCTURE_TYPE_SUBPASS_END_INFO_KHR, nullptr}; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdNextSubpass2KHR-None-03102"); - - vkCmdNextSubpass2KHR(m_commandBuffer->handle(), &subpassBeginInfo, &subpassEndInfo); - m_errorMonitor->VerifyFound(); - } - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, RenderPassEndBeforeFinalSubpass) { - TEST_DESCRIPTION("Test that an error is produced when CmdEndRenderPass is called before the final subpass has been reached"); - - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - PFN_vkCmdEndRenderPass2KHR vkCmdEndRenderPass2KHR = nullptr; - bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names); - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - - if (rp2Supported) { - vkCmdEndRenderPass2KHR = (PFN_vkCmdEndRenderPass2KHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdEndRenderPass2KHR"); - } - - VkSubpassDescription sd[2] = {{0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr}, - {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr}}; - - VkRenderPassCreateInfo rcpi = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 0, nullptr, 2, sd, 0, nullptr}; - - VkRenderPass rp; - VkResult err = vkCreateRenderPass(m_device->device(), &rcpi, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - - VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 0, nullptr, 16, 16, 1}; - - VkFramebuffer fb; - err = vkCreateFramebuffer(m_device->device(), &fbci, nullptr, &fb); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - - VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, rp, fb, {{0, 0}, {16, 16}}, 0, nullptr}; - - vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdEndRenderPass-None-00910"); - vkCmdEndRenderPass(m_commandBuffer->handle()); - m_errorMonitor->VerifyFound(); - - if (rp2Supported) { - VkSubpassEndInfoKHR subpassEndInfo = {VK_STRUCTURE_TYPE_SUBPASS_END_INFO_KHR, nullptr}; - - m_commandBuffer->reset(); - m_commandBuffer->begin(); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdEndRenderPass2KHR-None-03103"); - vkCmdEndRenderPass2KHR(m_commandBuffer->handle(), &subpassEndInfo); - m_errorMonitor->VerifyFound(); - } - - // Clean up. - vkDestroyFramebuffer(m_device->device(), fb, nullptr); - vkDestroyRenderPass(m_device->device(), rp, nullptr); -} - -TEST_F(VkLayerTest, RenderPassDestroyWhileInUse) { - TEST_DESCRIPTION("Delete in-use renderPass."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Create simple renderpass - VkAttachmentReference attach = {}; - attach.layout = VK_IMAGE_LAYOUT_GENERAL; - VkSubpassDescription subpass = {}; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &attach; - VkRenderPassCreateInfo rpci = {}; - rpci.subpassCount = 1; - rpci.pSubpasses = &subpass; - rpci.attachmentCount = 1; - VkAttachmentDescription attach_desc = {}; - attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM; - attach_desc.samples = VK_SAMPLE_COUNT_1_BIT; - attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL; - rpci.pAttachments = &attach_desc; - rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - VkRenderPass rp; - VkResult err = vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->ExpectSuccess(); - - m_commandBuffer->begin(); - VkRenderPassBeginInfo rpbi = {}; - rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - rpbi.framebuffer = m_framebuffer; - rpbi.renderPass = rp; - m_commandBuffer->BeginRenderPass(rpbi); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyNotFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkDestroyRenderPass-renderPass-00873"); - vkDestroyRenderPass(m_device->device(), rp, nullptr); - m_errorMonitor->VerifyFound(); - - // Wait for queue to complete so we can safely destroy rp - 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("Was it created? Has it already been destroyed?"); - vkDestroyRenderPass(m_device->device(), rp, nullptr); -} - -TEST_F(VkPositiveLayerTest, RenderPassCreateAttachmentUsedTwiceOK) { - TEST_DESCRIPTION("Attachment is used simultaneously as color and input, with the same layout. This is OK."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkAttachmentDescription attach[] = { - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL}, - }; - VkAttachmentReference ref = {0, VK_IMAGE_LAYOUT_GENERAL}; - VkSubpassDescription subpasses[] = { - {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &ref, 1, &ref, nullptr, nullptr, 0, nullptr}, - }; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, attach, 1, subpasses, 0, nullptr}; - VkRenderPass rp; - - m_errorMonitor->ExpectSuccess(); - vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); - m_errorMonitor->VerifyNotFound(); - vkDestroyRenderPass(m_device->device(), rp, nullptr); -} - -TEST_F(VkPositiveLayerTest, RenderPassCreateInitialLayoutUndefined) { - TEST_DESCRIPTION( - "Ensure that CmdBeginRenderPass with an attachment's initialLayout of VK_IMAGE_LAYOUT_UNDEFINED works when the command " - "buffer has prior knowledge of that attachment's layout."); - - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // A renderpass with one color attachment. - VkAttachmentDescription attachment = {0, - VK_FORMAT_R8G8B8A8_UNORM, - VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_STORE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - - VkAttachmentReference att_ref = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - - VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &att_ref, nullptr, nullptr, 0, nullptr}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &attachment, 1, &subpass, 0, nullptr}; - - VkRenderPass rp; - VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - - // A compatible framebuffer. - VkImageObj image(m_device); - image.Init(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - VkImageViewCreateInfo ivci = { - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - nullptr, - 0, - image.handle(), - VK_IMAGE_VIEW_TYPE_2D, - VK_FORMAT_R8G8B8A8_UNORM, - {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, - VK_COMPONENT_SWIZZLE_IDENTITY}, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}, - }; - VkImageView view; - err = vkCreateImageView(m_device->device(), &ivci, nullptr, &view); - ASSERT_VK_SUCCESS(err); - - VkFramebufferCreateInfo fci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 1, &view, 32, 32, 1}; - VkFramebuffer fb; - err = vkCreateFramebuffer(m_device->device(), &fci, nullptr, &fb); - ASSERT_VK_SUCCESS(err); - - // Record a single command buffer which uses this renderpass twice. The - // bug is triggered at the beginning of the second renderpass, when the - // command buffer already has a layout recorded for the attachment. - VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, rp, fb, {{0, 0}, {32, 32}}, 0, nullptr}; - m_commandBuffer->begin(); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE); - vkCmdEndRenderPass(m_commandBuffer->handle()); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE); - - m_errorMonitor->VerifyNotFound(); - - vkCmdEndRenderPass(m_commandBuffer->handle()); - m_commandBuffer->end(); - - vkDestroyFramebuffer(m_device->device(), fb, nullptr); - vkDestroyRenderPass(m_device->device(), rp, nullptr); - vkDestroyImageView(m_device->device(), view, nullptr); -} - -TEST_F(VkPositiveLayerTest, RenderPassCreateAttachmentLayoutWithLoadOpThenReadOnly) { - TEST_DESCRIPTION( - "Positive test where we create a renderpass with an attachment that uses LOAD_OP_CLEAR, the first subpass has a valid " - "layout, and a second subpass then uses a valid *READ_ONLY* layout."); - m_errorMonitor->ExpectSuccess(); - ASSERT_NO_FATAL_FAILURE(Init()); - auto depth_format = FindSupportedDepthStencilFormat(gpu()); - if (!depth_format) { - printf("%s No Depth + Stencil format found. Skipped.\n", kSkipPrefix); - return; - } - - VkAttachmentReference attach[2] = {}; - attach[0].attachment = 0; - attach[0].layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - attach[1].attachment = 0; - attach[1].layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - VkSubpassDescription subpasses[2] = {}; - // First subpass clears DS attach on load - subpasses[0].pDepthStencilAttachment = &attach[0]; - // 2nd subpass reads in DS as input attachment - subpasses[1].inputAttachmentCount = 1; - subpasses[1].pInputAttachments = &attach[1]; - VkAttachmentDescription attach_desc = {}; - attach_desc.format = depth_format; - attach_desc.samples = VK_SAMPLE_COUNT_1_BIT; - attach_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attach_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attach_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - VkRenderPassCreateInfo rpci = {}; - rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - rpci.attachmentCount = 1; - rpci.pAttachments = &attach_desc; - rpci.subpassCount = 2; - rpci.pSubpasses = subpasses; - - // Now create RenderPass and verify no errors - VkRenderPass rp; - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - m_errorMonitor->VerifyNotFound(); - - vkDestroyRenderPass(m_device->device(), rp, NULL); -} - -TEST_F(VkPositiveLayerTest, RenderPassBeginSubpassZeroTransitionsApplied) { - TEST_DESCRIPTION("Ensure that CmdBeginRenderPass applies the layout transitions for the first subpass"); - - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // A renderpass with one color attachment. - VkAttachmentDescription attachment = {0, - VK_FORMAT_R8G8B8A8_UNORM, - VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_STORE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - - VkAttachmentReference att_ref = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - - VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &att_ref, nullptr, nullptr, 0, nullptr}; - - VkSubpassDependency dep = {0, - 0, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_DEPENDENCY_BY_REGION_BIT}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &attachment, 1, &subpass, 1, &dep}; - - VkResult err; - VkRenderPass rp; - err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - - // A compatible framebuffer. - VkImageObj image(m_device); - image.Init(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - VkImageView view = image.targetView(VK_FORMAT_R8G8B8A8_UNORM); - - VkFramebufferCreateInfo fci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 1, &view, 32, 32, 1}; - VkFramebuffer fb; - err = vkCreateFramebuffer(m_device->device(), &fci, nullptr, &fb); - ASSERT_VK_SUCCESS(err); - - // Record a single command buffer which issues a pipeline barrier w/ - // image memory barrier for the attachment. This detects the previously - // missing tracking of the subpass layout by throwing a validation error - // if it doesn't occur. - VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, rp, fb, {{0, 0}, {32, 32}}, 0, nullptr}; - m_commandBuffer->begin(); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE); - - VkImageMemoryBarrier imb = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - nullptr, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, - image.handle(), - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}}; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &imb); - - vkCmdEndRenderPass(m_commandBuffer->handle()); - m_errorMonitor->VerifyNotFound(); - m_commandBuffer->end(); - - vkDestroyFramebuffer(m_device->device(), fb, nullptr); - vkDestroyRenderPass(m_device->device(), rp, nullptr); -} - -TEST_F(VkPositiveLayerTest, RenderPassBeginTransitionsAttachmentUnused) { - TEST_DESCRIPTION( - "Ensure that layout transitions work correctly without errors, when an attachment reference is VK_ATTACHMENT_UNUSED"); - - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // A renderpass with no attachments - VkAttachmentReference att_ref = {VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - - VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &att_ref, nullptr, nullptr, 0, nullptr}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 0, nullptr, 1, &subpass, 0, nullptr}; - - VkRenderPass rp; - VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - - // A compatible framebuffer. - VkFramebufferCreateInfo fci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 0, nullptr, 32, 32, 1}; - VkFramebuffer fb; - err = vkCreateFramebuffer(m_device->device(), &fci, nullptr, &fb); - ASSERT_VK_SUCCESS(err); - - // Record a command buffer which just begins and ends the renderpass. The - // bug manifests in BeginRenderPass. - VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, rp, fb, {{0, 0}, {32, 32}}, 0, nullptr}; - m_commandBuffer->begin(); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE); - vkCmdEndRenderPass(m_commandBuffer->handle()); - m_errorMonitor->VerifyNotFound(); - m_commandBuffer->end(); - - vkDestroyFramebuffer(m_device->device(), fb, nullptr); - vkDestroyRenderPass(m_device->device(), rp, nullptr); -} - -TEST_F(VkPositiveLayerTest, RenderPassBeginStencilLoadOp) { - TEST_DESCRIPTION("Create a stencil-only attachment with a LOAD_OP set to CLEAR. stencil[Load|Store]Op used to be ignored."); - VkResult result = VK_SUCCESS; - ASSERT_NO_FATAL_FAILURE(Init()); - auto depth_format = FindSupportedDepthStencilFormat(gpu()); - if (!depth_format) { - printf("%s No Depth + Stencil format found. Skipped.\n", kSkipPrefix); - return; - } - VkImageFormatProperties formatProps; - vkGetPhysicalDeviceImageFormatProperties(gpu(), depth_format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0, - &formatProps); - if (formatProps.maxExtent.width < 100 || formatProps.maxExtent.height < 100) { - printf("%s Image format max extent is too small.\n", kSkipPrefix); - return; - } - - VkFormat depth_stencil_fmt = depth_format; - m_depthStencil->Init(m_device, 100, 100, depth_stencil_fmt, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); - VkAttachmentDescription att = {}; - VkAttachmentReference ref = {}; - att.format = depth_stencil_fmt; - att.samples = VK_SAMPLE_COUNT_1_BIT; - att.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - att.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - att.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - att.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkClearValue clear; - clear.depthStencil.depth = 1.0; - clear.depthStencil.stencil = 0; - ref.attachment = 0; - ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.flags = 0; - subpass.inputAttachmentCount = 0; - subpass.pInputAttachments = NULL; - subpass.colorAttachmentCount = 0; - subpass.pColorAttachments = NULL; - subpass.pResolveAttachments = NULL; - subpass.pDepthStencilAttachment = &ref; - subpass.preserveAttachmentCount = 0; - subpass.pPreserveAttachments = NULL; - - VkRenderPass rp; - VkRenderPassCreateInfo rp_info = {}; - rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - rp_info.attachmentCount = 1; - rp_info.pAttachments = &att; - rp_info.subpassCount = 1; - rp_info.pSubpasses = &subpass; - result = vkCreateRenderPass(device(), &rp_info, NULL, &rp); - ASSERT_VK_SUCCESS(result); - - VkImageView *depthView = m_depthStencil->BindInfo(); - VkFramebufferCreateInfo fb_info = {}; - fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - fb_info.pNext = NULL; - fb_info.renderPass = rp; - fb_info.attachmentCount = 1; - fb_info.pAttachments = depthView; - fb_info.width = 100; - fb_info.height = 100; - fb_info.layers = 1; - VkFramebuffer fb; - result = vkCreateFramebuffer(device(), &fb_info, NULL, &fb); - ASSERT_VK_SUCCESS(result); - - VkRenderPassBeginInfo rpbinfo = {}; - rpbinfo.clearValueCount = 1; - rpbinfo.pClearValues = &clear; - rpbinfo.pNext = NULL; - rpbinfo.renderPass = rp; - rpbinfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - rpbinfo.renderArea.extent.width = 100; - rpbinfo.renderArea.extent.height = 100; - rpbinfo.renderArea.offset.x = 0; - rpbinfo.renderArea.offset.y = 0; - rpbinfo.framebuffer = fb; - - VkFenceObj fence; - fence.init(*m_device, VkFenceObj::create_info()); - ASSERT_TRUE(fence.initialized()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(rpbinfo); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - m_commandBuffer->QueueCommandBuffer(fence); - - VkImageObj destImage(m_device); - destImage.Init(100, 100, 1, depth_stencil_fmt, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - VkImageMemoryBarrier barrier = {}; - VkImageSubresourceRange range; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; - barrier.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - barrier.image = m_depthStencil->handle(); - range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - range.baseMipLevel = 0; - range.levelCount = 1; - range.baseArrayLayer = 0; - range.layerCount = 1; - barrier.subresourceRange = range; - fence.wait(VK_TRUE, UINT64_MAX); - VkCommandBufferObj cmdbuf(m_device, m_commandPool); - cmdbuf.begin(); - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1, - &barrier); - barrier.srcAccessMask = 0; - barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - barrier.image = destImage.handle(); - barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1, - &barrier); - VkImageCopy cregion; - cregion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - cregion.srcSubresource.mipLevel = 0; - cregion.srcSubresource.baseArrayLayer = 0; - cregion.srcSubresource.layerCount = 1; - cregion.srcOffset.x = 0; - cregion.srcOffset.y = 0; - cregion.srcOffset.z = 0; - cregion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - cregion.dstSubresource.mipLevel = 0; - cregion.dstSubresource.baseArrayLayer = 0; - cregion.dstSubresource.layerCount = 1; - cregion.dstOffset.x = 0; - cregion.dstOffset.y = 0; - cregion.dstOffset.z = 0; - cregion.extent.width = 100; - cregion.extent.height = 100; - cregion.extent.depth = 1; - cmdbuf.CopyImage(m_depthStencil->handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, destImage.handle(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &cregion); - cmdbuf.end(); - - VkSubmitInfo submit_info; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.pNext = NULL; - submit_info.waitSemaphoreCount = 0; - submit_info.pWaitSemaphores = NULL; - submit_info.pWaitDstStageMask = NULL; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &cmdbuf.handle(); - submit_info.signalSemaphoreCount = 0; - submit_info.pSignalSemaphores = NULL; - - m_errorMonitor->ExpectSuccess(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyNotFound(); - - vkQueueWaitIdle(m_device->m_queue); - vkDestroyRenderPass(m_device->device(), rp, nullptr); - vkDestroyFramebuffer(m_device->device(), fb, nullptr); -} - -TEST_F(VkPositiveLayerTest, RenderPassBeginInlineAndSecondaryCommandBuffers) { - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - m_commandBuffer->begin(); - - vkCmdBeginRenderPass(m_commandBuffer->handle(), &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); - vkCmdEndRenderPass(m_commandBuffer->handle()); - m_errorMonitor->VerifyNotFound(); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - m_errorMonitor->VerifyNotFound(); - vkCmdEndRenderPass(m_commandBuffer->handle()); - m_errorMonitor->VerifyNotFound(); - - m_commandBuffer->end(); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, RenderPassBeginDepthStencilLayoutTransitionFromUndefined) { - TEST_DESCRIPTION( - "Create a render pass with depth-stencil attachment where layout transition from UNDEFINED TO DS_READ_ONLY_OPTIMAL is set " - "by render pass and verify that transition has correctly occurred at queue submit time with no validation errors."); - - ASSERT_NO_FATAL_FAILURE(Init()); - auto depth_format = FindSupportedDepthStencilFormat(gpu()); - if (!depth_format) { - printf("%s No Depth + Stencil format found. Skipped.\n", kSkipPrefix); - return; - } - VkImageFormatProperties format_props; - vkGetPhysicalDeviceImageFormatProperties(gpu(), depth_format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0, &format_props); - if (format_props.maxExtent.width < 32 || format_props.maxExtent.height < 32) { - printf("%s Depth extent too small, RenderPassDepthStencilLayoutTransition skipped.\n", kSkipPrefix); - return; - } - - m_errorMonitor->ExpectSuccess(); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // A renderpass with one depth/stencil attachment. - VkAttachmentDescription attachment = {0, - depth_format, - VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}; - - VkAttachmentReference att_ref = {0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}; - - VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, &att_ref, 0, nullptr}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &attachment, 1, &subpass, 0, nullptr}; - - VkRenderPass rp; - VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - // A compatible ds image. - VkImageObj image(m_device); - image.Init(32, 32, 1, depth_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - VkImageViewCreateInfo ivci = { - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - nullptr, - 0, - image.handle(), - VK_IMAGE_VIEW_TYPE_2D, - depth_format, - {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, - VK_COMPONENT_SWIZZLE_IDENTITY}, - {VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, 0, 1}, - }; - VkImageView view; - err = vkCreateImageView(m_device->device(), &ivci, nullptr, &view); - ASSERT_VK_SUCCESS(err); - - VkFramebufferCreateInfo fci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 1, &view, 32, 32, 1}; - VkFramebuffer fb; - err = vkCreateFramebuffer(m_device->device(), &fci, nullptr, &fb); - ASSERT_VK_SUCCESS(err); - - VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, rp, fb, {{0, 0}, {32, 32}}, 0, nullptr}; - m_commandBuffer->begin(); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE); - vkCmdEndRenderPass(m_commandBuffer->handle()); - m_commandBuffer->end(); - m_commandBuffer->QueueCommandBuffer(false); - m_errorMonitor->VerifyNotFound(); - - // Cleanup - vkDestroyImageView(m_device->device(), view, NULL); - vkDestroyRenderPass(m_device->device(), rp, NULL); - vkDestroyFramebuffer(m_device->device(), fb, NULL); -} - -TEST_F(VkLayerTest, DisabledIndependentBlend) { - TEST_DESCRIPTION( - "Generate INDEPENDENT_BLEND by disabling independent blend and then specifying different blend states for two " - "attachments"); - VkPhysicalDeviceFeatures features = {}; - features.independentBlend = VK_FALSE; - ASSERT_NO_FATAL_FAILURE(Init(&features)); - - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Invalid Pipeline CreateInfo: If independent blend feature not enabled, all elements of pAttachments must be identical"); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - VkPipelineObj pipeline(m_device); - // Create a renderPass with two color attachments - VkAttachmentReference attachments[2] = {}; - attachments[0].layout = VK_IMAGE_LAYOUT_GENERAL; - attachments[1].attachment = 1; - attachments[1].layout = VK_IMAGE_LAYOUT_GENERAL; - - VkSubpassDescription subpass = {}; - subpass.pColorAttachments = attachments; - subpass.colorAttachmentCount = 2; - - VkRenderPassCreateInfo rpci = {}; - rpci.subpassCount = 1; - rpci.pSubpasses = &subpass; - rpci.attachmentCount = 2; - - VkAttachmentDescription attach_desc[2] = {}; - attach_desc[0].format = VK_FORMAT_B8G8R8A8_UNORM; - attach_desc[0].samples = VK_SAMPLE_COUNT_1_BIT; - attach_desc[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attach_desc[0].finalLayout = VK_IMAGE_LAYOUT_GENERAL; - attach_desc[1].format = VK_FORMAT_B8G8R8A8_UNORM; - attach_desc[1].samples = VK_SAMPLE_COUNT_1_BIT; - attach_desc[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attach_desc[1].finalLayout = VK_IMAGE_LAYOUT_GENERAL; - - rpci.pAttachments = attach_desc; - rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - - VkRenderPass renderpass; - vkCreateRenderPass(m_device->device(), &rpci, NULL, &renderpass); - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - pipeline.AddShader(&vs); - - VkPipelineColorBlendAttachmentState att_state1 = {}, att_state2 = {}; - att_state1.dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR; - att_state1.blendEnable = VK_TRUE; - att_state2.dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR; - att_state2.blendEnable = VK_FALSE; - pipeline.AddColorAttachment(0, att_state1); - pipeline.AddColorAttachment(1, att_state2); - pipeline.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderpass); - m_errorMonitor->VerifyFound(); - vkDestroyRenderPass(m_device->device(), renderpass, NULL); -} - -// Is the Pipeline compatible with the expectations of the Renderpass/subpasses? -TEST_F(VkLayerTest, PipelineRenderpassCompatibility) { - TEST_DESCRIPTION( - "Create a graphics pipeline that is incompatible with the requirements of its contained Renderpass/subpasses."); - ASSERT_NO_FATAL_FAILURE(Init()); - - VkDescriptorSetObj ds_obj(m_device); - ds_obj.AppendDummy(); - ds_obj.CreateVKDescriptorSet(m_commandBuffer); - - VkShaderObj vs_obj(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - - VkPipelineColorBlendAttachmentState att_state1 = {}; - att_state1.dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR; - att_state1.blendEnable = VK_TRUE; - - VkRenderpassObj rp_obj(m_device); - - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-00753"); - VkPipelineObj pipeline(m_device); - pipeline.AddShader(&vs_obj); - pipeline.AddColorAttachment(0, att_state1); - - VkGraphicsPipelineCreateInfo info = {}; - pipeline.InitGraphicsPipelineCreateInfo(&info); - info.pColorBlendState = nullptr; - - pipeline.CreateVKPipeline(ds_obj.GetPipelineLayout(), rp_obj.handle(), &info); - m_errorMonitor->VerifyFound(); - } -} - -TEST_F(VkLayerTest, FramebufferCreateErrors) { - TEST_DESCRIPTION( - "Hit errors when attempting to create a framebuffer :\n" - " 1. Mismatch between framebuffer & renderPass attachmentCount\n" - " 2. Use a color image as depthStencil attachment\n" - " 3. Mismatch framebuffer & renderPass attachment formats\n" - " 4. Mismatch framebuffer & renderPass attachment #samples\n" - " 5. Framebuffer attachment w/ non-1 mip-levels\n" - " 6. Framebuffer attachment where dimensions don't match\n" - " 7. Framebuffer attachment where dimensions don't match\n" - " 8. Framebuffer attachment w/o identity swizzle\n" - " 9. framebuffer dimensions exceed physical device limits\n"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-attachmentCount-00876"); - - // Create a renderPass with a single color attachment - VkAttachmentReference attach = {}; - attach.layout = VK_IMAGE_LAYOUT_GENERAL; - VkSubpassDescription subpass = {}; - subpass.pColorAttachments = &attach; - VkRenderPassCreateInfo rpci = {}; - rpci.subpassCount = 1; - rpci.pSubpasses = &subpass; - rpci.attachmentCount = 1; - VkAttachmentDescription attach_desc = {}; - attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM; - attach_desc.samples = VK_SAMPLE_COUNT_1_BIT; - attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL; - rpci.pAttachments = &attach_desc; - rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - VkRenderPass rp; - VkResult err = vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - ASSERT_VK_SUCCESS(err); - - VkImageView ivs[2]; - ivs[0] = m_renderTargets[0]->targetView(VK_FORMAT_B8G8R8A8_UNORM); - ivs[1] = m_renderTargets[0]->targetView(VK_FORMAT_B8G8R8A8_UNORM); - VkFramebufferCreateInfo fb_info = {}; - fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - fb_info.pNext = NULL; - fb_info.renderPass = rp; - // Set mis-matching attachmentCount - fb_info.attachmentCount = 2; - fb_info.pAttachments = ivs; - fb_info.width = 100; - fb_info.height = 100; - fb_info.layers = 1; - - VkFramebuffer fb; - err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb); - - m_errorMonitor->VerifyFound(); - if (err == VK_SUCCESS) { - vkDestroyFramebuffer(m_device->device(), fb, NULL); - } - vkDestroyRenderPass(m_device->device(), rp, NULL); - - // Create a renderPass with a depth-stencil attachment created with - // IMAGE_USAGE_COLOR_ATTACHMENT - // Add our color attachment to pDepthStencilAttachment - subpass.pDepthStencilAttachment = &attach; - subpass.pColorAttachments = NULL; - VkRenderPass rp_ds; - err = vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_ds); - ASSERT_VK_SUCCESS(err); - // Set correct attachment count, but attachment has COLOR usage bit set - fb_info.attachmentCount = 1; - fb_info.renderPass = rp_ds; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-02633"); - err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb); - - m_errorMonitor->VerifyFound(); - if (err == VK_SUCCESS) { - vkDestroyFramebuffer(m_device->device(), fb, NULL); - } - vkDestroyRenderPass(m_device->device(), rp_ds, NULL); - - // Create new renderpass with alternate attachment format from fb - attach_desc.format = VK_FORMAT_R8G8B8A8_UNORM; - subpass.pDepthStencilAttachment = NULL; - subpass.pColorAttachments = &attach; - err = vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - ASSERT_VK_SUCCESS(err); - - // Cause error due to mis-matched formats between rp & fb - // rp attachment 0 now has RGBA8 but corresponding fb attach is BGRA8 - fb_info.renderPass = rp; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-00880"); - err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb); - - m_errorMonitor->VerifyFound(); - if (err == VK_SUCCESS) { - vkDestroyFramebuffer(m_device->device(), fb, NULL); - } - vkDestroyRenderPass(m_device->device(), rp, NULL); - - // Create new renderpass with alternate sample count from fb - attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM; - attach_desc.samples = VK_SAMPLE_COUNT_4_BIT; - err = vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - ASSERT_VK_SUCCESS(err); - - // Cause error due to mis-matched sample count between rp & fb - fb_info.renderPass = rp; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-00881"); - err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb); - - m_errorMonitor->VerifyFound(); - if (err == VK_SUCCESS) { - vkDestroyFramebuffer(m_device->device(), fb, NULL); - } - - vkDestroyRenderPass(m_device->device(), rp, NULL); - - { - // Create an image with 2 mip levels. - VkImageObj image(m_device); - image.Init(128, 128, 2, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - // Create a image view with two mip levels. - VkImageView view; - VkImageViewCreateInfo ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.image = image.handle(); - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.format = VK_FORMAT_B8G8R8A8_UNORM; - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - // Set level count to 2 (only 1 is allowed for FB attachment) - ivci.subresourceRange.levelCount = 2; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - err = vkCreateImageView(m_device->device(), &ivci, NULL, &view); - ASSERT_VK_SUCCESS(err); - - // Re-create renderpass to have matching sample count - attach_desc.samples = VK_SAMPLE_COUNT_1_BIT; - err = vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - ASSERT_VK_SUCCESS(err); - - fb_info.renderPass = rp; - fb_info.pAttachments = &view; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-00883"); - err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb); - - m_errorMonitor->VerifyFound(); - if (err == VK_SUCCESS) { - vkDestroyFramebuffer(m_device->device(), fb, NULL); - } - vkDestroyImageView(m_device->device(), view, NULL); - } - - // Update view to original color buffer and grow FB dimensions too big - fb_info.pAttachments = ivs; - fb_info.height = 1024; - fb_info.width = 1024; - fb_info.layers = 2; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-00882"); - err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb); - - m_errorMonitor->VerifyFound(); - if (err == VK_SUCCESS) { - vkDestroyFramebuffer(m_device->device(), fb, NULL); - } - - { - // Create an image with one mip level. - VkImageObj image(m_device); - image.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - // Create view attachment with non-identity swizzle - VkImageView view; - VkImageViewCreateInfo ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.image = image.handle(); - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.format = VK_FORMAT_B8G8R8A8_UNORM; - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - ivci.subresourceRange.levelCount = 1; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - ivci.components.r = VK_COMPONENT_SWIZZLE_G; - ivci.components.g = VK_COMPONENT_SWIZZLE_R; - ivci.components.b = VK_COMPONENT_SWIZZLE_A; - ivci.components.a = VK_COMPONENT_SWIZZLE_B; - err = vkCreateImageView(m_device->device(), &ivci, NULL, &view); - ASSERT_VK_SUCCESS(err); - - fb_info.pAttachments = &view; - fb_info.height = 100; - fb_info.width = 100; - fb_info.layers = 1; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-00884"); - err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb); - - m_errorMonitor->VerifyFound(); - if (err == VK_SUCCESS) { - vkDestroyFramebuffer(m_device->device(), fb, NULL); - } - vkDestroyImageView(m_device->device(), view, NULL); - } - - // reset attachment to color attachment - fb_info.pAttachments = ivs; - - // Request fb that exceeds max width - fb_info.width = m_device->props.limits.maxFramebufferWidth + 1; - fb_info.height = 100; - fb_info.layers = 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-width-00886"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-00882"); - err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb); - m_errorMonitor->VerifyFound(); - if (err == VK_SUCCESS) { - vkDestroyFramebuffer(m_device->device(), fb, NULL); - } - // and width=0 - fb_info.width = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-width-00885"); - err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb); - m_errorMonitor->VerifyFound(); - if (err == VK_SUCCESS) { - vkDestroyFramebuffer(m_device->device(), fb, NULL); - } - - // Request fb that exceeds max height - fb_info.width = 100; - fb_info.height = m_device->props.limits.maxFramebufferHeight + 1; - fb_info.layers = 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-height-00888"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-00882"); - err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb); - m_errorMonitor->VerifyFound(); - if (err == VK_SUCCESS) { - vkDestroyFramebuffer(m_device->device(), fb, NULL); - } - // and height=0 - fb_info.height = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-height-00887"); - err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb); - m_errorMonitor->VerifyFound(); - if (err == VK_SUCCESS) { - vkDestroyFramebuffer(m_device->device(), fb, NULL); - } - - // Request fb that exceeds max layers - fb_info.width = 100; - fb_info.height = 100; - fb_info.layers = m_device->props.limits.maxFramebufferLayers + 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-layers-00890"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-00882"); - err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb); - m_errorMonitor->VerifyFound(); - if (err == VK_SUCCESS) { - vkDestroyFramebuffer(m_device->device(), fb, NULL); - } - // and layers=0 - fb_info.layers = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-layers-00889"); - err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb); - m_errorMonitor->VerifyFound(); - if (err == VK_SUCCESS) { - vkDestroyFramebuffer(m_device->device(), fb, NULL); - } - - vkDestroyRenderPass(m_device->device(), rp, NULL); -} - -TEST_F(VkLayerTest, PointSizeFailure) { - TEST_DESCRIPTION("Create a pipeline using TOPOLOGY_POINT_LIST but do not set PointSize in vertex shader."); - - ASSERT_NO_FATAL_FAILURE(Init()); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Pipeline topology is set to POINT_LIST"); - - ASSERT_NO_FATAL_FAILURE(InitViewport()); - - // Create VS declaring PointSize but not writing to it - static const char NoPointSizeVertShader[] = - "#version 450\n" - "vec2 vertices[3];\n" - "out gl_PerVertex\n" - "{\n" - " vec4 gl_Position;\n" - " float gl_PointSize;\n" - "};\n" - "void main() {\n" - " vertices[0] = vec2(-1.0, -1.0);\n" - " vertices[1] = vec2( 1.0, -1.0);\n" - " vertices[2] = vec2( 0.0, 1.0);\n" - " gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);\n" - "}\n"; - - VkShaderObj vs(m_device, NoPointSizeVertShader, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj ps(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipelineobj(m_device); - pipelineobj.AddDefaultColorAttachment(); - pipelineobj.AddShader(&vs); - pipelineobj.AddShader(&ps); - - // Set Input Assembly to TOPOLOGY POINT LIST - VkPipelineInputAssemblyStateCreateInfo ia_state = {}; - ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - ia_state.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; - pipelineobj.SetInputAssembly(&ia_state); - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - m_commandBuffer->begin(); - m_commandBuffer->ClearAllBuffers(m_renderTargets, m_clear_color, m_depthStencil, m_depth_clear_color, m_stencil_clear_color); - m_commandBuffer->PrepareAttachments(m_renderTargets, m_depthStencil); - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, InvalidTopology) { - TEST_DESCRIPTION("InvalidTopology."); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - VkPhysicalDeviceFeatures deviceFeatures = {}; - deviceFeatures.geometryShader = VK_FALSE; - deviceFeatures.tessellationShader = VK_FALSE; - - ASSERT_NO_FATAL_FAILURE(InitState(&deviceFeatures)); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - - const char PointSizeWriteVertShaderFcn[] = - "#version 450\n" - "vec2 vertices[3];\n" - "out gl_PerVertex\n" - "{\n" - " vec4 gl_Position;\n" - " float gl_PointSize;\n" - "};\n" - "void OutPointSize() {\n" - " gl_PointSize = 7.0;\n" - "}\n" - "void main() {\n" - " vertices[0] = vec2(-1.0, -1.0);\n" - " vertices[1] = vec2( 1.0, -1.0);\n" - " vertices[2] = vec2( 0.0, 1.0);\n" - " gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);\n" - " OutPointSize();\n" - "}\n"; - - VkShaderObj vs(m_device, PointSizeWriteVertShaderFcn, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj ps(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipelineobj(m_device); - pipelineobj.AddDefaultColorAttachment(); - pipelineobj.AddShader(&vs); - pipelineobj.AddShader(&ps); - - // Set Input Assembly to TOPOLOGY POINT LIST - VkPipelineInputAssemblyStateCreateInfo ia_state = {}; - ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - m_commandBuffer->begin(); - m_commandBuffer->ClearAllBuffers(m_renderTargets, m_clear_color, m_depthStencil, m_depth_clear_color, m_stencil_clear_color); - m_commandBuffer->PrepareAttachments(m_renderTargets, m_depthStencil); - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - ia_state.primitiveRestartEnable = VK_TRUE; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00428"); - ia_state.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; - pipelineobj.SetInputAssembly(&ia_state); - pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00428"); - ia_state.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST; - pipelineobj.SetInputAssembly(&ia_state); - pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00428"); - ia_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - pipelineobj.SetInputAssembly(&ia_state); - pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00428"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429"); - ia_state.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY; - pipelineobj.SetInputAssembly(&ia_state); - pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00428"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429"); - ia_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY; - pipelineobj.SetInputAssembly(&ia_state); - pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00428"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00430"); - m_errorMonitor->SetUnexpectedError("VUID-VkGraphicsPipelineCreateInfo-topology-00737"); - ia_state.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; - pipelineobj.SetInputAssembly(&ia_state); - pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429"); - ia_state.topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY; - pipelineobj.SetInputAssembly(&ia_state); - pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429"); - ia_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY; - pipelineobj.SetInputAssembly(&ia_state); - pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, PointSizeGeomShaderFailure) { - TEST_DESCRIPTION( - "Create a pipeline using TOPOLOGY_POINT_LIST, set PointSize vertex shader, but not in the final geometry stage."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - if ((!m_device->phy().features().geometryShader) || (!m_device->phy().features().shaderTessellationAndGeometryPointSize)) { - printf("%s Device does not support the required geometry shader features; skipped.\n", kSkipPrefix); - return; - } - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Pipeline topology is set to POINT_LIST"); - - ASSERT_NO_FATAL_FAILURE(InitViewport()); - - // Create VS declaring PointSize and writing to it - static const char PointSizeVertShader[] = - "#version 450\n" - "vec2 vertices[3];\n" - "out gl_PerVertex\n" - "{\n" - " vec4 gl_Position;\n" - " float gl_PointSize;\n" - "};\n" - "void main() {\n" - " vertices[0] = vec2(-1.0, -1.0);\n" - " vertices[1] = vec2( 1.0, -1.0);\n" - " vertices[2] = vec2( 0.0, 1.0);\n" - " gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);\n" - " gl_PointSize = 5.0;\n" - "}\n"; - static char const *gsSource = - "#version 450\n" - "layout (points) in;\n" - "layout (points) out;\n" - "layout (max_vertices = 1) out;\n" - "void main() {\n" - " gl_Position = vec4(1.0, 0.5, 0.5, 0.0);\n" - " EmitVertex();\n" - "}\n"; - - VkShaderObj vs(m_device, PointSizeVertShader, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj gs(m_device, gsSource, VK_SHADER_STAGE_GEOMETRY_BIT, this); - VkShaderObj ps(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipelineobj(m_device); - pipelineobj.AddDefaultColorAttachment(); - pipelineobj.AddShader(&vs); - pipelineobj.AddShader(&gs); - pipelineobj.AddShader(&ps); - - // Set Input Assembly to TOPOLOGY POINT LIST - VkPipelineInputAssemblyStateCreateInfo ia_state = {}; - ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - ia_state.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; - pipelineobj.SetInputAssembly(&ia_state); - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - m_commandBuffer->begin(); - m_commandBuffer->ClearAllBuffers(m_renderTargets, m_clear_color, m_depthStencil, m_depth_clear_color, m_stencil_clear_color); - m_commandBuffer->PrepareAttachments(m_renderTargets, m_depthStencil); - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, BuiltinBlockOrderMismatchVsGs) { - TEST_DESCRIPTION("Use different order of gl_Position and gl_PointSize in builtin block interface between VS and GS."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - if (!m_device->phy().features().geometryShader) { - printf("%s Device does not support geometry shaders; Skipped.\n", kSkipPrefix); - return; - } - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Builtin variable inside block doesn't match between"); - - ASSERT_NO_FATAL_FAILURE(InitViewport()); - static const char *vsSource = - "#version 450\n" - "out gl_PerVertex\n" - "{\n" - " vec4 gl_Position;\n" - " float gl_PointSize;\n" - "};\n" - "void main() {\n" - " gl_Position = vec4(1.0);\n" - " gl_PointSize = 5.0;\n" - "}\n"; - - // Compiled using the GLSL code below. GlslangValidator rearranges the members, but here they are kept in the order provided. - // #version 450 - // layout (points) in; - // layout (points) out; - // layout (max_vertices = 1) out; - // in gl_PerVertex { - // float gl_PointSize; - // vec4 gl_Position; - // } gl_in[]; - // void main() { - // gl_Position = gl_in[0].gl_Position; - // gl_PointSize = gl_in[0].gl_PointSize; - // EmitVertex(); - // } - - const std::string gsSource = R"( - OpCapability Geometry - OpCapability GeometryPointSize - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Geometry %main "main" %_ %gl_in - OpExecutionMode %main InputPoints - OpExecutionMode %main Invocations 1 - OpExecutionMode %main OutputPoints - OpExecutionMode %main OutputVertices 1 - OpSource GLSL 450 - OpMemberDecorate %gl_PerVertex 0 BuiltIn Position - OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize - OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance - OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance - OpDecorate %gl_PerVertex Block - OpMemberDecorate %gl_PerVertex_0 0 BuiltIn PointSize - OpMemberDecorate %gl_PerVertex_0 1 BuiltIn Position - OpDecorate %gl_PerVertex_0 Block - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %uint = OpTypeInt 32 0 - %uint_1 = OpConstant %uint 1 -%_arr_float_uint_1 = OpTypeArray %float %uint_1 -%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1 -%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex - %_ = OpVariable %_ptr_Output_gl_PerVertex Output - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 -%gl_PerVertex_0 = OpTypeStruct %float %v4float -%_arr_gl_PerVertex_0_uint_1 = OpTypeArray %gl_PerVertex_0 %uint_1 -%_ptr_Input__arr_gl_PerVertex_0_uint_1 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_1 - %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_1 Input -%_ptr_Input_v4float = OpTypePointer Input %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float - %int_1 = OpConstant %int 1 -%_ptr_Input_float = OpTypePointer Input %float -%_ptr_Output_float = OpTypePointer Output %float - %main = OpFunction %void None %3 - %5 = OpLabel - %21 = OpAccessChain %_ptr_Input_v4float %gl_in %int_0 %int_1 - %22 = OpLoad %v4float %21 - %24 = OpAccessChain %_ptr_Output_v4float %_ %int_0 - OpStore %24 %22 - %27 = OpAccessChain %_ptr_Input_float %gl_in %int_0 %int_0 - %28 = OpLoad %float %27 - %30 = OpAccessChain %_ptr_Output_float %_ %int_1 - OpStore %30 %28 - OpEmitVertex - OpReturn - OpFunctionEnd - )"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj gs(m_device, gsSource, VK_SHADER_STAGE_GEOMETRY_BIT, this); - VkShaderObj ps(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipelineobj(m_device); - pipelineobj.AddDefaultColorAttachment(); - pipelineobj.AddShader(&vs); - pipelineobj.AddShader(&gs); - pipelineobj.AddShader(&ps); - - VkPipelineInputAssemblyStateCreateInfo ia_state = {}; - ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - ia_state.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; - pipelineobj.SetInputAssembly(&ia_state); - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - m_commandBuffer->begin(); - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, BuiltinBlockSizeMismatchVsGs) { - TEST_DESCRIPTION("Use different number of elements in builtin block interface between VS and GS."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - if (!m_device->phy().features().geometryShader) { - printf("%s Device does not support geometry shaders; Skipped.\n", kSkipPrefix); - return; - } - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Number of elements inside builtin block differ between stages"); - - ASSERT_NO_FATAL_FAILURE(InitViewport()); - static const char *vsSource = - "#version 450\n" - "out gl_PerVertex\n" - "{\n" - " vec4 gl_Position;\n" - " float gl_PointSize;\n" - "};\n" - "void main() {\n" - " gl_Position = vec4(1.0);\n" - " gl_PointSize = 5.0;\n" - "}\n"; - - static const char *gsSource = - "#version 450\n" - "layout (points) in;\n" - "layout (points) out;\n" - "layout (max_vertices = 1) out;\n" - "in gl_PerVertex\n" - "{\n" - " vec4 gl_Position;\n" - " float gl_PointSize;\n" - " float gl_ClipDistance[];\n" - "} gl_in[];\n" - "void main()\n" - "{\n" - " gl_Position = gl_in[0].gl_Position;\n" - " gl_PointSize = gl_in[0].gl_PointSize;\n" - " EmitVertex();\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj gs(m_device, gsSource, VK_SHADER_STAGE_GEOMETRY_BIT, this); - VkShaderObj ps(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipelineobj(m_device); - pipelineobj.AddDefaultColorAttachment(); - pipelineobj.AddShader(&vs); - pipelineobj.AddShader(&gs); - pipelineobj.AddShader(&ps); - - VkPipelineInputAssemblyStateCreateInfo ia_state = {}; - ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - ia_state.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; - pipelineobj.SetInputAssembly(&ia_state); - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - m_commandBuffer->begin(); - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, DynamicDepthBiasNotBound) { - TEST_DESCRIPTION( - "Run a simple draw calls to validate failure when Depth Bias dynamic state is required but not correctly bound."); - - ASSERT_NO_FATAL_FAILURE(Init()); - // Dynamic depth bias - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Dynamic depth bias state not set for this command buffer"); - VKTriangleTest(BsoFailDepthBias); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, DynamicLineWidthNotBound) { - TEST_DESCRIPTION( - "Run a simple draw calls to validate failure when Line Width dynamic state is required but not correctly bound."); - - ASSERT_NO_FATAL_FAILURE(Init()); - // Dynamic line width - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Dynamic line width state not set for this command buffer"); - VKTriangleTest(BsoFailLineWidth); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, DynamicViewportNotBound) { - TEST_DESCRIPTION( - "Run a simple draw calls to validate failure when Viewport dynamic state is required but not correctly bound."); - - ASSERT_NO_FATAL_FAILURE(Init()); - // Dynamic viewport state - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Dynamic viewport(s) 0 are used by pipeline state object, but were not provided"); - VKTriangleTest(BsoFailViewport); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, DynamicScissorNotBound) { - TEST_DESCRIPTION("Run a simple draw calls to validate failure when Scissor dynamic state is required but not correctly bound."); - - ASSERT_NO_FATAL_FAILURE(Init()); - // Dynamic scissor state - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Dynamic scissor(s) 0 are used by pipeline state object, but were not provided"); - VKTriangleTest(BsoFailScissor); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, DynamicBlendConstantsNotBound) { - TEST_DESCRIPTION( - "Run a simple draw calls to validate failure when Blend Constants dynamic state is required but not correctly bound."); - - ASSERT_NO_FATAL_FAILURE(Init()); - // Dynamic blend constant state - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Dynamic blend constants state not set for this command buffer"); - VKTriangleTest(BsoFailBlend); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, DynamicDepthBoundsNotBound) { - TEST_DESCRIPTION( - "Run a simple draw calls to validate failure when Depth Bounds dynamic state is required but not correctly bound."); - - ASSERT_NO_FATAL_FAILURE(Init()); - if (!m_device->phy().features().depthBounds) { - printf("%s Device does not support depthBounds test; skipped.\n", kSkipPrefix); - return; - } - // Dynamic depth bounds - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Dynamic depth bounds state not set for this command buffer"); - VKTriangleTest(BsoFailDepthBounds); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, DynamicStencilReadNotBound) { - TEST_DESCRIPTION( - "Run a simple draw calls to validate failure when Stencil Read dynamic state is required but not correctly bound."); - - ASSERT_NO_FATAL_FAILURE(Init()); - // Dynamic stencil read mask - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Dynamic stencil read mask state not set for this command buffer"); - VKTriangleTest(BsoFailStencilReadMask); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, DynamicStencilWriteNotBound) { - TEST_DESCRIPTION( - "Run a simple draw calls to validate failure when Stencil Write dynamic state is required but not correctly bound."); - - ASSERT_NO_FATAL_FAILURE(Init()); - // Dynamic stencil write mask - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Dynamic stencil write mask state not set for this command buffer"); - VKTriangleTest(BsoFailStencilWriteMask); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, DynamicStencilRefNotBound) { - TEST_DESCRIPTION( - "Run a simple draw calls to validate failure when Stencil Ref dynamic state is required but not correctly bound."); - - ASSERT_NO_FATAL_FAILURE(Init()); - // Dynamic stencil reference - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Dynamic stencil reference state not set for this command buffer"); - VKTriangleTest(BsoFailStencilReference); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, IndexBufferNotBound) { - TEST_DESCRIPTION("Run an indexed draw call without an index buffer bound."); - - ASSERT_NO_FATAL_FAILURE(Init()); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Index buffer object not bound to this command buffer when Indexed "); - VKTriangleTest(BsoFailIndexBuffer); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, IndexBufferBadSize) { - TEST_DESCRIPTION("Run indexed draw call with bad index buffer size."); - - ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "vkCmdDrawIndexed() index size "); - VKTriangleTest(BsoFailIndexBufferBadSize); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, IndexBufferBadOffset) { - TEST_DESCRIPTION("Run indexed draw call with bad index buffer offset."); - - ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "vkCmdDrawIndexed() index size "); - VKTriangleTest(BsoFailIndexBufferBadOffset); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, IndexBufferBadBindSize) { - TEST_DESCRIPTION("Run bind index buffer with a size greater than the index buffer."); - - ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "vkCmdDrawIndexed() index size "); - VKTriangleTest(BsoFailIndexBufferBadMapSize); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, IndexBufferBadBindOffset) { - TEST_DESCRIPTION("Run bind index buffer with an offset greater than the size of the index buffer."); - - ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "vkCmdDrawIndexed() index size "); - VKTriangleTest(BsoFailIndexBufferBadMapOffset); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CommandBufferTwoSubmits) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "was begun w/ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT set, but has been submitted"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // We luck out b/c by default the framework creates CB w/ the - // VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT set - m_commandBuffer->begin(); - m_commandBuffer->ClearAllBuffers(m_renderTargets, m_clear_color, nullptr, m_depth_clear_color, m_stencil_clear_color); - m_commandBuffer->end(); - - // Bypass framework since it does the waits automatically - VkResult err = VK_SUCCESS; - VkSubmitInfo submit_info; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.pNext = NULL; - submit_info.waitSemaphoreCount = 0; - submit_info.pWaitSemaphores = NULL; - submit_info.pWaitDstStageMask = NULL; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - submit_info.signalSemaphoreCount = 0; - submit_info.pSignalSemaphores = NULL; - - err = vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - ASSERT_VK_SUCCESS(err); - vkQueueWaitIdle(m_device->m_queue); - - // Cause validation error by re-submitting cmd buffer that should only be - // submitted once - err = vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - vkQueueWaitIdle(m_device->m_queue); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, AllocDescriptorFromEmptyPool) { - TEST_DESCRIPTION("Attempt to allocate more sets and descriptors than descriptor pool has available."); - VkResult err; - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // This test is valid for Vulkan 1.0 only -- skip if device has an API version greater than 1.0. - if (m_device->props.apiVersion >= VK_API_VERSION_1_1) { - printf("%s Device has apiVersion greater than 1.0 -- skipping Descriptor Set checks.\n", kSkipPrefix); - return; - } - - // Create Pool w/ 1 Sampler descriptor, but try to alloc Uniform Buffer - // descriptor from it - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_SAMPLER; - ds_type_count.descriptorCount = 2; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.flags = 0; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool; - err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSetLayoutBinding dsl_binding_samp = {}; - dsl_binding_samp.binding = 0; - dsl_binding_samp.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - dsl_binding_samp.descriptorCount = 1; - dsl_binding_samp.stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding_samp.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout_samp(m_device, {dsl_binding_samp}); - - // Try to allocate 2 sets when pool only has 1 set - VkDescriptorSet descriptor_sets[2]; - VkDescriptorSetLayout set_layouts[2] = {ds_layout_samp.handle(), ds_layout_samp.handle()}; - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorSetCount = 2; - alloc_info.descriptorPool = ds_pool; - alloc_info.pSetLayouts = set_layouts; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkDescriptorSetAllocateInfo-descriptorSetCount-00306"); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, descriptor_sets); - m_errorMonitor->VerifyFound(); - - alloc_info.descriptorSetCount = 1; - // Create layout w/ descriptor type not available in pool - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 0; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout_ub(m_device, {dsl_binding}); - - VkDescriptorSet descriptor_set; - alloc_info.descriptorSetCount = 1; - alloc_info.pSetLayouts = &ds_layout_ub.handle(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorSetAllocateInfo-descriptorPool-00307"); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptor_set); - - m_errorMonitor->VerifyFound(); - - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); -} - -TEST_F(VkLayerTest, FreeDescriptorFromOneShotPool) { - VkResult err; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkFreeDescriptorSets-descriptorPool-00312"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.flags = 0; - // Not specifying VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT means - // app can only call vkResetDescriptorPool on this pool.; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool; - err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 0; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding}); - - VkDescriptorSet descriptorSet; - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorSetCount = 1; - alloc_info.descriptorPool = ds_pool; - alloc_info.pSetLayouts = &ds_layout.handle(); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptorSet); - ASSERT_VK_SUCCESS(err); - - err = vkFreeDescriptorSets(m_device->device(), ds_pool, 1, &descriptorSet); - m_errorMonitor->VerifyFound(); - - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); -} - -TEST_F(VkLayerTest, InvalidDescriptorPool) { - // Attempt to clear Descriptor Pool with bad object. - // ObjectTracker should catch this. - - ASSERT_NO_FATAL_FAILURE(Init()); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkResetDescriptorPool-descriptorPool-parameter"); - uint64_t fake_pool_handle = 0xbaad6001; - VkDescriptorPool bad_pool = reinterpret_cast<VkDescriptorPool &>(fake_pool_handle); - vkResetDescriptorPool(device(), bad_pool, 0); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, InvalidDescriptorSet) { - // Attempt to bind an invalid Descriptor Set to a valid Command Buffer - // ObjectTracker should catch this. - // Create a valid cmd buffer - // call vkCmdBindDescriptorSets w/ false Descriptor Set - - uint64_t fake_set_handle = 0xbaad6001; - VkDescriptorSet bad_set = reinterpret_cast<VkDescriptorSet &>(fake_set_handle); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindDescriptorSets-pDescriptorSets-parameter"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkDescriptorSetLayoutBinding layout_binding = {}; - layout_binding.binding = 0; - layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - layout_binding.descriptorCount = 1; - layout_binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - layout_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj descriptor_set_layout(m_device, {layout_binding}); - - const VkPipelineLayoutObj pipeline_layout(DeviceObj(), {&descriptor_set_layout}); - - m_commandBuffer->begin(); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, &bad_set, 0, - NULL); - m_errorMonitor->VerifyFound(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, InvalidDescriptorSetLayout) { - // Attempt to create a Pipeline Layout with an invalid Descriptor Set Layout. - // ObjectTracker should catch this. - uint64_t fake_layout_handle = 0xbaad6001; - VkDescriptorSetLayout bad_layout = reinterpret_cast<VkDescriptorSetLayout &>(fake_layout_handle); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-parameter"); - ASSERT_NO_FATAL_FAILURE(Init()); - VkPipelineLayout pipeline_layout; - VkPipelineLayoutCreateInfo plci = {}; - plci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - plci.pNext = NULL; - plci.setLayoutCount = 1; - plci.pSetLayouts = &bad_layout; - vkCreatePipelineLayout(device(), &plci, NULL, &pipeline_layout); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, WriteDescriptorSetIntegrityCheck) { - TEST_DESCRIPTION( - "This test verifies some requirements of chapter 13.2.3 of the Vulkan Spec " - "1) A uniform buffer update must have a valid buffer index. " - "2) When using an array of descriptors in a single WriteDescriptor, the descriptor types and stageflags " - "must all be the same. " - "3) Immutable Sampler state must match across descriptors. " - "4) That sampled image descriptors have required layouts. "); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-00324"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - VkSampler sampler; - VkResult err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler); - ASSERT_VK_SUCCESS(err); - - OneOffDescriptorSet::Bindings bindings = { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, NULL}, - {1, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, NULL}, - {2, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, static_cast<VkSampler *>(&sampler)}, - {3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT, NULL}}; - OneOffDescriptorSet descriptor_set(m_device, bindings); - ASSERT_TRUE(descriptor_set.Initialized()); - - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = descriptor_set.set_; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - - // 1) The uniform buffer is intentionally invalid here - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - - // Create a buffer to update the descriptor with - uint32_t qfi = 0; - VkBufferCreateInfo buffCI = {}; - buffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffCI.size = 1024; - buffCI.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - buffCI.queueFamilyIndexCount = 1; - buffCI.pQueueFamilyIndices = &qfi; - - VkBuffer dyub; - err = vkCreateBuffer(m_device->device(), &buffCI, NULL, &dyub); - ASSERT_VK_SUCCESS(err); - - VkDeviceMemory mem; - VkMemoryRequirements mem_reqs; - vkGetBufferMemoryRequirements(m_device->device(), dyub, &mem_reqs); - - VkMemoryAllocateInfo mem_alloc_info = {}; - mem_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc_info.allocationSize = mem_reqs.size; - m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &mem_alloc_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - err = vkAllocateMemory(m_device->device(), &mem_alloc_info, NULL, &mem); - ASSERT_VK_SUCCESS(err); - - err = vkBindBufferMemory(m_device->device(), dyub, mem, 0); - ASSERT_VK_SUCCESS(err); - - VkDescriptorBufferInfo buffInfo[2] = {}; - buffInfo[0].buffer = dyub; - buffInfo[0].offset = 0; - buffInfo[0].range = 1024; - buffInfo[1].buffer = dyub; - buffInfo[1].offset = 0; - buffInfo[1].range = 1024; - descriptor_write.pBufferInfo = buffInfo; - descriptor_write.descriptorCount = 2; - - // 2) The stateFlags don't match between the first and second descriptor - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-dstArrayElement-00321"); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - - // 3) The second descriptor has a null_ptr pImmutableSamplers and - // the third descriptor contains an immutable sampler - descriptor_write.dstBinding = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - - // Make pImageInfo index non-null to avoid complaints of it missing - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - descriptor_write.pImageInfo = &imageInfo; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-dstArrayElement-00321"); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - - // 4) That sampled image descriptors have required layouts - // Create images to update the descriptor with - VkImageObj image(m_device); - const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; - image.Init(32, 32, 1, tex_format, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - // Attmept write with incorrect layout for sampled descriptor - imageInfo.sampler = VK_NULL_HANDLE; - imageInfo.imageView = image.targetView(tex_format); - imageInfo.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - descriptor_write.dstBinding = 3; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-01403"); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - - vkDestroyBuffer(m_device->device(), dyub, NULL); - vkFreeMemory(m_device->device(), mem, NULL); - vkDestroySampler(m_device->device(), sampler, NULL); -} - -TEST_F(VkLayerTest, WriteDescriptorSetConsecutiveUpdates) { - TEST_DESCRIPTION( - "Verifies that updates rolling over to next descriptor work correctly by destroying buffer from consecutive update known " - "to be used in descriptor set and verifying that error is flagged."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, VK_SHADER_STAGE_ALL, nullptr}, - {1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - - uint32_t qfi = 0; - VkBufferCreateInfo bci = {}; - bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bci.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - bci.size = 2048; - bci.queueFamilyIndexCount = 1; - bci.pQueueFamilyIndices = &qfi; - VkBufferObj buffer0; - buffer0.init(*m_device, bci); - VkPipelineObj pipe(m_device); - { // Scope 2nd buffer to cause early destruction - VkBufferObj buffer1; - bci.size = 1024; - buffer1.init(*m_device, bci); - - VkDescriptorBufferInfo buffer_info[3] = {}; - buffer_info[0].buffer = buffer0.handle(); - buffer_info[0].offset = 0; - buffer_info[0].range = 1024; - buffer_info[1].buffer = buffer0.handle(); - buffer_info[1].offset = 1024; - buffer_info[1].range = 1024; - buffer_info[2].buffer = buffer1.handle(); - buffer_info[2].offset = 0; - buffer_info[2].range = 1024; - - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; // descriptor_set; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 3; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_write.pBufferInfo = buffer_info; - - // Update descriptor - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - // Create PSO that uses the uniform buffers - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 x;\n" - "layout(set=0) layout(binding=0) uniform foo { int x; int y; } bar;\n" - "layout(set=0) layout(binding=1) uniform blah { int x; } duh;\n" - "void main(){\n" - " x = vec4(duh.x, bar.y, bar.x, 1);\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - - VkResult err = pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &ds.set_, 0, nullptr); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - vkCmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); - vkCmdEndRenderPass(m_commandBuffer->handle()); - m_commandBuffer->end(); - } - // buffer2 just went out of scope and was destroyed along with its memory - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " that is invalid because bound Buffer "); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " that is invalid because bound DeviceMemory "); - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineLayoutExceedsSetLimit) { - TEST_DESCRIPTION("Attempt to create a pipeline layout using more than the physical limit of SetLayouts."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkDescriptorSetLayoutBinding layout_binding = {}; - layout_binding.binding = 0; - layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - layout_binding.descriptorCount = 1; - layout_binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - layout_binding.pImmutableSamplers = NULL; - - VkDescriptorSetLayoutCreateInfo ds_layout_ci = {}; - ds_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - ds_layout_ci.bindingCount = 1; - ds_layout_ci.pBindings = &layout_binding; - VkDescriptorSetLayout ds_layout = {}; - VkResult err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - ASSERT_VK_SUCCESS(err); - - // Create an array of DSLs, one larger than the physical limit - const auto excess_layouts = 1 + m_device->phy().properties().limits.maxBoundDescriptorSets; - std::vector<VkDescriptorSetLayout> dsl_array(excess_layouts, ds_layout); - - VkPipelineLayoutCreateInfo pipeline_layout_ci = {}; - pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_ci.pNext = NULL; - pipeline_layout_ci.setLayoutCount = excess_layouts; - pipeline_layout_ci.pSetLayouts = dsl_array.data(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-setLayoutCount-00286"); - VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - - // Clean up - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL); -} - -TEST_F(VkLayerTest, CreatePipelineLayoutExcessPerStageDescriptors) { - TEST_DESCRIPTION("Attempt to create a pipeline layout where total descriptors exceed per-stage limits"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - uint32_t max_uniform_buffers = m_device->phy().properties().limits.maxPerStageDescriptorUniformBuffers; - uint32_t max_storage_buffers = m_device->phy().properties().limits.maxPerStageDescriptorStorageBuffers; - uint32_t max_sampled_images = m_device->phy().properties().limits.maxPerStageDescriptorSampledImages; - uint32_t max_storage_images = m_device->phy().properties().limits.maxPerStageDescriptorStorageImages; - uint32_t max_samplers = m_device->phy().properties().limits.maxPerStageDescriptorSamplers; - uint32_t max_combined = std::min(max_samplers, max_sampled_images); - uint32_t max_input_attachments = m_device->phy().properties().limits.maxPerStageDescriptorInputAttachments; - - uint32_t sum_dyn_uniform_buffers = m_device->phy().properties().limits.maxDescriptorSetUniformBuffersDynamic; - uint32_t sum_uniform_buffers = m_device->phy().properties().limits.maxDescriptorSetUniformBuffers; - uint32_t sum_dyn_storage_buffers = m_device->phy().properties().limits.maxDescriptorSetStorageBuffersDynamic; - uint32_t sum_storage_buffers = m_device->phy().properties().limits.maxDescriptorSetStorageBuffers; - uint32_t sum_sampled_images = m_device->phy().properties().limits.maxDescriptorSetSampledImages; - uint32_t sum_storage_images = m_device->phy().properties().limits.maxDescriptorSetStorageImages; - uint32_t sum_samplers = m_device->phy().properties().limits.maxDescriptorSetSamplers; - uint32_t sum_input_attachments = m_device->phy().properties().limits.maxDescriptorSetInputAttachments; - - // Devices that report UINT32_MAX for any of these limits can't run this test - if (UINT32_MAX == std::max({max_uniform_buffers, max_storage_buffers, max_sampled_images, max_storage_images, max_samplers})) { - printf("%s Physical device limits report as 2^32-1. Skipping test.\n", kSkipPrefix); - return; - } - - VkDescriptorSetLayoutBinding dslb = {}; - std::vector<VkDescriptorSetLayoutBinding> dslb_vec = {}; - VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE; - VkDescriptorSetLayoutCreateInfo ds_layout_ci = {}; - ds_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - ds_layout_ci.pNext = NULL; - VkPipelineLayoutCreateInfo pipeline_layout_ci = {}; - pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_ci.pNext = NULL; - pipeline_layout_ci.setLayoutCount = 1; - pipeline_layout_ci.pSetLayouts = &ds_layout; - VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; - - // VU 0fe0023e - too many sampler type descriptors in fragment stage - dslb_vec.clear(); - dslb.binding = 0; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - dslb.descriptorCount = max_samplers; - dslb.stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS; - dslb.pImmutableSamplers = NULL; - dslb_vec.push_back(dslb); - dslb.binding = 1; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - dslb.descriptorCount = max_combined; - dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - dslb_vec.push_back(dslb); - - ds_layout_ci.bindingCount = dslb_vec.size(); - ds_layout_ci.pBindings = dslb_vec.data(); - VkResult err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00287"); - if ((max_samplers + max_combined) > sum_samplers) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01677"); // expect all-stages sum too - } - if (max_combined > sum_sampled_images) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01682"); // expect all-stages sum too - } - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL); // Unnecessary but harmless if test passed - pipeline_layout = VK_NULL_HANDLE; - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL); - - // VU 0fe00240 - too many uniform buffer type descriptors in vertex stage - dslb_vec.clear(); - dslb.binding = 0; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - dslb.descriptorCount = max_uniform_buffers + 1; - dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; - dslb_vec.push_back(dslb); - dslb.binding = 1; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - dslb_vec.push_back(dslb); - - ds_layout_ci.bindingCount = dslb_vec.size(); - ds_layout_ci.pBindings = dslb_vec.data(); - err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00288"); - if (dslb.descriptorCount > sum_uniform_buffers) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01678"); // expect all-stages sum too - } - if (dslb.descriptorCount > sum_dyn_uniform_buffers) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01679"); // expect all-stages sum too - } - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL); // Unnecessary but harmless if test passed - pipeline_layout = VK_NULL_HANDLE; - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL); - - // VU 0fe00242 - too many storage buffer type descriptors in compute stage - dslb_vec.clear(); - dslb.binding = 0; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - dslb.descriptorCount = max_storage_buffers + 1; - dslb.stageFlags = VK_SHADER_STAGE_ALL; - dslb_vec.push_back(dslb); - dslb.binding = 1; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; - dslb_vec.push_back(dslb); - dslb.binding = 2; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - dslb.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; - dslb_vec.push_back(dslb); - - ds_layout_ci.bindingCount = dslb_vec.size(); - ds_layout_ci.pBindings = dslb_vec.data(); - err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00289"); - if (dslb.descriptorCount > sum_dyn_storage_buffers) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01681"); // expect all-stages sum too - } - if (dslb_vec[0].descriptorCount + dslb_vec[2].descriptorCount > sum_storage_buffers) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01680"); // expect all-stages sum too - } - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL); // Unnecessary but harmless if test passed - pipeline_layout = VK_NULL_HANDLE; - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL); - - // VU 0fe00244 - too many sampled image type descriptors in multiple stages - dslb_vec.clear(); - dslb.binding = 0; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - dslb.descriptorCount = max_sampled_images; - dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; - dslb_vec.push_back(dslb); - dslb.binding = 1; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - dslb.stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS; - dslb_vec.push_back(dslb); - dslb.binding = 2; - dslb.descriptorCount = max_combined; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - dslb_vec.push_back(dslb); - - ds_layout_ci.bindingCount = dslb_vec.size(); - ds_layout_ci.pBindings = dslb_vec.data(); - err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00290"); - if (max_combined + 2 * max_sampled_images > sum_sampled_images) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01682"); // expect all-stages sum too - } - if (max_combined > sum_samplers) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01677"); // expect all-stages sum too - } - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL); // Unnecessary but harmless if test passed - pipeline_layout = VK_NULL_HANDLE; - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL); - - // VU 0fe00246 - too many storage image type descriptors in fragment stage - dslb_vec.clear(); - dslb.binding = 0; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - dslb.descriptorCount = 1 + (max_storage_images / 2); - dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - dslb_vec.push_back(dslb); - dslb.binding = 1; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT; - dslb_vec.push_back(dslb); - - ds_layout_ci.bindingCount = dslb_vec.size(); - ds_layout_ci.pBindings = dslb_vec.data(); - err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00291"); - if (2 * dslb.descriptorCount > sum_storage_images) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01683"); // expect all-stages sum too - } - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL); // Unnecessary but harmless if test passed - pipeline_layout = VK_NULL_HANDLE; - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL); - - // VU 0fe00d18 - too many input attachments in fragment stage - dslb_vec.clear(); - dslb.binding = 0; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; - dslb.descriptorCount = 1 + max_input_attachments; - dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - dslb_vec.push_back(dslb); - - ds_layout_ci.bindingCount = dslb_vec.size(); - ds_layout_ci.pBindings = dslb_vec.data(); - err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01676"); - if (dslb.descriptorCount > sum_input_attachments) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01684"); // expect all-stages sum too - } - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL); // Unnecessary but harmless if test passed - pipeline_layout = VK_NULL_HANDLE; - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL); -} - -TEST_F(VkLayerTest, CreatePipelineLayoutExcessDescriptorsOverall) { - TEST_DESCRIPTION("Attempt to create a pipeline layout where total descriptors exceed limits"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - uint32_t max_uniform_buffers = m_device->phy().properties().limits.maxPerStageDescriptorUniformBuffers; - uint32_t max_storage_buffers = m_device->phy().properties().limits.maxPerStageDescriptorStorageBuffers; - uint32_t max_sampled_images = m_device->phy().properties().limits.maxPerStageDescriptorSampledImages; - uint32_t max_storage_images = m_device->phy().properties().limits.maxPerStageDescriptorStorageImages; - uint32_t max_samplers = m_device->phy().properties().limits.maxPerStageDescriptorSamplers; - uint32_t max_input_attachments = m_device->phy().properties().limits.maxPerStageDescriptorInputAttachments; - - uint32_t sum_dyn_uniform_buffers = m_device->phy().properties().limits.maxDescriptorSetUniformBuffersDynamic; - uint32_t sum_uniform_buffers = m_device->phy().properties().limits.maxDescriptorSetUniformBuffers; - uint32_t sum_dyn_storage_buffers = m_device->phy().properties().limits.maxDescriptorSetStorageBuffersDynamic; - uint32_t sum_storage_buffers = m_device->phy().properties().limits.maxDescriptorSetStorageBuffers; - uint32_t sum_sampled_images = m_device->phy().properties().limits.maxDescriptorSetSampledImages; - uint32_t sum_storage_images = m_device->phy().properties().limits.maxDescriptorSetStorageImages; - uint32_t sum_samplers = m_device->phy().properties().limits.maxDescriptorSetSamplers; - uint32_t sum_input_attachments = m_device->phy().properties().limits.maxDescriptorSetInputAttachments; - - // Devices that report UINT32_MAX for any of these limits can't run this test - if (UINT32_MAX == std::max({sum_dyn_uniform_buffers, sum_uniform_buffers, sum_dyn_storage_buffers, sum_storage_buffers, - sum_sampled_images, sum_storage_images, sum_samplers, sum_input_attachments})) { - printf("%s Physical device limits report as 2^32-1. Skipping test.\n", kSkipPrefix); - return; - } - - VkDescriptorSetLayoutBinding dslb = {}; - std::vector<VkDescriptorSetLayoutBinding> dslb_vec = {}; - VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE; - VkDescriptorSetLayoutCreateInfo ds_layout_ci = {}; - ds_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - ds_layout_ci.pNext = NULL; - VkPipelineLayoutCreateInfo pipeline_layout_ci = {}; - pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_ci.pNext = NULL; - pipeline_layout_ci.setLayoutCount = 1; - pipeline_layout_ci.pSetLayouts = &ds_layout; - VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; - - // VU 0fe00d1a - too many sampler type descriptors overall - dslb_vec.clear(); - dslb.binding = 0; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - dslb.descriptorCount = sum_samplers / 2; - dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - dslb.pImmutableSamplers = NULL; - dslb_vec.push_back(dslb); - dslb.binding = 1; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - dslb.descriptorCount = sum_samplers - dslb.descriptorCount + 1; - dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - dslb_vec.push_back(dslb); - - ds_layout_ci.bindingCount = dslb_vec.size(); - ds_layout_ci.pBindings = dslb_vec.data(); - VkResult err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01677"); - if (dslb.descriptorCount > max_samplers) { - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00287"); // Expect max-per-stage samplers exceeds limits - } - if (dslb.descriptorCount > sum_sampled_images) { - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01682"); // Expect max overall sampled image count exceeds limits - } - if (dslb.descriptorCount > max_sampled_images) { - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00290"); // Expect max per-stage sampled image count exceeds limits - } - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL); // Unnecessary but harmless if test passed - pipeline_layout = VK_NULL_HANDLE; - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL); - - // VU 0fe00d1c - too many uniform buffer type descriptors overall - dslb_vec.clear(); - dslb.binding = 0; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - dslb.descriptorCount = sum_uniform_buffers + 1; - dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; - dslb.pImmutableSamplers = NULL; - dslb_vec.push_back(dslb); - - ds_layout_ci.bindingCount = dslb_vec.size(); - ds_layout_ci.pBindings = dslb_vec.data(); - err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01678"); - if (dslb.descriptorCount > max_uniform_buffers) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00288"); // expect max-per-stage too - } - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL); // Unnecessary but harmless if test passed - pipeline_layout = VK_NULL_HANDLE; - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL); - - // VU 0fe00d1e - too many dynamic uniform buffer type descriptors overall - dslb_vec.clear(); - dslb.binding = 0; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - dslb.descriptorCount = sum_dyn_uniform_buffers + 1; - dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; - dslb.pImmutableSamplers = NULL; - dslb_vec.push_back(dslb); - - ds_layout_ci.bindingCount = dslb_vec.size(); - ds_layout_ci.pBindings = dslb_vec.data(); - err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01679"); - if (dslb.descriptorCount > max_uniform_buffers) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00288"); // expect max-per-stage too - } - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL); // Unnecessary but harmless if test passed - pipeline_layout = VK_NULL_HANDLE; - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL); - - // VU 0fe00d20 - too many storage buffer type descriptors overall - dslb_vec.clear(); - dslb.binding = 0; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - dslb.descriptorCount = sum_storage_buffers + 1; - dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; - dslb.pImmutableSamplers = NULL; - dslb_vec.push_back(dslb); - - ds_layout_ci.bindingCount = dslb_vec.size(); - ds_layout_ci.pBindings = dslb_vec.data(); - err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01680"); - if (dslb.descriptorCount > max_storage_buffers) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00289"); // expect max-per-stage too - } - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL); // Unnecessary but harmless if test passed - pipeline_layout = VK_NULL_HANDLE; - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL); - - // VU 0fe00d22 - too many dynamic storage buffer type descriptors overall - dslb_vec.clear(); - dslb.binding = 0; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; - dslb.descriptorCount = sum_dyn_storage_buffers + 1; - dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; - dslb.pImmutableSamplers = NULL; - dslb_vec.push_back(dslb); - - ds_layout_ci.bindingCount = dslb_vec.size(); - ds_layout_ci.pBindings = dslb_vec.data(); - err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01681"); - if (dslb.descriptorCount > max_storage_buffers) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00289"); // expect max-per-stage too - } - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL); // Unnecessary but harmless if test passed - pipeline_layout = VK_NULL_HANDLE; - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL); - - // VU 0fe00d24 - too many sampled image type descriptors overall - dslb_vec.clear(); - dslb.binding = 0; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - dslb.descriptorCount = max_samplers; - dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - dslb.pImmutableSamplers = NULL; - dslb_vec.push_back(dslb); - dslb.binding = 1; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - // revisit: not robust to odd limits. - uint32_t remaining = (max_samplers > sum_sampled_images ? 0 : (sum_sampled_images - max_samplers) / 2); - dslb.descriptorCount = 1 + remaining; - dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - dslb_vec.push_back(dslb); - dslb.binding = 2; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - dslb.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; - dslb_vec.push_back(dslb); - - ds_layout_ci.bindingCount = dslb_vec.size(); - ds_layout_ci.pBindings = dslb_vec.data(); - err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01682"); - if (std::max(dslb_vec[0].descriptorCount, dslb_vec[1].descriptorCount) > max_sampled_images) { - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00290"); // Expect max-per-stage sampled images to exceed limits - } - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL); // Unnecessary but harmless if test passed - pipeline_layout = VK_NULL_HANDLE; - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL); - - // VU 0fe00d26 - too many storage image type descriptors overall - dslb_vec.clear(); - dslb.binding = 0; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - dslb.descriptorCount = sum_storage_images / 2; - dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - dslb.pImmutableSamplers = NULL; - dslb_vec.push_back(dslb); - dslb.binding = 1; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - dslb.descriptorCount = sum_storage_images - dslb.descriptorCount + 1; - dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - dslb_vec.push_back(dslb); - - ds_layout_ci.bindingCount = dslb_vec.size(); - ds_layout_ci.pBindings = dslb_vec.data(); - err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01683"); - if (dslb.descriptorCount > max_storage_images) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00291"); // expect max-per-stage too - } - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL); // Unnecessary but harmless if test passed - pipeline_layout = VK_NULL_HANDLE; - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL); - - // VU 0fe00d28 - too many input attachment type descriptors overall - dslb_vec.clear(); - dslb.binding = 0; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; - dslb.descriptorCount = sum_input_attachments + 1; - dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - dslb.pImmutableSamplers = NULL; - dslb_vec.push_back(dslb); - - ds_layout_ci.bindingCount = dslb_vec.size(); - ds_layout_ci.pBindings = dslb_vec.data(); - err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01684"); - if (dslb.descriptorCount > max_input_attachments) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01676"); // expect max-per-stage too - } - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL); // Unnecessary but harmless if test passed - pipeline_layout = VK_NULL_HANDLE; - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL); -} - -TEST_F(VkLayerTest, InvalidCmdBufferBufferDestroyed) { - TEST_DESCRIPTION("Attempt to draw with a command buffer that is invalid due to a buffer dependency being destroyed."); - ASSERT_NO_FATAL_FAILURE(Init()); - - VkBuffer buffer; - VkDeviceMemory mem; - VkMemoryRequirements mem_reqs; - - VkBufferCreateInfo buf_info = {}; - buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buf_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; - buf_info.size = 256; - buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VkResult err = vkCreateBuffer(m_device->device(), &buf_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - vkGetBufferMemoryRequirements(m_device->device(), buffer, &mem_reqs); - - VkMemoryAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.allocationSize = mem_reqs.size; - bool pass = false; - pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &alloc_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - if (!pass) { - printf("%s Failed to set memory type.\n", kSkipPrefix); - vkDestroyBuffer(m_device->device(), buffer, NULL); - return; - } - err = vkAllocateMemory(m_device->device(), &alloc_info, NULL, &mem); - ASSERT_VK_SUCCESS(err); - - err = vkBindBufferMemory(m_device->device(), buffer, mem, 0); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - vkCmdFillBuffer(m_commandBuffer->handle(), buffer, 0, VK_WHOLE_SIZE, 0); - m_commandBuffer->end(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " that is invalid because bound Buffer "); - // Destroy buffer dependency prior to submit to cause ERROR - vkDestroyBuffer(m_device->device(), buffer, NULL); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - - m_errorMonitor->VerifyFound(); - vkQueueWaitIdle(m_device->m_queue); - vkFreeMemory(m_device->handle(), mem, NULL); -} - -TEST_F(VkLayerTest, InvalidCmdBufferBufferViewDestroyed) { - TEST_DESCRIPTION("Delete bufferView bound to cmd buffer, then attempt to submit cmd buffer."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorPoolSize ds_type_count; - ds_type_count.type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool; - VkResult err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSetLayoutBinding layout_binding; - layout_binding.binding = 0; - layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - layout_binding.descriptorCount = 1; - layout_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - layout_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout(m_device, {layout_binding}); - - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorSetCount = 1; - alloc_info.descriptorPool = ds_pool; - alloc_info.pSetLayouts = &ds_layout.handle(); - VkDescriptorSet descriptor_set; - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptor_set); - ASSERT_VK_SUCCESS(err); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds_layout}); - - VkBuffer buffer; - uint32_t queue_family_index = 0; - VkBufferCreateInfo buffer_create_info = {}; - buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_create_info.size = 1024; - buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; - buffer_create_info.queueFamilyIndexCount = 1; - buffer_create_info.pQueueFamilyIndices = &queue_family_index; - - err = vkCreateBuffer(m_device->device(), &buffer_create_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - VkMemoryRequirements memory_reqs; - VkDeviceMemory buffer_memory; - - VkMemoryAllocateInfo memory_info = {}; - memory_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_info.allocationSize = 0; - memory_info.memoryTypeIndex = 0; - - vkGetBufferMemoryRequirements(m_device->device(), buffer, &memory_reqs); - memory_info.allocationSize = memory_reqs.size; - bool pass = m_device->phy().set_memory_type(memory_reqs.memoryTypeBits, &memory_info, 0); - ASSERT_TRUE(pass); - - err = vkAllocateMemory(m_device->device(), &memory_info, NULL, &buffer_memory); - ASSERT_VK_SUCCESS(err); - err = vkBindBufferMemory(m_device->device(), buffer, buffer_memory, 0); - ASSERT_VK_SUCCESS(err); - - VkBufferView view; - VkBufferViewCreateInfo bvci = {}; - bvci.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; - bvci.buffer = buffer; - bvci.format = VK_FORMAT_R32_SFLOAT; - bvci.range = VK_WHOLE_SIZE; - - err = vkCreateBufferView(m_device->device(), &bvci, NULL, &view); - ASSERT_VK_SUCCESS(err); - - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = descriptor_set; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - descriptor_write.pTexelBufferView = &view; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(set=0, binding=0, r32f) uniform readonly imageBuffer s;\n" - "layout(location=0) out vec4 x;\n" - "void main(){\n" - " x = imageLoad(s, 0);\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - // Bind pipeline to cmd buffer - This causes crash on Mali - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptor_set, 0, nullptr); - - vkDestroyBuffer(m_device->device(), buffer, NULL); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Descriptor in binding #0 index 0 is using buffer"); - m_commandBuffer->Draw(1, 0, 0, 0); - m_errorMonitor->VerifyFound(); - - vkDestroyBufferView(m_device->device(), view, NULL); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Descriptor in binding #0 index 0 is using bufferView"); - m_commandBuffer->Draw(1, 0, 0, 0); - m_errorMonitor->VerifyFound(); - - vkFreeMemory(m_device->device(), buffer_memory, NULL); - err = vkCreateBuffer(m_device->device(), &buffer_create_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - vkGetBufferMemoryRequirements(m_device->device(), buffer, &memory_reqs); - memory_info.allocationSize = memory_reqs.size; - pass = m_device->phy().set_memory_type(memory_reqs.memoryTypeBits, &memory_info, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(m_device->device(), &memory_info, NULL, &buffer_memory); - ASSERT_VK_SUCCESS(err); - err = vkBindBufferMemory(m_device->device(), buffer, buffer_memory, 0); - ASSERT_VK_SUCCESS(err); - bvci.buffer = buffer; - err = vkCreateBufferView(m_device->device(), &bvci, NULL, &view); - ASSERT_VK_SUCCESS(err); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptor_set, 0, nullptr); - m_commandBuffer->Draw(1, 0, 0, 0); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - - // Delete BufferView in order to invalidate cmd buffer - vkDestroyBufferView(m_device->device(), view, NULL); - // Now attempt submit of cmd buffer - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " that is invalid because bound BufferView "); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - - // Clean-up - vkDestroyBuffer(m_device->device(), buffer, NULL); - vkFreeMemory(m_device->device(), buffer_memory, NULL); - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); -} - -TEST_F(VkLayerTest, InvalidCmdBufferImageDestroyed) { - TEST_DESCRIPTION("Attempt to draw with a command buffer that is invalid due to an image dependency being destroyed."); - ASSERT_NO_FATAL_FAILURE(Init()); - - VkImage image; - const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = tex_format; - image_create_info.extent.width = 32; - image_create_info.extent.height = 32; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - image_create_info.flags = 0; - VkResult err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - ASSERT_VK_SUCCESS(err); - // Have to bind memory to image before recording cmd in cmd buffer using it - VkMemoryRequirements mem_reqs; - VkDeviceMemory image_mem; - bool pass; - VkMemoryAllocateInfo mem_alloc = {}; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.memoryTypeIndex = 0; - vkGetImageMemoryRequirements(m_device->device(), image, &mem_reqs); - mem_alloc.allocationSize = mem_reqs.size; - pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &mem_alloc, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &image_mem); - ASSERT_VK_SUCCESS(err); - err = vkBindImageMemory(m_device->device(), image, image_mem, 0); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - VkClearColorValue ccv; - ccv.float32[0] = 1.0f; - ccv.float32[1] = 1.0f; - ccv.float32[2] = 1.0f; - ccv.float32[3] = 1.0f; - VkImageSubresourceRange isr = {}; - isr.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - isr.baseArrayLayer = 0; - isr.baseMipLevel = 0; - isr.layerCount = 1; - isr.levelCount = 1; - vkCmdClearColorImage(m_commandBuffer->handle(), image, VK_IMAGE_LAYOUT_GENERAL, &ccv, 1, &isr); - m_commandBuffer->end(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " that is invalid because bound Image "); - // Destroy image dependency prior to submit to cause ERROR - vkDestroyImage(m_device->device(), image, NULL); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - - m_errorMonitor->VerifyFound(); - vkFreeMemory(m_device->device(), image_mem, nullptr); -} - -TEST_F(VkLayerTest, InvalidCmdBufferFramebufferImageDestroyed) { - TEST_DESCRIPTION( - "Attempt to draw with a command buffer that is invalid due to a framebuffer image dependency being destroyed."); - ASSERT_NO_FATAL_FAILURE(Init()); - VkFormatProperties format_properties; - VkResult err = VK_SUCCESS; - vkGetPhysicalDeviceFormatProperties(gpu(), VK_FORMAT_B8G8R8A8_UNORM, &format_properties); - if (!(format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) { - printf("%s Image format doesn't support required features.\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkImageCreateInfo image_ci = {}; - image_ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_ci.pNext = NULL; - image_ci.imageType = VK_IMAGE_TYPE_2D; - image_ci.format = VK_FORMAT_B8G8R8A8_UNORM; - image_ci.extent.width = 32; - image_ci.extent.height = 32; - image_ci.extent.depth = 1; - image_ci.mipLevels = 1; - image_ci.arrayLayers = 1; - image_ci.samples = VK_SAMPLE_COUNT_1_BIT; - image_ci.tiling = VK_IMAGE_TILING_OPTIMAL; - image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - image_ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - image_ci.flags = 0; - VkImage image; - ASSERT_VK_SUCCESS(vkCreateImage(m_device->handle(), &image_ci, NULL, &image)); - - VkMemoryRequirements memory_reqs; - VkDeviceMemory image_memory; - bool pass; - VkMemoryAllocateInfo memory_info = {}; - memory_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_info.pNext = NULL; - memory_info.allocationSize = 0; - memory_info.memoryTypeIndex = 0; - vkGetImageMemoryRequirements(m_device->device(), image, &memory_reqs); - memory_info.allocationSize = memory_reqs.size; - pass = m_device->phy().set_memory_type(memory_reqs.memoryTypeBits, &memory_info, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(m_device->device(), &memory_info, NULL, &image_memory); - ASSERT_VK_SUCCESS(err); - err = vkBindImageMemory(m_device->device(), image, image_memory, 0); - ASSERT_VK_SUCCESS(err); - - VkImageViewCreateInfo ivci = { - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - nullptr, - 0, - image, - VK_IMAGE_VIEW_TYPE_2D, - VK_FORMAT_B8G8R8A8_UNORM, - {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}, - }; - VkImageView view; - err = vkCreateImageView(m_device->device(), &ivci, nullptr, &view); - ASSERT_VK_SUCCESS(err); - - VkFramebufferCreateInfo fci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, m_renderPass, 1, &view, 32, 32, 1}; - VkFramebuffer fb; - err = vkCreateFramebuffer(m_device->device(), &fci, nullptr, &fb); - ASSERT_VK_SUCCESS(err); - - // Just use default renderpass with our framebuffer - m_renderPassBeginInfo.framebuffer = fb; - m_renderPassBeginInfo.renderArea.extent.width = 32; - m_renderPassBeginInfo.renderArea.extent.height = 32; - // Create Null cmd buffer for submit - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - // Destroy image attached to framebuffer to invalidate cmd buffer - 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_commandBuffer->QueueCommandBuffer(false); - m_errorMonitor->VerifyFound(); - - vkDestroyFramebuffer(m_device->device(), fb, nullptr); - vkDestroyImageView(m_device->device(), view, nullptr); - vkFreeMemory(m_device->device(), image_memory, nullptr); -} - -TEST_F(VkLayerTest, FramebufferInUseDestroyedSignaled) { - TEST_DESCRIPTION("Delete in-use framebuffer."); - ASSERT_NO_FATAL_FAILURE(Init()); - VkFormatProperties format_properties; - VkResult err = VK_SUCCESS; - vkGetPhysicalDeviceFormatProperties(gpu(), VK_FORMAT_B8G8R8A8_UNORM, &format_properties); - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkImageObj image(m_device); - image.Init(256, 256, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - VkImageView view = image.targetView(VK_FORMAT_B8G8R8A8_UNORM); - - VkFramebufferCreateInfo fci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, m_renderPass, 1, &view, 256, 256, 1}; - VkFramebuffer fb; - err = vkCreateFramebuffer(m_device->device(), &fci, nullptr, &fb); - ASSERT_VK_SUCCESS(err); - - // Just use default renderpass with our framebuffer - m_renderPassBeginInfo.framebuffer = fb; - // Create Null cmd buffer for submit - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - // Submit cmd buffer to put it in-flight - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - // Destroy framebuffer while in-flight - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkDestroyFramebuffer-framebuffer-00892"); - vkDestroyFramebuffer(m_device->device(), fb, NULL); - 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); -} - -TEST_F(VkLayerTest, FramebufferImageInUseDestroyedSignaled) { - TEST_DESCRIPTION("Delete in-use image that's child of framebuffer."); - ASSERT_NO_FATAL_FAILURE(Init()); - VkFormatProperties format_properties; - VkResult err = VK_SUCCESS; - vkGetPhysicalDeviceFormatProperties(gpu(), VK_FORMAT_B8G8R8A8_UNORM, &format_properties); - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkImageCreateInfo image_ci = {}; - image_ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_ci.pNext = NULL; - image_ci.imageType = VK_IMAGE_TYPE_2D; - image_ci.format = VK_FORMAT_B8G8R8A8_UNORM; - image_ci.extent.width = 256; - image_ci.extent.height = 256; - image_ci.extent.depth = 1; - image_ci.mipLevels = 1; - image_ci.arrayLayers = 1; - image_ci.samples = VK_SAMPLE_COUNT_1_BIT; - image_ci.tiling = VK_IMAGE_TILING_OPTIMAL; - image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - image_ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - image_ci.flags = 0; - VkImage image; - ASSERT_VK_SUCCESS(vkCreateImage(m_device->handle(), &image_ci, NULL, &image)); - - VkMemoryRequirements memory_reqs; - VkDeviceMemory image_memory; - bool pass; - VkMemoryAllocateInfo memory_info = {}; - memory_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_info.pNext = NULL; - memory_info.allocationSize = 0; - memory_info.memoryTypeIndex = 0; - vkGetImageMemoryRequirements(m_device->device(), image, &memory_reqs); - memory_info.allocationSize = memory_reqs.size; - pass = m_device->phy().set_memory_type(memory_reqs.memoryTypeBits, &memory_info, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(m_device->device(), &memory_info, NULL, &image_memory); - ASSERT_VK_SUCCESS(err); - err = vkBindImageMemory(m_device->device(), image, image_memory, 0); - ASSERT_VK_SUCCESS(err); - - VkImageViewCreateInfo ivci = { - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - nullptr, - 0, - image, - VK_IMAGE_VIEW_TYPE_2D, - VK_FORMAT_B8G8R8A8_UNORM, - {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}, - }; - VkImageView view; - err = vkCreateImageView(m_device->device(), &ivci, nullptr, &view); - ASSERT_VK_SUCCESS(err); - - VkFramebufferCreateInfo fci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, m_renderPass, 1, &view, 256, 256, 1}; - VkFramebuffer fb; - err = vkCreateFramebuffer(m_device->device(), &fci, nullptr, &fb); - ASSERT_VK_SUCCESS(err); - - // Just use default renderpass with our framebuffer - m_renderPassBeginInfo.framebuffer = fb; - // Create Null cmd buffer for submit - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - // Submit cmd buffer to put it (and attached imageView) in-flight - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - // Submit cmd buffer to put framebuffer and children in-flight - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - // Destroy image attached to framebuffer while in-flight - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkDestroyImage-image-01000"); - vkDestroyImage(m_device->device(), image, NULL); - 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); - vkFreeMemory(m_device->device(), image_memory, nullptr); -} - -TEST_F(VkLayerTest, ImageMemoryNotBound) { - TEST_DESCRIPTION("Attempt to draw with an image which has not had memory bound to it."); - ASSERT_NO_FATAL_FAILURE(Init()); - - VkImage image; - const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = tex_format; - image_create_info.extent.width = 32; - image_create_info.extent.height = 32; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - image_create_info.flags = 0; - VkResult err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - ASSERT_VK_SUCCESS(err); - // Have to bind memory to image before recording cmd in cmd buffer using it - VkMemoryRequirements mem_reqs; - VkDeviceMemory image_mem; - bool pass; - VkMemoryAllocateInfo mem_alloc = {}; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.memoryTypeIndex = 0; - vkGetImageMemoryRequirements(m_device->device(), image, &mem_reqs); - mem_alloc.allocationSize = mem_reqs.size; - pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &mem_alloc, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &image_mem); - ASSERT_VK_SUCCESS(err); - - // Introduce error, do not call vkBindImageMemory(m_device->device(), image, image_mem, 0); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - " used with no memory bound. Memory should be bound by calling vkBindImageMemory()."); - - m_commandBuffer->begin(); - VkClearColorValue ccv; - ccv.float32[0] = 1.0f; - ccv.float32[1] = 1.0f; - ccv.float32[2] = 1.0f; - ccv.float32[3] = 1.0f; - VkImageSubresourceRange isr = {}; - isr.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - isr.baseArrayLayer = 0; - isr.baseMipLevel = 0; - isr.layerCount = 1; - isr.levelCount = 1; - vkCmdClearColorImage(m_commandBuffer->handle(), image, VK_IMAGE_LAYOUT_GENERAL, &ccv, 1, &isr); - m_commandBuffer->end(); - - m_errorMonitor->VerifyFound(); - vkDestroyImage(m_device->device(), image, NULL); - vkFreeMemory(m_device->device(), image_mem, nullptr); -} - -TEST_F(VkLayerTest, BufferMemoryNotBound) { - TEST_DESCRIPTION("Attempt to copy from a buffer which has not had memory bound to it."); - ASSERT_NO_FATAL_FAILURE(Init()); - - VkImageObj image(m_device); - image.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - VkBuffer buffer; - VkDeviceMemory mem; - VkMemoryRequirements mem_reqs; - - VkBufferCreateInfo buf_info = {}; - buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buf_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - buf_info.size = 1024; - buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VkResult err = vkCreateBuffer(m_device->device(), &buf_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - vkGetBufferMemoryRequirements(m_device->device(), buffer, &mem_reqs); - - VkMemoryAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.allocationSize = 1024; - bool pass = false; - pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &alloc_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - if (!pass) { - printf("%s Failed to set memory type.\n", kSkipPrefix); - vkDestroyBuffer(m_device->device(), buffer, NULL); - return; - } - err = vkAllocateMemory(m_device->device(), &alloc_info, NULL, &mem); - ASSERT_VK_SUCCESS(err); - - // Introduce failure by not calling vkBindBufferMemory(m_device->device(), buffer, mem, 0); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - " used with no memory bound. Memory should be bound by calling vkBindBufferMemory()."); - VkBufferImageCopy region = {}; - region.bufferRowLength = 16; - region.bufferImageHeight = 16; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - region.imageSubresource.layerCount = 1; - region.imageExtent.height = 4; - region.imageExtent.width = 4; - region.imageExtent.depth = 1; - m_commandBuffer->begin(); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer, image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - m_commandBuffer->end(); - - m_errorMonitor->VerifyFound(); - - vkDestroyBuffer(m_device->device(), buffer, NULL); - vkFreeMemory(m_device->handle(), mem, NULL); -} - -TEST_F(VkLayerTest, InvalidCmdBufferEventDestroyed) { - TEST_DESCRIPTION("Attempt to draw with a command buffer that is invalid due to an event dependency being destroyed."); - ASSERT_NO_FATAL_FAILURE(Init()); - - VkEvent event; - VkEventCreateInfo evci = {}; - evci.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - VkResult result = vkCreateEvent(m_device->device(), &evci, NULL, &event); - ASSERT_VK_SUCCESS(result); - - m_commandBuffer->begin(); - vkCmdSetEvent(m_commandBuffer->handle(), event, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - m_commandBuffer->end(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " that is invalid because bound Event "); - // Destroy event dependency prior to submit to cause ERROR - vkDestroyEvent(m_device->device(), event, NULL); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, InvalidCmdBufferQueryPoolDestroyed) { - TEST_DESCRIPTION("Attempt to draw with a command buffer that is invalid due to a query pool dependency being destroyed."); - ASSERT_NO_FATAL_FAILURE(Init()); - - VkQueryPool query_pool; - VkQueryPoolCreateInfo qpci{}; - qpci.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; - qpci.queryType = VK_QUERY_TYPE_TIMESTAMP; - qpci.queryCount = 1; - VkResult result = vkCreateQueryPool(m_device->device(), &qpci, nullptr, &query_pool); - ASSERT_VK_SUCCESS(result); - - m_commandBuffer->begin(); - vkCmdResetQueryPool(m_commandBuffer->handle(), query_pool, 0, 1); - m_commandBuffer->end(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " that is invalid because bound QueryPool "); - // Destroy query pool dependency prior to submit to cause ERROR - vkDestroyQueryPool(m_device->device(), query_pool, NULL); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, InvalidCmdBufferPipelineDestroyed) { - TEST_DESCRIPTION("Attempt to draw with a command buffer that is invalid due to a pipeline dependency being destroyed."); - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - { - // Use helper to create graphics pipeline - CreatePipelineHelper helper(*this); - helper.InitInfo(); - helper.InitState(); - helper.CreateGraphicsPipeline(); - - // Bind helper pipeline to command buffer - m_commandBuffer->begin(); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, helper.pipeline_); - m_commandBuffer->end(); - - // pipeline will be destroyed when helper goes out of scope - } - - // Cause error by submitting command buffer that references destroyed pipeline - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " that is invalid because bound Pipeline "); - m_commandBuffer->QueueCommandBuffer(false); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkPositiveLayerTest, DestroyPipelineRenderPass) { - TEST_DESCRIPTION("Draw using a pipeline whose create renderPass has been destroyed."); - m_errorMonitor->ExpectSuccess(); - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkResult err; - - // Create a renderPass that's compatible with Draw-time renderPass - VkAttachmentDescription att = {}; - att.format = m_render_target_fmt; - att.samples = VK_SAMPLE_COUNT_1_BIT; - att.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - att.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - att.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - att.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkAttachmentReference ref = {}; - ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - ref.attachment = 0; - - m_renderPassClearValues.clear(); - VkClearValue clear = {}; - clear.color = m_clear_color; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.flags = 0; - subpass.inputAttachmentCount = 0; - subpass.pInputAttachments = NULL; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &ref; - subpass.pResolveAttachments = NULL; - - subpass.pDepthStencilAttachment = NULL; - subpass.preserveAttachmentCount = 0; - subpass.pPreserveAttachments = NULL; - - VkRenderPassCreateInfo rp_info = {}; - rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - rp_info.attachmentCount = 1; - rp_info.pAttachments = &att; - rp_info.subpassCount = 1; - rp_info.pSubpasses = &subpass; - - VkRenderPass rp; - err = vkCreateRenderPass(device(), &rp_info, NULL, &rp); - ASSERT_VK_SUCCESS(err); - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; - m_viewports.push_back(viewport); - pipe.SetViewport(m_viewports); - VkRect2D rect = {{0, 0}, {64, 64}}; - m_scissors.push_back(rect); - pipe.SetScissor(m_scissors); - - const VkPipelineLayoutObj pl(m_device); - pipe.CreateVKPipeline(pl.handle(), rp); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - // Destroy renderPass before pipeline is used in Draw - // We delay until after CmdBindPipeline to verify that invalid binding isn't - // created between CB & renderPass, which we used to do. - vkDestroyRenderPass(m_device->device(), rp, nullptr); - vkCmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); - vkCmdEndRenderPass(m_commandBuffer->handle()); - m_commandBuffer->end(); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyNotFound(); - vkQueueWaitIdle(m_device->m_queue); -} - -TEST_F(VkLayerTest, InvalidCmdBufferDescriptorSetBufferDestroyed) { - TEST_DESCRIPTION( - "Attempt to draw with a command buffer that is invalid due to a bound descriptor set with a buffer dependency being " - "destroyed."); - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool; - VkResult err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 0; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding}); - - VkDescriptorSet descriptorSet; - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorSetCount = 1; - alloc_info.descriptorPool = ds_pool; - alloc_info.pSetLayouts = &ds_layout.handle(); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptorSet); - ASSERT_VK_SUCCESS(err); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds_layout}); - - // Create a buffer to update the descriptor with - uint32_t qfi = 0; - VkBufferCreateInfo buffCI = {}; - buffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffCI.size = 1024; - buffCI.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - buffCI.queueFamilyIndexCount = 1; - buffCI.pQueueFamilyIndices = &qfi; - - VkBuffer buffer; - err = vkCreateBuffer(m_device->device(), &buffCI, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - // Allocate memory and bind to buffer so we can make it to the appropriate - // error - VkMemoryRequirements memReqs; - vkGetBufferMemoryRequirements(m_device->device(), buffer, &memReqs); - VkMemoryAllocateInfo mem_alloc = {}; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.allocationSize = memReqs.size; - mem_alloc.memoryTypeIndex = 0; - bool pass = m_device->phy().set_memory_type(memReqs.memoryTypeBits, &mem_alloc, 0); - if (!pass) { - printf("%s Failed to set memory type.\n", kSkipPrefix); - vkDestroyBuffer(m_device->device(), buffer, NULL); - return; - } - - VkDeviceMemory mem; - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &mem); - ASSERT_VK_SUCCESS(err); - err = vkBindBufferMemory(m_device->device(), buffer, mem, 0); - ASSERT_VK_SUCCESS(err); - // Correctly update descriptor to avoid "NOT_UPDATED" error - VkDescriptorBufferInfo buffInfo = {}; - buffInfo.buffer = buffer; - buffInfo.offset = 0; - buffInfo.range = 1024; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = descriptorSet; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_write.pBufferInfo = &buffInfo; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - // Create PSO to be used for draw-time errors below - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 x;\n" - "layout(set=0) layout(binding=0) uniform foo { int x; int y; } bar;\n" - "void main(){\n" - " x = vec4(bar.y);\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptorSet, 0, NULL); - - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &m_viewports[0]); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &m_scissors[0]); - - m_commandBuffer->Draw(1, 0, 0, 0); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " that is invalid because bound Buffer "); - // Destroy buffer should invalidate the cmd buffer, causing error on submit - vkDestroyBuffer(m_device->device(), buffer, NULL); - // Attempt to submit cmd buffer - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - // Cleanup - vkFreeMemory(m_device->device(), mem, NULL); - - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); -} - -TEST_F(VkLayerTest, InvalidCmdBufferDescriptorSetImageSamplerDestroyed) { - TEST_DESCRIPTION( - "Attempt to draw with a command buffer that is invalid due to a bound descriptor sets with a combined image sampler having " - "their image, sampler, and descriptor set each respectively destroyed and then attempting to submit associated cmd " - "buffers. Attempt to destroy a DescriptorSet that is in use."); - ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool; - VkResult err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 0; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding}); - - VkDescriptorSet descriptorSet; - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorSetCount = 1; - alloc_info.descriptorPool = ds_pool; - alloc_info.pSetLayouts = &ds_layout.handle(); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptorSet); - ASSERT_VK_SUCCESS(err); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds_layout}); - - // Create images to update the descriptor with - VkImage image; - VkImage image2; - const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; - const int32_t tex_width = 32; - const int32_t tex_height = 32; - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = tex_format; - image_create_info.extent.width = tex_width; - image_create_info.extent.height = tex_height; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - image_create_info.flags = 0; - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - ASSERT_VK_SUCCESS(err); - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image2); - ASSERT_VK_SUCCESS(err); - - VkMemoryRequirements memory_reqs; - VkDeviceMemory image_memory; - bool pass; - VkMemoryAllocateInfo memory_info = {}; - memory_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_info.pNext = NULL; - memory_info.allocationSize = 0; - memory_info.memoryTypeIndex = 0; - vkGetImageMemoryRequirements(m_device->device(), image, &memory_reqs); - // Allocate enough memory for both images - VkDeviceSize align_mod = memory_reqs.size % memory_reqs.alignment; - VkDeviceSize aligned_size = ((align_mod == 0) ? memory_reqs.size : (memory_reqs.size + memory_reqs.alignment - align_mod)); - memory_info.allocationSize = aligned_size * 2; - pass = m_device->phy().set_memory_type(memory_reqs.memoryTypeBits, &memory_info, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(m_device->device(), &memory_info, NULL, &image_memory); - ASSERT_VK_SUCCESS(err); - err = vkBindImageMemory(m_device->device(), image, image_memory, 0); - ASSERT_VK_SUCCESS(err); - // Bind second image to memory right after first image - err = vkBindImageMemory(m_device->device(), image2, image_memory, aligned_size); - ASSERT_VK_SUCCESS(err); - - VkImageViewCreateInfo image_view_create_info = {}; - image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - image_view_create_info.image = image; - image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - image_view_create_info.format = tex_format; - image_view_create_info.subresourceRange.layerCount = 1; - image_view_create_info.subresourceRange.baseMipLevel = 0; - image_view_create_info.subresourceRange.levelCount = 1; - image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - VkImageView tmp_view; // First test deletes this view - VkImageView view; - VkImageView view2; - err = vkCreateImageView(m_device->device(), &image_view_create_info, NULL, &tmp_view); - ASSERT_VK_SUCCESS(err); - err = vkCreateImageView(m_device->device(), &image_view_create_info, NULL, &view); - ASSERT_VK_SUCCESS(err); - image_view_create_info.image = image2; - err = vkCreateImageView(m_device->device(), &image_view_create_info, NULL, &view2); - ASSERT_VK_SUCCESS(err); - // Create Samplers - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - VkSampler sampler; - VkSampler sampler2; - err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler); - ASSERT_VK_SUCCESS(err); - err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler2); - ASSERT_VK_SUCCESS(err); - // Update descriptor with image and sampler - VkDescriptorImageInfo img_info = {}; - img_info.sampler = sampler; - img_info.imageView = tmp_view; - img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = descriptorSet; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_write.pImageInfo = &img_info; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - // Create PSO to be used for draw-time errors below - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(set=0, binding=0) uniform sampler2D s;\n" - "layout(location=0) out vec4 x;\n" - "void main(){\n" - " x = texture(s, vec2(1));\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - // First error case is destroying sampler prior to cmd buffer submission - m_commandBuffer->begin(); - - // Transit image layout from VK_IMAGE_LAYOUT_UNDEFINED into VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL - VkImageMemoryBarrier barrier = {}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = image; - barrier.srcAccessMask = 0; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = 1; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 1, &barrier); - - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptorSet, 0, NULL); - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - m_commandBuffer->Draw(1, 0, 0, 0); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - // This first submit should be successful - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - vkQueueWaitIdle(m_device->m_queue); - - // Now destroy imageview and reset cmdBuffer - vkDestroyImageView(m_device->device(), tmp_view, NULL); - m_commandBuffer->reset(0); - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptorSet, 0, NULL); - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " that has been destroyed."); - m_commandBuffer->Draw(1, 0, 0, 0); - m_errorMonitor->VerifyFound(); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - - // Re-update descriptor with new view - img_info.imageView = view; - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - // Now test destroying sampler prior to cmd buffer submission - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptorSet, 0, NULL); - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - m_commandBuffer->Draw(1, 0, 0, 0); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - // Destroy sampler invalidates the cmd buffer, causing error on submit - vkDestroySampler(m_device->device(), sampler, NULL); - // Attempt to submit cmd buffer - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "that is invalid because bound Sampler"); - submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - - // Now re-update descriptor with valid sampler and delete image - img_info.sampler = sampler2; - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - VkCommandBufferBeginInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - info.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " that is invalid because bound Image "); - m_commandBuffer->begin(&info); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptorSet, 0, NULL); - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - m_commandBuffer->Draw(1, 0, 0, 0); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - // Destroy image invalidates the cmd buffer, causing error on submit - vkDestroyImage(m_device->device(), image, NULL); - // Attempt to submit cmd buffer - submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - // Now update descriptor to be valid, but then free descriptor - img_info.imageView = view2; - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_commandBuffer->begin(&info); - - // Transit image2 layout from VK_IMAGE_LAYOUT_UNDEFINED into VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL - barrier.image = image2; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 1, &barrier); - - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptorSet, 0, NULL); - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - m_commandBuffer->Draw(1, 0, 0, 0); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - - // Immediately try to destroy the descriptor set in the active command buffer - failure expected - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Cannot call vkFreeDescriptorSets() on descriptor set 0x"); - vkFreeDescriptorSets(m_device->device(), ds_pool, 1, &descriptorSet); - m_errorMonitor->VerifyFound(); - - // 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 valid 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 DescriptorSet obj"); - vkFreeDescriptorSets(m_device->device(), ds_pool, 1, &descriptorSet); - - // Attempt to submit cmd buffer containing the freed descriptor set - submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " that is invalid because bound DescriptorSet "); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - - // Cleanup - vkFreeMemory(m_device->device(), image_memory, NULL); - vkDestroySampler(m_device->device(), sampler2, NULL); - vkDestroyImage(m_device->device(), image2, NULL); - vkDestroyImageView(m_device->device(), view, NULL); - vkDestroyImageView(m_device->device(), view2, NULL); - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); -} - -TEST_F(VkLayerTest, InvalidDescriptorSetSamplerDestroyed) { - TEST_DESCRIPTION("Attempt to draw with a bound descriptor sets with a combined image sampler where sampler has been deleted."); - ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr}, - {1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - // Create images to update the descriptor with - VkImageObj image(m_device); - const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; - image.Init(32, 32, 1, tex_format, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - VkImageViewCreateInfo image_view_create_info = {}; - image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - image_view_create_info.image = image.handle(); - image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - image_view_create_info.format = tex_format; - image_view_create_info.subresourceRange.layerCount = 1; - image_view_create_info.subresourceRange.baseMipLevel = 0; - image_view_create_info.subresourceRange.levelCount = 1; - image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - VkImageView view; - VkResult err = vkCreateImageView(m_device->device(), &image_view_create_info, NULL, &view); - ASSERT_VK_SUCCESS(err); - // Create Samplers - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - VkSampler sampler; - err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler); - ASSERT_VK_SUCCESS(err); - VkSampler sampler1; - err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler1); - ASSERT_VK_SUCCESS(err); - // Update descriptor with image and sampler - VkDescriptorImageInfo img_info = {}; - img_info.sampler = sampler; - img_info.imageView = view; - img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkDescriptorImageInfo img_info1 = img_info; - img_info1.sampler = sampler1; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_write.pImageInfo = &img_info; - - std::array<VkWriteDescriptorSet, 2> descriptor_writes = {descriptor_write, descriptor_write}; - descriptor_writes[1].dstBinding = 1; - descriptor_writes[1].pImageInfo = &img_info1; - - vkUpdateDescriptorSets(m_device->device(), 2, descriptor_writes.data(), 0, NULL); - - // Destroy the sampler before it's bound to the cmd buffer - vkDestroySampler(m_device->device(), sampler1, NULL); - - // Create PSO to be used for draw-time errors below - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(set=0, binding=0) uniform sampler2D s;\n" - "layout(set=0, binding=1) uniform sampler2D s1;\n" - "layout(location=0) out vec4 x;\n" - "void main(){\n" - " x = texture(s, vec2(1));\n" - " x = texture(s1, vec2(1));\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - // First error case is destroying sampler prior to cmd buffer submission - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, &ds.set_, 0, - NULL); - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " Descriptor in binding #1 index 0 is using sampler "); - m_commandBuffer->Draw(1, 0, 0, 0); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - - vkDestroySampler(m_device->device(), sampler, NULL); - vkDestroyImageView(m_device->device(), view, NULL); -} - -TEST_F(VkLayerTest, ImageDescriptorLayoutMismatch) { - TEST_DESCRIPTION("Create an image sampler layout->image layout mismatch within/without a command buffer"); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - bool maint2_support = DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE2_EXTENSION_NAME); - if (maint2_support) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME); - } else { - printf("%s Relaxed layout matching subtest requires API >= 1.1 or KHR_MAINTENANCE2 extension, unavailable - skipped.\n", - kSkipPrefix); - } - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - VkDescriptorSet descriptorSet = ds.set_; - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - - // Create image, view, and sampler - const VkFormat format = VK_FORMAT_B8G8R8A8_UNORM; - VkImageObj image(m_device); - image.Init(32, 32, 1, format, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_TILING_OPTIMAL, - 0); - ASSERT_TRUE(image.initialized()); - - vk_testing::ImageView view; - auto image_view_create_info = SafeSaneImageViewCreateInfo(image, format, VK_IMAGE_ASPECT_COLOR_BIT); - view.init(*m_device, image_view_create_info); - ASSERT_TRUE(view.initialized()); - - // Create Sampler - vk_testing::Sampler sampler; - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - sampler.init(*m_device, sampler_ci); - ASSERT_TRUE(sampler.initialized()); - - // Setup structure for descriptor update with sampler, for update in do_test below - VkDescriptorImageInfo img_info = {}; - img_info.sampler = sampler.handle(); - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = descriptorSet; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_write.pImageInfo = &img_info; - - // Create PSO to be used for draw-time errors below - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(set=0, binding=0) uniform sampler2D s;\n" - "layout(location=0) out vec4 x;\n" - "void main(){\n" - " x = texture(s, vec2(1));\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - VkRect2D scissor = {{0, 0}, {16, 16}}; - - VkCommandBufferObj cmd_buf(m_device, m_commandPool); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &cmd_buf.handle(); - - enum TestType { - kInternal, // Image layout mismatch is *within* a given command buffer - kExternal // Image layout mismatch is with the current state of the image, found at QueueSubmit - }; - std::array<TestType, 2> test_list = {kInternal, kExternal}; - const std::vector<std::string> internal_errors = {"VUID-VkDescriptorImageInfo-imageLayout-00344", - "UNASSIGNED-CoreValidation-DrawState-DescriptorSetNotUpdated"}; - const std::vector<std::string> external_errors = {"UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout"}; - - // Common steps to create the two classes of errors (or two classes of positives) - auto do_test = [&](VkImageObj *image, vk_testing::ImageView *view, VkImageAspectFlags aspect_mask, VkImageLayout image_layout, - VkImageLayout descriptor_layout, const bool positive_test) { - // Set up the descriptor - img_info.imageView = view->handle(); - img_info.imageLayout = descriptor_layout; - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - for (TestType test_type : test_list) { - cmd_buf.begin(); - // record layout different than actual descriptor layout. - const VkFlags read_write = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; - auto image_barrier = image->image_memory_barrier(read_write, read_write, VK_IMAGE_LAYOUT_UNDEFINED, image_layout, - image->subresource_range(aspect_mask)); - cmd_buf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, 0, nullptr, 0, - nullptr, 1, &image_barrier); - - if (test_type == kExternal) { - // The image layout is external to the command buffer we are recording to test. Submit to push to instance scope. - cmd_buf.end(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - vkQueueWaitIdle(m_device->m_queue); - cmd_buf.begin(); - } - - cmd_buf.BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(cmd_buf.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(cmd_buf.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptorSet, 0, NULL); - vkCmdSetViewport(cmd_buf.handle(), 0, 1, &viewport); - vkCmdSetScissor(cmd_buf.handle(), 0, 1, &scissor); - - // At draw time the update layout will mis-match the actual layout - if (positive_test || (test_type == kExternal)) { - m_errorMonitor->ExpectSuccess(); - } else { - for (const auto &err : internal_errors) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, err.c_str()); - } - } - cmd_buf.Draw(1, 0, 0, 0); - if (positive_test || (test_type == kExternal)) { - m_errorMonitor->VerifyNotFound(); - } else { - m_errorMonitor->VerifyFound(); - } - - m_errorMonitor->ExpectSuccess(); - cmd_buf.EndRenderPass(); - cmd_buf.end(); - m_errorMonitor->VerifyNotFound(); - - // Submit cmd buffer - if (positive_test || (test_type == kInternal)) { - m_errorMonitor->ExpectSuccess(); - } else { - for (const auto &err : external_errors) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, err.c_str()); - } - } - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - vkQueueWaitIdle(m_device->m_queue); - if (positive_test || (test_type == kInternal)) { - m_errorMonitor->VerifyNotFound(); - } else { - m_errorMonitor->VerifyFound(); - } - } - }; - do_test(&image, &view, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, /* positive */ false); - - // Create depth stencil image and views - const VkFormat format_ds = m_depth_stencil_fmt = FindSupportedDepthStencilFormat(gpu()); - bool ds_test_support = maint2_support && (format_ds != VK_FORMAT_UNDEFINED); - VkImageObj image_ds(m_device); - vk_testing::ImageView stencil_view; - vk_testing::ImageView depth_view; - const VkImageLayout ds_image_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - const VkImageLayout depth_descriptor_layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL; - const VkImageLayout stencil_descriptor_layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL; - const VkImageAspectFlags depth_stencil = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - if (ds_test_support) { - image_ds.Init(32, 32, 1, format_ds, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image_ds.initialized()); - auto ds_view_ci = SafeSaneImageViewCreateInfo(image_ds, format_ds, VK_IMAGE_ASPECT_DEPTH_BIT); - depth_view.init(*m_device, ds_view_ci); - ds_view_ci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; - stencil_view.init(*m_device, ds_view_ci); - do_test(&image_ds, &depth_view, depth_stencil, ds_image_layout, depth_descriptor_layout, /* positive */ true); - do_test(&image_ds, &depth_view, depth_stencil, ds_image_layout, VK_IMAGE_LAYOUT_GENERAL, /* positive */ false); - do_test(&image_ds, &stencil_view, depth_stencil, ds_image_layout, stencil_descriptor_layout, /* positive */ true); - do_test(&image_ds, &stencil_view, depth_stencil, ds_image_layout, VK_IMAGE_LAYOUT_GENERAL, /* positive */ false); - } -} - -TEST_F(VkLayerTest, DescriptorPoolInUseDestroyedSignaled) { - TEST_DESCRIPTION("Delete a DescriptorPool with a DescriptorSet that is in use."); - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool; - VkResult err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 0; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding}); - - VkDescriptorSet descriptor_set; - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorSetCount = 1; - alloc_info.descriptorPool = ds_pool; - alloc_info.pSetLayouts = &ds_layout.handle(); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptor_set); - ASSERT_VK_SUCCESS(err); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds_layout}); - - // Create image to update the descriptor with - VkImageObj image(m_device); - image.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - VkImageView view = image.targetView(VK_FORMAT_B8G8R8A8_UNORM); - // Create Sampler - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - VkSampler sampler; - err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler); - ASSERT_VK_SUCCESS(err); - // Update descriptor with image and sampler - VkDescriptorImageInfo img_info = {}; - img_info.sampler = sampler; - img_info.imageView = view; - img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = descriptor_set; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_write.pImageInfo = &img_info; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - // Create PSO to be used for draw-time errors below - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(set=0, binding=0) uniform sampler2D s;\n" - "layout(location=0) out vec4 x;\n" - "void main(){\n" - " x = texture(s, vec2(1));\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptor_set, 0, NULL); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - - m_commandBuffer->Draw(1, 0, 0, 0); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - // Submit cmd buffer to put pool in-flight - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - // Destroy pool while in-flight, causing error - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkDestroyDescriptorPool-descriptorPool-00303"); - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); - m_errorMonitor->VerifyFound(); - vkQueueWaitIdle(m_device->m_queue); - // Cleanup - vkDestroySampler(m_device->device(), sampler, NULL); - m_errorMonitor->SetUnexpectedError( - "If descriptorPool is not VK_NULL_HANDLE, descriptorPool must be a valid VkDescriptorPool handle"); - m_errorMonitor->SetUnexpectedError("Unable to remove DescriptorPool obj"); - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); - // TODO : It seems Validation layers think ds_pool was already destroyed, even though it wasn't? -} - -TEST_F(VkLayerTest, DescriptorPoolInUseResetSignaled) { - TEST_DESCRIPTION("Reset a DescriptorPool with a DescriptorSet that is in use."); - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = nullptr; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool; - VkResult err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, nullptr, &ds_pool); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 0; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding.pImmutableSamplers = nullptr; - - const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding}); - - VkDescriptorSet descriptor_set; - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorSetCount = 1; - alloc_info.descriptorPool = ds_pool; - alloc_info.pSetLayouts = &ds_layout.handle(); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptor_set); - ASSERT_VK_SUCCESS(err); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds_layout}); - - // Create image to update the descriptor with - VkImageObj image(m_device); - image.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - VkImageView view = image.targetView(VK_FORMAT_B8G8R8A8_UNORM); - // Create Sampler - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - VkSampler sampler; - err = vkCreateSampler(m_device->device(), &sampler_ci, nullptr, &sampler); - ASSERT_VK_SUCCESS(err); - // Update descriptor with image and sampler - VkDescriptorImageInfo img_info = {}; - img_info.sampler = sampler; - img_info.imageView = view; - img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = descriptor_set; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_write.pImageInfo = &img_info; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, nullptr); - - // Create PSO to be used for draw-time errors below - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(set=0, binding=0) uniform sampler2D s;\n" - "layout(location=0) out vec4 x;\n" - "void main(){\n" - " x = texture(s, vec2(1));\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptor_set, 0, nullptr); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - - m_commandBuffer->Draw(1, 0, 0, 0); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - // Submit cmd buffer to put pool in-flight - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - // Reset pool while in-flight, causing error - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkResetDescriptorPool-descriptorPool-00313"); - vkResetDescriptorPool(m_device->device(), ds_pool, 0); - m_errorMonitor->VerifyFound(); - vkQueueWaitIdle(m_device->m_queue); - // Cleanup - vkDestroySampler(m_device->device(), sampler, nullptr); - m_errorMonitor->SetUnexpectedError( - "If descriptorPool is not VK_NULL_HANDLE, descriptorPool must be a valid VkDescriptorPool handle"); - m_errorMonitor->SetUnexpectedError("Unable to remove DescriptorPool obj"); - vkDestroyDescriptorPool(m_device->device(), ds_pool, nullptr); -} - -TEST_F(VkLayerTest, DescriptorImageUpdateNoMemoryBound) { - TEST_DESCRIPTION("Attempt an image descriptor set update where image's bound memory has been freed."); - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool; - VkResult err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 0; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding}); - - VkDescriptorSet descriptorSet; - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorSetCount = 1; - alloc_info.descriptorPool = ds_pool; - alloc_info.pSetLayouts = &ds_layout.handle(); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptorSet); - ASSERT_VK_SUCCESS(err); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds_layout}); - - // Create images to update the descriptor with - VkImage image; - const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; - const int32_t tex_width = 32; - const int32_t tex_height = 32; - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = tex_format; - image_create_info.extent.width = tex_width; - image_create_info.extent.height = tex_height; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - image_create_info.flags = 0; - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - ASSERT_VK_SUCCESS(err); - // Initially bind memory to avoid error at bind view time. We'll break binding before update. - VkMemoryRequirements memory_reqs; - VkDeviceMemory image_memory; - bool pass; - VkMemoryAllocateInfo memory_info = {}; - memory_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_info.pNext = NULL; - memory_info.allocationSize = 0; - memory_info.memoryTypeIndex = 0; - vkGetImageMemoryRequirements(m_device->device(), image, &memory_reqs); - // Allocate enough memory for image - memory_info.allocationSize = memory_reqs.size; - pass = m_device->phy().set_memory_type(memory_reqs.memoryTypeBits, &memory_info, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(m_device->device(), &memory_info, NULL, &image_memory); - ASSERT_VK_SUCCESS(err); - err = vkBindImageMemory(m_device->device(), image, image_memory, 0); - ASSERT_VK_SUCCESS(err); - - VkImageViewCreateInfo image_view_create_info = {}; - image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - image_view_create_info.image = image; - image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - image_view_create_info.format = tex_format; - image_view_create_info.subresourceRange.layerCount = 1; - image_view_create_info.subresourceRange.baseMipLevel = 0; - image_view_create_info.subresourceRange.levelCount = 1; - image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - VkImageView view; - err = vkCreateImageView(m_device->device(), &image_view_create_info, NULL, &view); - ASSERT_VK_SUCCESS(err); - // Create Samplers - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - VkSampler sampler; - err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler); - ASSERT_VK_SUCCESS(err); - // Update descriptor with image and sampler - VkDescriptorImageInfo img_info = {}; - img_info.sampler = sampler; - img_info.imageView = view; - img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = descriptorSet; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_write.pImageInfo = &img_info; - // Break memory binding and attempt update - vkFreeMemory(m_device->device(), image_memory, nullptr); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - " previously bound memory was freed. Memory must not be freed prior to this operation."); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkUpdateDescriptorSets() failed write update validation for Descriptor Set 0x"); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - // Cleanup - vkDestroyImage(m_device->device(), image, NULL); - vkDestroySampler(m_device->device(), sampler, NULL); - vkDestroyImageView(m_device->device(), view, NULL); - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); -} - -TEST_F(VkLayerTest, InvalidPipeline) { - uint64_t fake_pipeline_handle = 0xbaad6001; - VkPipeline bad_pipeline = reinterpret_cast<VkPipeline &>(fake_pipeline_handle); - - // Enable VK_KHR_draw_indirect_count for KHR variants - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME); - } - ASSERT_NO_FATAL_FAILURE(InitState()); - bool has_khr_indirect = DeviceExtensionEnabled(VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Attempt to bind an invalid Pipeline to a valid Command Buffer - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindPipeline-pipeline-parameter"); - m_commandBuffer->begin(); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, bad_pipeline); - m_errorMonitor->VerifyFound(); - - // Try each of the 6 flavors of Draw() - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); // Draw*() calls must be submitted within a renderpass - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDraw-None-02700"); - m_commandBuffer->Draw(1, 0, 0, 0); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndexed-None-02700"); - m_commandBuffer->DrawIndexed(1, 1, 0, 0, 0); - m_errorMonitor->VerifyFound(); - - VkBufferObj buffer; - VkBufferCreateInfo ci = {}; - ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - ci.usage = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; - ci.size = 1024; - buffer.init(*m_device, ci); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndirect-None-02700"); - vkCmdDrawIndirect(m_commandBuffer->handle(), buffer.handle(), 0, 1, 0); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndexedIndirect-None-02700"); - vkCmdDrawIndexedIndirect(m_commandBuffer->handle(), buffer.handle(), 0, 1, 0); - m_errorMonitor->VerifyFound(); - - if (has_khr_indirect) { - auto fpCmdDrawIndirectCountKHR = - (PFN_vkCmdDrawIndirectCountKHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdDrawIndirectCountKHR"); - ASSERT_NE(fpCmdDrawIndirectCountKHR, nullptr); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndirectCountKHR-None-02700"); - // stride must be a multiple of 4 and must be greater than or equal to sizeof(VkDrawIndirectCommand) - fpCmdDrawIndirectCountKHR(m_commandBuffer->handle(), buffer.handle(), 0, buffer.handle(), 512, 1, 512); - m_errorMonitor->VerifyFound(); - - auto fpCmdDrawIndexedIndirectCountKHR = - (PFN_vkCmdDrawIndexedIndirectCountKHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdDrawIndexedIndirectCountKHR"); - ASSERT_NE(fpCmdDrawIndexedIndirectCountKHR, nullptr); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndexedIndirectCountKHR-None-02700"); - // stride must be a multiple of 4 and must be greater than or equal to sizeof(VkDrawIndexedIndirectCommand) - fpCmdDrawIndexedIndirectCountKHR(m_commandBuffer->handle(), buffer.handle(), 0, buffer.handle(), 512, 1, 512); - m_errorMonitor->VerifyFound(); - } - - // Also try the Dispatch variants - vkCmdEndRenderPass(m_commandBuffer->handle()); // Compute submissions must be outside a renderpass - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatch-None-02700"); - vkCmdDispatch(m_commandBuffer->handle(), 0, 0, 0); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatchIndirect-None-02700"); - vkCmdDispatchIndirect(m_commandBuffer->handle(), buffer.handle(), 0); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CmdDispatchExceedLimits) { - TEST_DESCRIPTION("Compute dispatch with dimensions that exceed device limits"); - - // Enable KHX device group extensions, if available - if (InstanceExtensionSupported(VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME); - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - bool khx_dg_ext_available = false; - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_DEVICE_GROUP_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_DEVICE_GROUP_EXTENSION_NAME); - khx_dg_ext_available = true; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - uint32_t x_count_limit = m_device->props.limits.maxComputeWorkGroupCount[0]; - uint32_t y_count_limit = m_device->props.limits.maxComputeWorkGroupCount[1]; - uint32_t z_count_limit = m_device->props.limits.maxComputeWorkGroupCount[2]; - if (std::max({x_count_limit, y_count_limit, z_count_limit}) == UINT32_MAX) { - printf("%s device maxComputeWorkGroupCount limit reports UINT32_MAX, test not possible, skipping.\n", kSkipPrefix); - return; - } - - uint32_t x_size_limit = m_device->props.limits.maxComputeWorkGroupSize[0]; - uint32_t y_size_limit = m_device->props.limits.maxComputeWorkGroupSize[1]; - uint32_t z_size_limit = m_device->props.limits.maxComputeWorkGroupSize[2]; - - std::string spv_source = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize )"; - spv_source.append(std::to_string(x_size_limit + 1) + " " + std::to_string(y_size_limit + 1) + " " + - std::to_string(z_size_limit + 1)); - spv_source.append(R"( - %void = OpTypeVoid - %3 = OpTypeFunction %void - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd)"); - - VkShaderObj cs_obj_asm(m_device, spv_source, VK_SHADER_STAGE_COMPUTE_BIT, this); - - VkPipelineLayoutCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - info.pNext = nullptr; - VkPipelineLayout pipe_layout; - vkCreatePipelineLayout(device(), &info, nullptr, &pipe_layout); - - VkComputePipelineCreateInfo pipeline_info = {}; - pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; - pipeline_info.pNext = nullptr; - pipeline_info.flags = khx_dg_ext_available ? VK_PIPELINE_CREATE_DISPATCH_BASE_KHR : 0; - pipeline_info.layout = pipe_layout; - pipeline_info.basePipelineHandle = VK_NULL_HANDLE; - pipeline_info.basePipelineIndex = -1; - pipeline_info.stage = cs_obj_asm.GetStageCreateInfo(); - VkPipeline cs_pipeline; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "exceeds device limit maxComputeWorkGroupSize[0]"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "exceeds device limit maxComputeWorkGroupSize[1]"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "exceeds device limit maxComputeWorkGroupSize[2]"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "features-limits-maxComputeWorkGroupInvocations"); - vkCreateComputePipelines(device(), VK_NULL_HANDLE, 1, &pipeline_info, nullptr, &cs_pipeline); - m_errorMonitor->VerifyFound(); - - // Create a minimal compute pipeline - x_size_limit = (x_size_limit > 1024) ? 1024 : x_size_limit; - y_size_limit = (y_size_limit > 1024) ? 1024 : y_size_limit; - z_size_limit = (z_size_limit > 64) ? 64 : z_size_limit; - - uint32_t invocations_limit = m_device->props.limits.maxComputeWorkGroupInvocations; - x_size_limit = (x_size_limit > invocations_limit) ? invocations_limit : x_size_limit; - invocations_limit /= x_size_limit; - y_size_limit = (y_size_limit > invocations_limit) ? invocations_limit : y_size_limit; - invocations_limit /= y_size_limit; - z_size_limit = (z_size_limit > invocations_limit) ? invocations_limit : z_size_limit; - - char cs_text[128] = ""; - sprintf(cs_text, "#version 450\nlayout(local_size_x = %d, local_size_y = %d, local_size_z = %d) in;\nvoid main() {}\n", - x_size_limit, y_size_limit, z_size_limit); - - VkShaderObj cs_obj(m_device, cs_text, VK_SHADER_STAGE_COMPUTE_BIT, this); - pipeline_info.stage = cs_obj.GetStageCreateInfo(); - vkCreateComputePipelines(device(), VK_NULL_HANDLE, 1, &pipeline_info, nullptr, &cs_pipeline); - - // Bind pipeline to command buffer - m_commandBuffer->begin(); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_COMPUTE, cs_pipeline); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "features-limits-maxComputeWorkGroupInvocations"); - vkCmdDispatch(m_commandBuffer->handle(), x_count_limit, y_count_limit, z_count_limit); - m_errorMonitor->VerifyFound(); - - // Dispatch counts that exceed device limits - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatch-groupCountX-00386"); - vkCmdDispatch(m_commandBuffer->handle(), x_count_limit + 1, y_count_limit, z_count_limit); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatch-groupCountY-00387"); - vkCmdDispatch(m_commandBuffer->handle(), x_count_limit, y_count_limit + 1, z_count_limit); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatch-groupCountZ-00388"); - vkCmdDispatch(m_commandBuffer->handle(), x_count_limit, y_count_limit, z_count_limit + 1); - m_errorMonitor->VerifyFound(); - - if (khx_dg_ext_available) { - PFN_vkCmdDispatchBaseKHR fp_vkCmdDispatchBaseKHR = - (PFN_vkCmdDispatchBaseKHR)vkGetInstanceProcAddr(instance(), "vkCmdDispatchBaseKHR"); - - // Base equals or exceeds limit - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatchBase-baseGroupX-00421"); - fp_vkCmdDispatchBaseKHR(m_commandBuffer->handle(), x_count_limit, y_count_limit - 1, z_count_limit - 1, 0, 0, 0); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatchBase-baseGroupX-00422"); - fp_vkCmdDispatchBaseKHR(m_commandBuffer->handle(), x_count_limit - 1, y_count_limit, z_count_limit - 1, 0, 0, 0); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatchBase-baseGroupZ-00423"); - fp_vkCmdDispatchBaseKHR(m_commandBuffer->handle(), x_count_limit - 1, y_count_limit - 1, z_count_limit, 0, 0, 0); - m_errorMonitor->VerifyFound(); - - // (Base + count) exceeds limit - uint32_t x_base = x_count_limit / 2; - uint32_t y_base = y_count_limit / 2; - uint32_t z_base = z_count_limit / 2; - x_count_limit -= x_base; - y_count_limit -= y_base; - z_count_limit -= z_base; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatchBase-groupCountX-00424"); - fp_vkCmdDispatchBaseKHR(m_commandBuffer->handle(), x_base, y_base, z_base, x_count_limit + 1, y_count_limit, z_count_limit); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatchBase-groupCountY-00425"); - fp_vkCmdDispatchBaseKHR(m_commandBuffer->handle(), x_base, y_base, z_base, x_count_limit, y_count_limit + 1, z_count_limit); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatchBase-groupCountZ-00426"); - fp_vkCmdDispatchBaseKHR(m_commandBuffer->handle(), x_base, y_base, z_base, x_count_limit, y_count_limit, z_count_limit + 1); - m_errorMonitor->VerifyFound(); - } else { - printf("%s KHX_DEVICE_GROUP_* extensions not supported, skipping CmdDispatchBaseKHR() tests.\n", kSkipPrefix); - } - - // Clean up - vkDestroyPipeline(device(), cs_pipeline, nullptr); - vkDestroyPipelineLayout(device(), pipe_layout, nullptr); -} - -TEST_F(VkLayerTest, MultiplaneImageLayoutBadAspectFlags) { - TEST_DESCRIPTION("Query layout of a multiplane image using illegal aspect flag masks"); - - // Enable KHR multiplane req'd extensions - bool mp_extensions = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, - VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION); - if (mp_extensions) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - if (mp_extensions) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - } else { - printf("%s test requires KHR multiplane extensions, not available. Skipping.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkImageCreateInfo ci = {}; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_2D; - ci.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR; - ci.extent = {128, 128, 1}; - ci.mipLevels = 1; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.tiling = VK_IMAGE_TILING_LINEAR; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - // Verify formats - bool supported = ImageFormatAndFeaturesSupported(instance(), gpu(), ci, VK_FORMAT_FEATURE_TRANSFER_SRC_BIT); - ci.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR; - supported = supported && ImageFormatAndFeaturesSupported(instance(), gpu(), ci, VK_FORMAT_FEATURE_TRANSFER_SRC_BIT); - if (!supported) { - printf("%s Multiplane image format not supported. Skipping test.\n", kSkipPrefix); - return; // Assume there's low ROI on searching for different mp formats - } - - VkImage image_2plane, image_3plane; - ci.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR; - VkResult err = vkCreateImage(device(), &ci, NULL, &image_2plane); - ASSERT_VK_SUCCESS(err); - - ci.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR; - err = vkCreateImage(device(), &ci, NULL, &image_3plane); - ASSERT_VK_SUCCESS(err); - - // Query layout of 3rd plane, for a 2-plane image - VkImageSubresource subres = {}; - subres.aspectMask = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR; - subres.mipLevel = 0; - subres.arrayLayer = 0; - VkSubresourceLayout layout = {}; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkGetImageSubresourceLayout-format-01581"); - vkGetImageSubresourceLayout(device(), image_2plane, &subres, &layout); - m_errorMonitor->VerifyFound(); - - // Query layout using color aspect, for a 3-plane image - subres.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkGetImageSubresourceLayout-format-01582"); - vkGetImageSubresourceLayout(device(), image_3plane, &subres, &layout); - m_errorMonitor->VerifyFound(); - - // Clean up - vkDestroyImage(device(), image_2plane, NULL); - vkDestroyImage(device(), image_3plane, NULL); -} - -TEST_F(VkPositiveLayerTest, MultiplaneGetImageSubresourceLayout) { - TEST_DESCRIPTION("Positive test, query layout of a single plane of a multiplane image. (repro Github #2530)"); - - // Enable KHR multiplane req'd extensions - bool mp_extensions = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, - VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION); - if (mp_extensions) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - if (mp_extensions) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - } else { - printf("%s test requires KHR multiplane extensions, not available. Skipping.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkImageCreateInfo ci = {}; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_2D; - ci.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR; - ci.extent = {128, 128, 1}; - ci.mipLevels = 1; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.tiling = VK_IMAGE_TILING_LINEAR; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - // Verify format - bool supported = ImageFormatAndFeaturesSupported(instance(), gpu(), ci, VK_FORMAT_FEATURE_TRANSFER_SRC_BIT); - if (!supported) { - printf("%s Multiplane image format not supported. Skipping test.\n", kSkipPrefix); - return; // Assume there's low ROI on searching for different mp formats - } - - VkImage image; - VkResult err = vkCreateImage(device(), &ci, NULL, &image); - ASSERT_VK_SUCCESS(err); - - // Query layout of 3rd plane - VkImageSubresource subres = {}; - subres.aspectMask = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR; - subres.mipLevel = 0; - subres.arrayLayer = 0; - VkSubresourceLayout layout = {}; - - m_errorMonitor->ExpectSuccess(); - vkGetImageSubresourceLayout(device(), image, &subres, &layout); - m_errorMonitor->VerifyNotFound(); - - vkDestroyImage(device(), image, NULL); -} - -TEST_F(VkLayerTest, InvalidBufferViewObject) { - // Create a single TEXEL_BUFFER descriptor and send it an invalid bufferView - // First, cause the bufferView to be invalid due to underlying buffer being destroyed - // Then destroy view itself and verify that same error is hit - VkResult err; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-00323"); - ASSERT_NO_FATAL_FAILURE(Init()); - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool; - err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 0; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding}); - - VkDescriptorSet descriptorSet; - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorSetCount = 1; - alloc_info.descriptorPool = ds_pool; - alloc_info.pSetLayouts = &ds_layout.handle(); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptorSet); - ASSERT_VK_SUCCESS(err); - - // Create a valid bufferView to start with - VkBuffer buffer; - uint32_t queue_family_index = 0; - VkBufferCreateInfo buffer_create_info = {}; - buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_create_info.size = 1024; - buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; - buffer_create_info.queueFamilyIndexCount = 1; - buffer_create_info.pQueueFamilyIndices = &queue_family_index; - - err = vkCreateBuffer(m_device->device(), &buffer_create_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - VkMemoryRequirements memory_reqs; - VkDeviceMemory buffer_memory; - - VkMemoryAllocateInfo memory_info = {}; - memory_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_info.allocationSize = 0; - memory_info.memoryTypeIndex = 0; - - vkGetBufferMemoryRequirements(m_device->device(), buffer, &memory_reqs); - memory_info.allocationSize = memory_reqs.size; - bool pass = m_device->phy().set_memory_type(memory_reqs.memoryTypeBits, &memory_info, 0); - ASSERT_TRUE(pass); - - err = vkAllocateMemory(m_device->device(), &memory_info, NULL, &buffer_memory); - ASSERT_VK_SUCCESS(err); - err = vkBindBufferMemory(m_device->device(), buffer, buffer_memory, 0); - ASSERT_VK_SUCCESS(err); - - VkBufferView view; - VkBufferViewCreateInfo bvci = {}; - bvci.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; - bvci.buffer = buffer; - bvci.format = VK_FORMAT_R32_SFLOAT; - bvci.range = VK_WHOLE_SIZE; - - err = vkCreateBufferView(m_device->device(), &bvci, NULL, &view); - ASSERT_VK_SUCCESS(err); - - // First Destroy buffer underlying view which should hit error in CV - vkDestroyBuffer(m_device->device(), buffer, NULL); - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = descriptorSet; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - descriptor_write.pTexelBufferView = &view; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - - // Now destroy view itself and verify same error, which is hit in PV this time - vkDestroyBufferView(m_device->device(), view, NULL); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-00323"); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - vkFreeMemory(m_device->device(), buffer_memory, NULL); - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); -} - -TEST_F(VkLayerTest, CreateBufferViewNoMemoryBoundToBuffer) { - TEST_DESCRIPTION("Attempt to create a buffer view with a buffer that has no memory bound to it."); - - VkResult err; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - " used with no memory bound. Memory should be bound by calling vkBindBufferMemory()."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // Create a buffer with no bound memory and then attempt to create - // a buffer view. - VkBufferCreateInfo buff_ci = {}; - buff_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buff_ci.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; - buff_ci.size = 256; - buff_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VkBuffer buffer; - err = vkCreateBuffer(m_device->device(), &buff_ci, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - VkBufferViewCreateInfo buff_view_ci = {}; - buff_view_ci.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; - buff_view_ci.buffer = buffer; - buff_view_ci.format = VK_FORMAT_R8_UNORM; - buff_view_ci.range = VK_WHOLE_SIZE; - VkBufferView buff_view; - err = vkCreateBufferView(m_device->device(), &buff_view_ci, NULL, &buff_view); - - m_errorMonitor->VerifyFound(); - vkDestroyBuffer(m_device->device(), buffer, NULL); - // If last error is success, it still created the view, so delete it. - if (err == VK_SUCCESS) { - vkDestroyBufferView(m_device->device(), buff_view, NULL); - } -} - -TEST_F(VkLayerTest, InvalidBufferViewCreateInfoEntries) { - TEST_DESCRIPTION("Attempt to create a buffer view with invalid create info."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - const VkPhysicalDeviceLimits &dev_limits = m_device->props.limits; - const VkDeviceSize minTexelBufferOffsetAlignment = dev_limits.minTexelBufferOffsetAlignment; - if (minTexelBufferOffsetAlignment == 1) { - printf("%s Test requires minTexelOffsetAlignment to not be equal to 1. \n", kSkipPrefix); - return; - } - - const VkFormat format_with_uniform_texel_support = VK_FORMAT_R8G8B8A8_UNORM; - const char *format_with_uniform_texel_support_string = "VK_FORMAT_R8G8B8A8_UNORM"; - const VkFormat format_without_texel_support = VK_FORMAT_R8G8B8_UNORM; - const char *format_without_texel_support_string = "VK_FORMAT_R8G8B8_UNORM"; - VkFormatProperties format_properties; - vkGetPhysicalDeviceFormatProperties(gpu(), format_with_uniform_texel_support, &format_properties); - if (!(format_properties.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)) { - printf("%s Test requires %s to support VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT\n", kSkipPrefix, - format_with_uniform_texel_support_string); - return; - } - vkGetPhysicalDeviceFormatProperties(gpu(), format_without_texel_support, &format_properties); - if ((format_properties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) || - (format_properties.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)) { - printf( - "%s Test requires %s to not support VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT nor " - "VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT\n", - kSkipPrefix, format_without_texel_support_string); - return; - } - - // Create a test buffer--buffer must have been created using VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT or - // VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, so use a different usage value instead to cause an error - const VkDeviceSize resource_size = 1024; - const VkBufferCreateInfo bad_buffer_info = VkBufferObj::create_info(resource_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); - VkBufferObj bad_buffer; - bad_buffer.init(*m_device, bad_buffer_info, (VkMemoryPropertyFlags)VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - // Create a test buffer view - VkBufferViewCreateInfo buff_view_ci = {}; - buff_view_ci.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; - buff_view_ci.buffer = bad_buffer.handle(); - buff_view_ci.format = format_with_uniform_texel_support; - buff_view_ci.range = VK_WHOLE_SIZE; - - auto CatchError = [this, &buff_view_ci](const string &desired_error_string) { - VkBufferView buff_view; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, desired_error_string); - VkResult err = vkCreateBufferView(m_device->device(), &buff_view_ci, NULL, &buff_view); - m_errorMonitor->VerifyFound(); - // If previous error is success, it still created the view, so delete it - if (err == VK_SUCCESS) { - vkDestroyBufferView(m_device->device(), buff_view, NULL); - } - }; - - CatchError("VUID-VkBufferViewCreateInfo-buffer-00932"); - - // Create a better test buffer - const VkBufferCreateInfo buffer_info = VkBufferObj::create_info(resource_size, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT); - VkBufferObj buffer; - buffer.init(*m_device, buffer_info, (VkMemoryPropertyFlags)VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - // Offset must be less than the size of the buffer, so set it equal to the buffer size to cause an error - buff_view_ci.buffer = buffer.handle(); - buff_view_ci.offset = buffer.create_info().size; - CatchError("VUID-VkBufferViewCreateInfo-offset-00925"); - - // Offset must be a multiple of VkPhysicalDeviceLimits::minTexelBufferOffsetAlignment so add 1 to ensure it is not - buff_view_ci.offset = minTexelBufferOffsetAlignment + 1; - CatchError("VUID-VkBufferViewCreateInfo-offset-00926"); - - // Set offset to acceptable value for range tests - buff_view_ci.offset = minTexelBufferOffsetAlignment; - // Setting range equal to 0 will cause an error to occur - buff_view_ci.range = 0; - CatchError("VUID-VkBufferViewCreateInfo-range-00928"); - - uint32_t format_size = FormatElementSize(buff_view_ci.format); - // Range must be a multiple of the element size of format, so add one to ensure it is not - buff_view_ci.range = format_size + 1; - CatchError("VUID-VkBufferViewCreateInfo-range-00929"); - - // Twice the element size of format multiplied by VkPhysicalDeviceLimits::maxTexelBufferElements guarantees range divided by the - // element size is greater than maxTexelBufferElements, causing failure - buff_view_ci.range = 2 * format_size * dev_limits.maxTexelBufferElements; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferViewCreateInfo-range-00930"); - CatchError("VUID-VkBufferViewCreateInfo-offset-00931"); - - // Set rage to acceptable value for buffer tests - buff_view_ci.format = format_without_texel_support; - buff_view_ci.range = VK_WHOLE_SIZE; - - // `buffer` was created using VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT so we can use that for the first buffer test - CatchError("VUID-VkBufferViewCreateInfo-buffer-00933"); - - // Create a new buffer using VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT - const VkBufferCreateInfo storage_buffer_info = - VkBufferObj::create_info(resource_size, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT); - VkBufferObj storage_buffer; - storage_buffer.init(*m_device, storage_buffer_info, (VkMemoryPropertyFlags)VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - buff_view_ci.buffer = storage_buffer.handle(); - CatchError("VUID-VkBufferViewCreateInfo-buffer-00934"); -} - -TEST_F(VkLayerTest, InvalidDynamicOffsetCases) { - // Create a descriptorSet w/ dynamic descriptor and then hit 3 offset error - // cases: - // 1. No dynamicOffset supplied - // 2. Too many dynamicOffsets supplied - // 3. Dynamic offset oversteps buffer being updated - VkResult err; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - " requires 1 dynamicOffsets, but only 0 dynamicOffsets are left in pDynamicOffsets "); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool; - err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 0; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding}); - - VkDescriptorSet descriptorSet; - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorSetCount = 1; - alloc_info.descriptorPool = ds_pool; - alloc_info.pSetLayouts = &ds_layout.handle(); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptorSet); - ASSERT_VK_SUCCESS(err); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds_layout}); - - // Create a buffer to update the descriptor with - uint32_t qfi = 0; - VkBufferCreateInfo buffCI = {}; - buffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffCI.size = 1024; - buffCI.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - buffCI.queueFamilyIndexCount = 1; - buffCI.pQueueFamilyIndices = &qfi; - - VkBuffer dyub; - err = vkCreateBuffer(m_device->device(), &buffCI, NULL, &dyub); - ASSERT_VK_SUCCESS(err); - // Allocate memory and bind to buffer so we can make it to the appropriate error - VkMemoryRequirements memReqs; - vkGetBufferMemoryRequirements(m_device->device(), dyub, &memReqs); - VkMemoryAllocateInfo mem_alloc = {}; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.allocationSize = memReqs.size; - mem_alloc.memoryTypeIndex = 0; - bool pass = m_device->phy().set_memory_type(memReqs.memoryTypeBits, &mem_alloc, 0); - if (!pass) { - printf("%s Failed to allocate memory.\n", kSkipPrefix); - vkDestroyBuffer(m_device->device(), dyub, NULL); - return; - } - - VkDeviceMemory mem; - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &mem); - ASSERT_VK_SUCCESS(err); - err = vkBindBufferMemory(m_device->device(), dyub, mem, 0); - ASSERT_VK_SUCCESS(err); - // Correctly update descriptor to avoid "NOT_UPDATED" error - VkDescriptorBufferInfo buffInfo = {}; - buffInfo.buffer = dyub; - buffInfo.offset = 0; - buffInfo.range = 1024; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = descriptorSet; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - descriptor_write.pBufferInfo = &buffInfo; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptorSet, 0, NULL); - m_errorMonitor->VerifyFound(); - uint32_t pDynOff[2] = {512, 756}; - // Now cause error b/c too many dynOffsets in array for # of dyn descriptors - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Attempting to bind 1 descriptorSets with 1 dynamic descriptors, but "); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptorSet, 2, pDynOff); - m_errorMonitor->VerifyFound(); - // Finally cause error due to dynamicOffset being too big - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - " dynamic offset 512 combined with offset 0 and range 1024 that oversteps the buffer size of 1024"); - // Create PSO to be used for draw-time errors below - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 x;\n" - "layout(set=0) layout(binding=0) uniform foo { int x; int y; } bar;\n" - "void main(){\n" - " x = vec4(bar.y);\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - // This update should succeed, but offset size of 512 will overstep buffer - // /w range 1024 & size 1024 - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptorSet, 1, pDynOff); - m_commandBuffer->Draw(1, 0, 0, 0); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - - vkDestroyBuffer(m_device->device(), dyub, NULL); - vkFreeMemory(m_device->device(), mem, NULL); - - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); -} - -TEST_F(VkLayerTest, DescriptorBufferUpdateNoMemoryBound) { - TEST_DESCRIPTION("Attempt to update a descriptor with a non-sparse buffer that doesn't have memory bound"); - VkResult err; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - " used with no memory bound. Memory should be bound by calling vkBindBufferMemory()."); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkUpdateDescriptorSets() failed write update validation for Descriptor Set 0x"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool; - err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 0; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding}); - - VkDescriptorSet descriptorSet; - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorSetCount = 1; - alloc_info.descriptorPool = ds_pool; - alloc_info.pSetLayouts = &ds_layout.handle(); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptorSet); - ASSERT_VK_SUCCESS(err); - - // Create a buffer to update the descriptor with - uint32_t qfi = 0; - VkBufferCreateInfo buffCI = {}; - buffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffCI.size = 1024; - buffCI.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - buffCI.queueFamilyIndexCount = 1; - buffCI.pQueueFamilyIndices = &qfi; - - VkBuffer dyub; - err = vkCreateBuffer(m_device->device(), &buffCI, NULL, &dyub); - ASSERT_VK_SUCCESS(err); - - // Attempt to update descriptor without binding memory to it - VkDescriptorBufferInfo buffInfo = {}; - buffInfo.buffer = dyub; - buffInfo.offset = 0; - buffInfo.range = 1024; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = descriptorSet; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - descriptor_write.pBufferInfo = &buffInfo; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - - vkDestroyBuffer(m_device->device(), dyub, NULL); - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); -} - -TEST_F(VkLayerTest, InvalidPushConstants) { - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkPipelineLayout pipeline_layout; - VkPushConstantRange pc_range = {}; - VkPipelineLayoutCreateInfo pipeline_layout_ci = {}; - pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_ci.pushConstantRangeCount = 1; - pipeline_layout_ci.pPushConstantRanges = &pc_range; - - // - // Check for invalid push constant ranges in pipeline layouts. - // - struct PipelineLayoutTestCase { - VkPushConstantRange const range; - char const *msg; - }; - - const uint32_t too_big = m_device->props.limits.maxPushConstantsSize + 0x4; - const std::array<PipelineLayoutTestCase, 10> range_tests = {{ - {{VK_SHADER_STAGE_VERTEX_BIT, 0, 0}, "vkCreatePipelineLayout() call has push constants index 0 with size 0."}, - {{VK_SHADER_STAGE_VERTEX_BIT, 0, 1}, "vkCreatePipelineLayout() call has push constants index 0 with size 1."}, - {{VK_SHADER_STAGE_VERTEX_BIT, 4, 1}, "vkCreatePipelineLayout() call has push constants index 0 with size 1."}, - {{VK_SHADER_STAGE_VERTEX_BIT, 4, 0}, "vkCreatePipelineLayout() call has push constants index 0 with size 0."}, - {{VK_SHADER_STAGE_VERTEX_BIT, 1, 4}, "vkCreatePipelineLayout() call has push constants index 0 with offset 1. Offset must"}, - {{VK_SHADER_STAGE_VERTEX_BIT, 0, too_big}, "vkCreatePipelineLayout() call has push constants index 0 with offset "}, - {{VK_SHADER_STAGE_VERTEX_BIT, too_big, too_big}, "vkCreatePipelineLayout() call has push constants index 0 with offset "}, - {{VK_SHADER_STAGE_VERTEX_BIT, too_big, 4}, "vkCreatePipelineLayout() call has push constants index 0 with offset "}, - {{VK_SHADER_STAGE_VERTEX_BIT, 0xFFFFFFF0, 0x00000020}, - "vkCreatePipelineLayout() call has push constants index 0 with offset "}, - {{VK_SHADER_STAGE_VERTEX_BIT, 0x00000020, 0xFFFFFFF0}, - "vkCreatePipelineLayout() call has push constants index 0 with offset "}, - }}; - - // Check for invalid offset and size - for (const auto &iter : range_tests) { - pc_range = iter.range; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, iter.msg); - vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - } - - // Check for invalid stage flag - pc_range.offset = 0; - pc_range.size = 16; - pc_range.stageFlags = 0; - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkCreatePipelineLayout: value of pCreateInfo->pPushConstantRanges[0].stageFlags must not be 0"); - vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - - // Check for duplicate stage flags in a list of push constant ranges. - // A shader can only have one push constant block and that block is mapped - // to the push constant range that has that shader's stage flag set. - // The shader's stage flag can only appear once in all the ranges, so the - // implementation can find the one and only range to map it to. - const uint32_t ranges_per_test = 5; - struct DuplicateStageFlagsTestCase { - VkPushConstantRange const ranges[ranges_per_test]; - std::vector<char const *> const msg; - }; - // Overlapping ranges are OK, but a stage flag can appear only once. - const std::array<DuplicateStageFlagsTestCase, 3> duplicate_stageFlags_tests = { - { - {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 4}, - {VK_SHADER_STAGE_VERTEX_BIT, 0, 4}, - {VK_SHADER_STAGE_VERTEX_BIT, 0, 4}, - {VK_SHADER_STAGE_VERTEX_BIT, 0, 4}, - {VK_SHADER_STAGE_VERTEX_BIT, 0, 4}}, - { - "vkCreatePipelineLayout() Duplicate stage flags found in ranges 0 and 1.", - "vkCreatePipelineLayout() Duplicate stage flags found in ranges 0 and 2.", - "vkCreatePipelineLayout() Duplicate stage flags found in ranges 0 and 3.", - "vkCreatePipelineLayout() Duplicate stage flags found in ranges 0 and 4.", - "vkCreatePipelineLayout() Duplicate stage flags found in ranges 1 and 2.", - "vkCreatePipelineLayout() Duplicate stage flags found in ranges 1 and 3.", - "vkCreatePipelineLayout() Duplicate stage flags found in ranges 1 and 4.", - "vkCreatePipelineLayout() Duplicate stage flags found in ranges 2 and 3.", - "vkCreatePipelineLayout() Duplicate stage flags found in ranges 2 and 4.", - "vkCreatePipelineLayout() Duplicate stage flags found in ranges 3 and 4.", - }}, - {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 4}, - {VK_SHADER_STAGE_GEOMETRY_BIT, 0, 4}, - {VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4}, - {VK_SHADER_STAGE_VERTEX_BIT, 0, 4}, - {VK_SHADER_STAGE_GEOMETRY_BIT, 0, 4}}, - { - "vkCreatePipelineLayout() Duplicate stage flags found in ranges 0 and 3.", - "vkCreatePipelineLayout() Duplicate stage flags found in ranges 1 and 4.", - }}, - {{{VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4}, - {VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 0, 4}, - {VK_SHADER_STAGE_VERTEX_BIT, 0, 4}, - {VK_SHADER_STAGE_VERTEX_BIT, 0, 4}, - {VK_SHADER_STAGE_GEOMETRY_BIT, 0, 4}}, - { - "vkCreatePipelineLayout() Duplicate stage flags found in ranges 2 and 3.", - }}, - }, - }; - - for (const auto &iter : duplicate_stageFlags_tests) { - pipeline_layout_ci.pPushConstantRanges = iter.ranges; - pipeline_layout_ci.pushConstantRangeCount = ranges_per_test; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, iter.msg.begin(), iter.msg.end()); - vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - } - - // - // CmdPushConstants tests - // - - // Setup a pipeline layout with ranges: [0,32) [16,80) - const std::vector<VkPushConstantRange> pc_range2 = {{VK_SHADER_STAGE_VERTEX_BIT, 16, 64}, - {VK_SHADER_STAGE_FRAGMENT_BIT, 0, 32}}; - const VkPipelineLayoutObj pipeline_layout_obj(m_device, {}, pc_range2); - - const uint8_t dummy_values[100] = {}; - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - // Check for invalid stage flag - // Note that VU 00996 isn't reached due to parameter validation - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "vkCmdPushConstants: value of stageFlags must not be 0"); - vkCmdPushConstants(m_commandBuffer->handle(), pipeline_layout_obj.handle(), 0, 0, 16, dummy_values); - m_errorMonitor->VerifyFound(); - - // Positive tests for the overlapping ranges - m_errorMonitor->ExpectSuccess(); - vkCmdPushConstants(m_commandBuffer->handle(), pipeline_layout_obj.handle(), VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16, dummy_values); - m_errorMonitor->VerifyNotFound(); - m_errorMonitor->ExpectSuccess(); - vkCmdPushConstants(m_commandBuffer->handle(), pipeline_layout_obj.handle(), VK_SHADER_STAGE_VERTEX_BIT, 32, 48, dummy_values); - m_errorMonitor->VerifyNotFound(); - m_errorMonitor->ExpectSuccess(); - vkCmdPushConstants(m_commandBuffer->handle(), pipeline_layout_obj.handle(), - VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 16, 16, dummy_values); - m_errorMonitor->VerifyNotFound(); - - // Wrong cmd stages for extant range - // No range for all cmd stages -- "VUID-vkCmdPushConstants-offset-01795" VUID-vkCmdPushConstants-offset-01795 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPushConstants-offset-01795"); - // Missing cmd stages for found overlapping range -- "VUID-vkCmdPushConstants-offset-01796" VUID-vkCmdPushConstants-offset-01796 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPushConstants-offset-01796"); - vkCmdPushConstants(m_commandBuffer->handle(), pipeline_layout_obj.handle(), VK_SHADER_STAGE_GEOMETRY_BIT, 0, 16, dummy_values); - m_errorMonitor->VerifyFound(); - - // Wrong no extant range - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPushConstants-offset-01795"); - vkCmdPushConstants(m_commandBuffer->handle(), pipeline_layout_obj.handle(), VK_SHADER_STAGE_FRAGMENT_BIT, 80, 4, dummy_values); - m_errorMonitor->VerifyFound(); - - // Wrong overlapping extent - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPushConstants-offset-01795"); - vkCmdPushConstants(m_commandBuffer->handle(), pipeline_layout_obj.handle(), - VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 20, dummy_values); - m_errorMonitor->VerifyFound(); - - // Wrong stage flags for valid overlapping range - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPushConstants-offset-01796"); - vkCmdPushConstants(m_commandBuffer->handle(), pipeline_layout_obj.handle(), VK_SHADER_STAGE_VERTEX_BIT, 16, 16, dummy_values); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, DescriptorSetCompatibility) { - // Test various desriptorSet errors with bad binding combinations - using std::vector; - VkResult err; - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - static const uint32_t NUM_DESCRIPTOR_TYPES = 5; - VkDescriptorPoolSize ds_type_count[NUM_DESCRIPTOR_TYPES] = {}; - ds_type_count[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - ds_type_count[0].descriptorCount = 10; - ds_type_count[1].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - ds_type_count[1].descriptorCount = 2; - ds_type_count[2].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - ds_type_count[2].descriptorCount = 2; - ds_type_count[3].type = VK_DESCRIPTOR_TYPE_SAMPLER; - ds_type_count[3].descriptorCount = 5; - // TODO : LunarG ILO driver currently asserts in desc.c w/ INPUT_ATTACHMENT - // type - // ds_type_count[4].type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; - ds_type_count[4].type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - ds_type_count[4].descriptorCount = 2; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.maxSets = 5; - ds_pool_ci.poolSizeCount = NUM_DESCRIPTOR_TYPES; - ds_pool_ci.pPoolSizes = ds_type_count; - - VkDescriptorPool ds_pool; - err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - ASSERT_VK_SUCCESS(err); - - static const uint32_t MAX_DS_TYPES_IN_LAYOUT = 2; - VkDescriptorSetLayoutBinding dsl_binding[MAX_DS_TYPES_IN_LAYOUT] = {}; - dsl_binding[0].binding = 0; - dsl_binding[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - dsl_binding[0].descriptorCount = 5; - dsl_binding[0].stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding[0].pImmutableSamplers = NULL; - - // Create layout identical to set0 layout but w/ different stageFlags - VkDescriptorSetLayoutBinding dsl_fs_stage_only = {}; - dsl_fs_stage_only.binding = 0; - dsl_fs_stage_only.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - dsl_fs_stage_only.descriptorCount = 5; - dsl_fs_stage_only.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; // Different stageFlags to cause error at - // bind time - dsl_fs_stage_only.pImmutableSamplers = NULL; - - vector<VkDescriptorSetLayoutObj> ds_layouts; - // Create 4 unique layouts for full pipelineLayout, and 1 special fs-only - // layout for error case - ds_layouts.emplace_back(m_device, std::vector<VkDescriptorSetLayoutBinding>(1, dsl_binding[0])); - - const VkDescriptorSetLayoutObj ds_layout_fs_only(m_device, {dsl_fs_stage_only}); - - dsl_binding[0].binding = 0; - dsl_binding[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - dsl_binding[0].descriptorCount = 2; - dsl_binding[1].binding = 1; - dsl_binding[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - dsl_binding[1].descriptorCount = 2; - dsl_binding[1].stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding[1].pImmutableSamplers = NULL; - ds_layouts.emplace_back(m_device, std::vector<VkDescriptorSetLayoutBinding>({dsl_binding[0], dsl_binding[1]})); - - dsl_binding[0].binding = 0; - dsl_binding[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - dsl_binding[0].descriptorCount = 5; - ds_layouts.emplace_back(m_device, std::vector<VkDescriptorSetLayoutBinding>(1, dsl_binding[0])); - - dsl_binding[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - dsl_binding[0].descriptorCount = 2; - ds_layouts.emplace_back(m_device, std::vector<VkDescriptorSetLayoutBinding>(1, dsl_binding[0])); - - const auto &ds_vk_layouts = MakeVkHandles<VkDescriptorSetLayout>(ds_layouts); - - static const uint32_t NUM_SETS = 4; - VkDescriptorSet descriptorSet[NUM_SETS] = {}; - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorPool = ds_pool; - alloc_info.descriptorSetCount = ds_vk_layouts.size(); - alloc_info.pSetLayouts = ds_vk_layouts.data(); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, descriptorSet); - ASSERT_VK_SUCCESS(err); - VkDescriptorSet ds0_fs_only = {}; - alloc_info.descriptorSetCount = 1; - alloc_info.pSetLayouts = &ds_layout_fs_only.handle(); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &ds0_fs_only); - ASSERT_VK_SUCCESS(err); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds_layouts[0], &ds_layouts[1]}); - // Create pipelineLayout with only one setLayout - const VkPipelineLayoutObj single_pipe_layout(m_device, {&ds_layouts[0]}); - // Create pipelineLayout with 2 descriptor setLayout at index 0 - const VkPipelineLayoutObj pipe_layout_one_desc(m_device, {&ds_layouts[3]}); - // Create pipelineLayout with 5 SAMPLER descriptor setLayout at index 0 - const VkPipelineLayoutObj pipe_layout_five_samp(m_device, {&ds_layouts[2]}); - // Create pipelineLayout with UB type, but stageFlags for FS only - VkPipelineLayoutObj pipe_layout_fs_only(m_device, {&ds_layout_fs_only}); - // Create pipelineLayout w/ incompatible set0 layout, but set1 is fine - const VkPipelineLayoutObj pipe_layout_bad_set0(m_device, {&ds_layout_fs_only, &ds_layouts[1]}); - - // Add buffer binding for UBO - uint32_t qfi = 0; - VkBufferCreateInfo bci = {}; - bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bci.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - bci.size = 8; - bci.queueFamilyIndexCount = 1; - bci.pQueueFamilyIndices = &qfi; - VkBufferObj buffer; - buffer.init(*m_device, bci); - VkDescriptorBufferInfo buffer_info; - buffer_info.buffer = buffer.handle(); - buffer_info.offset = 0; - buffer_info.range = VK_WHOLE_SIZE; - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = descriptorSet[0]; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_write.pBufferInfo = &buffer_info; - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - // Create PSO to be used for draw-time errors below - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 x;\n" - "layout(set=0) layout(binding=0) uniform foo { int x; int y; } bar;\n" - "void main(){\n" - " x = vec4(bar.y);\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.CreateVKPipeline(pipe_layout_fs_only.handle(), renderPass()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - // TODO : Want to cause various binding incompatibility issues here to test - // DrawState - // First cause various verify_layout_compatibility() fails - // Second disturb early and late sets and verify INFO msgs - // VerifySetLayoutCompatibility fail cases: - // 1. invalid VkPipelineLayout (layout) passed into vkCmdBindDescriptorSets - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindDescriptorSets-layout-parameter"); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, (VkPipelineLayout)((size_t)0xbaadb1be), 0, - 1, &descriptorSet[0], 0, NULL); - m_errorMonitor->VerifyFound(); - - // 2. layoutIndex exceeds # of layouts in layout - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " attempting to bind set to index 1"); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, single_pipe_layout.handle(), 0, 2, - &descriptorSet[0], 0, NULL); - m_errorMonitor->VerifyFound(); - - // 3. Pipeline setLayout[0] has 2 descriptors, but set being bound has 5 - // descriptors - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " has 2 descriptors, but DescriptorSetLayout "); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_layout_one_desc.handle(), 0, 1, - &descriptorSet[0], 0, NULL); - m_errorMonitor->VerifyFound(); - - // 4. same # of descriptors but mismatch in type - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " is type 'VK_DESCRIPTOR_TYPE_SAMPLER' but binding "); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_layout_five_samp.handle(), 0, 1, - &descriptorSet[0], 0, NULL); - m_errorMonitor->VerifyFound(); - - // 5. same # of descriptors but mismatch in stageFlags - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - " has stageFlags 16 but binding 0 for DescriptorSetLayout "); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_layout_fs_only.handle(), 0, 1, - &descriptorSet[0], 0, NULL); - m_errorMonitor->VerifyFound(); - - // Now that we're done actively using the pipelineLayout that gfx pipeline - // was created with, we should be able to delete it. Do that now to verify - // that validation obeys pipelineLayout lifetime - pipe_layout_fs_only.Reset(); - - // Cause draw-time errors due to PSO incompatibilities - // 1. Error due to not binding required set (we actually use same code as - // above to disturb set0) - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 2, - &descriptorSet[0], 0, NULL); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_layout_bad_set0.handle(), 1, 1, - &descriptorSet[1], 0, NULL); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " uses set #0 but that set is not bound."); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - - m_commandBuffer->Draw(1, 0, 0, 0); - m_errorMonitor->VerifyFound(); - - // 2. Error due to bound set not being compatible with PSO's - // VkPipelineLayout (diff stageFlags in this case) - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 2, - &descriptorSet[0], 0, NULL); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " bound as set #0 is not compatible with "); - m_commandBuffer->Draw(1, 0, 0, 0); - m_errorMonitor->VerifyFound(); - - // Remaining clean-up - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); -} - -TEST_F(VkLayerTest, NoBeginCommandBuffer) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "You must call vkBeginCommandBuffer() before this call to "); - - ASSERT_NO_FATAL_FAILURE(Init()); - VkCommandBufferObj commandBuffer(m_device, m_commandPool); - // Call EndCommandBuffer() w/o calling BeginCommandBuffer() - vkEndCommandBuffer(commandBuffer.handle()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, SecondaryCommandBufferNullRenderpass) { - ASSERT_NO_FATAL_FAILURE(Init()); - - VkCommandBufferObj cb(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); - - // Force the failure by not setting the Renderpass and Framebuffer fields - VkCommandBufferInheritanceInfo cmd_buf_hinfo = {}; - cmd_buf_hinfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; - - VkCommandBufferBeginInfo cmd_buf_info = {}; - cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - cmd_buf_info.pNext = NULL; - cmd_buf_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; - cmd_buf_info.pInheritanceInfo = &cmd_buf_hinfo; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkCommandBufferBeginInfo-flags-00053"); - vkBeginCommandBuffer(cb.handle(), &cmd_buf_info); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, SecondaryCommandBufferRerecordedExplicitReset) { - ASSERT_NO_FATAL_FAILURE(Init()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "was destroyed or rerecorded"); - - // A pool we can reset in. - VkCommandPoolObj pool(m_device, m_device->graphics_queue_node_index_, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); - VkCommandBufferObj secondary(m_device, &pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); - - secondary.begin(); - secondary.end(); - - m_commandBuffer->begin(); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary.handle()); - - // rerecording of secondary - secondary.reset(); // explicit reset here. - secondary.begin(); - secondary.end(); - - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary.handle()); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, SecondaryCommandBufferRerecordedNoReset) { - ASSERT_NO_FATAL_FAILURE(Init()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "was destroyed or rerecorded"); - - // A pool we can reset in. - VkCommandPoolObj pool(m_device, m_device->graphics_queue_node_index_, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); - VkCommandBufferObj secondary(m_device, &pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); - - secondary.begin(); - secondary.end(); - - m_commandBuffer->begin(); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary.handle()); - - // rerecording of secondary - secondary.begin(); // implicit reset in begin - secondary.end(); - - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary.handle()); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CascadedInvalidation) { - ASSERT_NO_FATAL_FAILURE(Init()); - - VkEventCreateInfo eci = {VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, nullptr, 0}; - VkEvent event; - vkCreateEvent(m_device->device(), &eci, nullptr, &event); - - VkCommandBufferObj secondary(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); - secondary.begin(); - vkCmdSetEvent(secondary.handle(), event, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); - secondary.end(); - - m_commandBuffer->begin(); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary.handle()); - m_commandBuffer->end(); - - // destroying the event should invalidate both primary and secondary CB - vkDestroyEvent(m_device->device(), event, nullptr); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "invalid because bound Event"); - m_commandBuffer->QueueCommandBuffer(false); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CommandBufferResetErrors) { - // Cause error due to Begin while recording CB - // Then cause 2 errors for attempting to reset CB w/o having - // VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT set for the pool from - // which CBs were allocated. Note that this bit is off by default. - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Cannot call Begin on command buffer"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // Calls AllocateCommandBuffers - VkCommandBufferObj commandBuffer(m_device, m_commandPool); - - // Force the failure by setting the Renderpass and Framebuffer fields with (fake) data - VkCommandBufferInheritanceInfo cmd_buf_hinfo = {}; - cmd_buf_hinfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; - VkCommandBufferBeginInfo cmd_buf_info = {}; - cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - cmd_buf_info.pNext = NULL; - cmd_buf_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - cmd_buf_info.pInheritanceInfo = &cmd_buf_hinfo; - - // Begin CB to transition to recording state - vkBeginCommandBuffer(commandBuffer.handle(), &cmd_buf_info); - // Can't re-begin. This should trigger error - vkBeginCommandBuffer(commandBuffer.handle(), &cmd_buf_info); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkResetCommandBuffer-commandBuffer-00046"); - VkCommandBufferResetFlags flags = 0; // Don't care about flags for this test - // Reset attempt will trigger error due to incorrect CommandPool state - vkResetCommandBuffer(commandBuffer.handle(), flags); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBeginCommandBuffer-commandBuffer-00050"); - // Transition CB to RECORDED state - vkEndCommandBuffer(commandBuffer.handle()); - // Now attempting to Begin will implicitly reset, which triggers error - vkBeginCommandBuffer(commandBuffer.handle(), &cmd_buf_info); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, InvalidPipelineCreateState) { - // Attempt to Create Gfx Pipeline w/o a VS - VkResult err; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Invalid Pipeline CreateInfo State: Vertex Shader required"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool; - err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 0; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding}); - - VkDescriptorSet descriptorSet; - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorSetCount = 1; - alloc_info.descriptorPool = ds_pool; - alloc_info.pSetLayouts = &ds_layout.handle(); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptorSet); - ASSERT_VK_SUCCESS(err); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds_layout}); - - VkPipelineRasterizationStateCreateInfo rs_state_ci = {}; - rs_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rs_state_ci.polygonMode = VK_POLYGON_MODE_FILL; - rs_state_ci.cullMode = VK_CULL_MODE_BACK_BIT; - rs_state_ci.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rs_state_ci.depthClampEnable = VK_FALSE; - rs_state_ci.rasterizerDiscardEnable = VK_TRUE; - rs_state_ci.depthBiasEnable = VK_FALSE; - rs_state_ci.lineWidth = 1.0f; - - VkPipelineVertexInputStateCreateInfo vi_ci = {}; - vi_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vi_ci.pNext = nullptr; - vi_ci.vertexBindingDescriptionCount = 0; - vi_ci.pVertexBindingDescriptions = nullptr; - vi_ci.vertexAttributeDescriptionCount = 0; - vi_ci.pVertexAttributeDescriptions = nullptr; - - VkPipelineInputAssemblyStateCreateInfo ia_ci = {}; - ia_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - ia_ci.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; - - VkPipelineShaderStageCreateInfo shaderStages[2]; - memset(&shaderStages, 0, 2 * sizeof(VkPipelineShaderStageCreateInfo)); - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - shaderStages[0] = fs.GetStageCreateInfo(); // should be: vs.GetStageCreateInfo(); - shaderStages[1] = fs.GetStageCreateInfo(); - - VkGraphicsPipelineCreateInfo gp_ci = {}; - gp_ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - gp_ci.pViewportState = nullptr; // no viewport b/c rasterizer is disabled - gp_ci.pRasterizationState = &rs_state_ci; - gp_ci.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; - gp_ci.layout = pipeline_layout.handle(); - gp_ci.renderPass = renderPass(); - gp_ci.pVertexInputState = &vi_ci; - gp_ci.pInputAssemblyState = &ia_ci; - - gp_ci.stageCount = 1; - gp_ci.pStages = shaderStages; - - VkPipelineCacheCreateInfo pc_ci = {}; - pc_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - pc_ci.initialDataSize = 0; - pc_ci.pInitialData = 0; - - VkPipeline pipeline; - VkPipelineCache pipelineCache; - - err = vkCreatePipelineCache(m_device->device(), &pc_ci, NULL, &pipelineCache); - ASSERT_VK_SUCCESS(err); - err = vkCreateGraphicsPipelines(m_device->device(), pipelineCache, 1, &gp_ci, NULL, &pipeline); - m_errorMonitor->VerifyFound(); - - // Finally, check the string validation for the shader stage pName variable. Correct the shader stage data, and bork the - // string before calling again - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "contains invalid characters or is badly formed"); - shaderStages[0] = vs.GetStageCreateInfo(); - const uint8_t cont_char = 0xf8; - char bad_string[] = {static_cast<char>(cont_char), static_cast<char>(cont_char), static_cast<char>(cont_char), - static_cast<char>(cont_char)}; - shaderStages[0].pName = bad_string; - err = vkCreateGraphicsPipelines(m_device->device(), pipelineCache, 1, &gp_ci, NULL, &pipeline); - m_errorMonitor->VerifyFound(); - - vkDestroyPipelineCache(m_device->device(), pipelineCache, NULL); - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); -} - -TEST_F(VkLayerTest, InvalidPipelineSampleRateFeatureDisable) { - // Enable sample shading in pipeline when the feature is disabled. - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - // Disable sampleRateShading here - VkPhysicalDeviceFeatures device_features = {}; - ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features)); - device_features.sampleRateShading = VK_FALSE; - - ASSERT_NO_FATAL_FAILURE(InitState(&device_features)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Cause the error by enabling sample shading... - auto set_shading_enable = [](CreatePipelineHelper &helper) { helper.pipe_ms_state_ci_.sampleShadingEnable = VK_TRUE; }; - CreatePipelineHelper::OneshotTest(*this, set_shading_enable, VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineMultisampleStateCreateInfo-sampleShadingEnable-00784"); -} - -TEST_F(VkLayerTest, InvalidPipelineSampleRateFeatureEnable) { - // Enable sample shading in pipeline when the feature is disabled. - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - // Require sampleRateShading here - VkPhysicalDeviceFeatures device_features = {}; - ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features)); - if (device_features.sampleRateShading == VK_FALSE) { - printf("%s SampleRateShading feature is disabled -- skipping related checks.\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState(&device_features)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - auto range_test = [this](float value, bool positive_test) { - auto info_override = [value](CreatePipelineHelper &helper) { - helper.pipe_ms_state_ci_.sampleShadingEnable = VK_TRUE; - helper.pipe_ms_state_ci_.minSampleShading = value; - }; - CreatePipelineHelper::OneshotTest(*this, info_override, VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineMultisampleStateCreateInfo-minSampleShading-00786", positive_test); - }; - - range_test(NearestSmaller(0.0F), false); - range_test(NearestGreater(1.0F), false); - range_test(0.0F, /* positive_test= */ true); - range_test(1.0F, /* positive_test= */ true); -} - -TEST_F(VkLayerTest, InvalidPipelineSamplePNext) { - // Enable sample shading in pipeline when the feature is disabled. - // Check for VK_KHR_get_physical_device_properties2 - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - // Set up the extension structs - auto sampleLocations = chain_util::Init<VkPipelineSampleLocationsStateCreateInfoEXT>(); - sampleLocations.sampleLocationsInfo.sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT; - auto coverageToColor = chain_util::Init<VkPipelineCoverageToColorStateCreateInfoNV>(); - auto coverageModulation = chain_util::Init<VkPipelineCoverageModulationStateCreateInfoNV>(); - auto discriminatrix = [this](const char *name) { return DeviceExtensionSupported(gpu(), nullptr, name); }; - chain_util::ExtensionChain chain(discriminatrix, &m_device_extension_names); - chain.Add(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME, sampleLocations); - chain.Add(VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME, coverageToColor); - chain.Add(VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME, coverageModulation); - const void *extension_head = chain.Head(); - - ASSERT_NO_FATAL_FAILURE(InitState()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - if (extension_head) { - auto good_chain = [extension_head](CreatePipelineHelper &helper) { helper.pipe_ms_state_ci_.pNext = extension_head; }; - CreatePipelineHelper::OneshotTest(*this, good_chain, (VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT), - "No error", true); - } else { - printf("%s Required extension not present -- skipping positive checks.\n", kSkipPrefix); - } - - auto instance_ci = chain_util::Init<VkInstanceCreateInfo>(); - auto bad_chain = [&instance_ci](CreatePipelineHelper &helper) { helper.pipe_ms_state_ci_.pNext = &instance_ci; }; - CreatePipelineHelper::OneshotTest(*this, bad_chain, VK_DEBUG_REPORT_WARNING_BIT_EXT, - "VUID-VkPipelineMultisampleStateCreateInfo-pNext-pNext"); -} - -TEST_F(VkLayerTest, DeviceFeature2AndVertexAttributeDivisorExtensionUnenabled) { - TEST_DESCRIPTION( - "Test unenabled VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME & " - "VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME."); - - VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vadf = {}; - vadf.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT; - VkPhysicalDeviceFeatures2 pd_features2 = {}; - pd_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; - pd_features2.pNext = &vadf; - - ASSERT_NO_FATAL_FAILURE(Init()); - vk_testing::QueueCreateInfoArray queue_info(m_device->queue_props); - VkDeviceCreateInfo device_create_info = {}; - device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - device_create_info.pNext = &pd_features2; - device_create_info.queueCreateInfoCount = queue_info.size(); - device_create_info.pQueueCreateInfos = queue_info.data(); - VkDevice testDevice; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VK_KHR_get_physical_device_properties2 must be enabled when it creates an instance"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VK_EXT_vertex_attribute_divisor must be enabled when it creates a device"); - m_errorMonitor->SetUnexpectedError("Failed to create device chain"); - vkCreateDevice(gpu(), &device_create_info, NULL, &testDevice); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, VertexAttributeDivisorExtension) { - TEST_DESCRIPTION("Test VUIDs added with VK_EXT_vertex_attribute_divisor extension."); - - bool inst_ext = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - if (inst_ext) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - } - if (inst_ext && DeviceExtensionSupported(gpu(), nullptr, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME); - return; - } - - VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vadf = {}; - vadf.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT; - vadf.vertexAttributeInstanceRateDivisor = VK_TRUE; - vadf.vertexAttributeInstanceRateZeroDivisor = VK_TRUE; - - VkPhysicalDeviceFeatures2 pd_features2 = {}; - pd_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; - pd_features2.pNext = &vadf; - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &pd_features2)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const VkPhysicalDeviceLimits &dev_limits = m_device->props.limits; - VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT pdvad_props = {}; - pdvad_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT; - VkPhysicalDeviceProperties2 pd_props2 = {}; - pd_props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - pd_props2.pNext = &pdvad_props; - vkGetPhysicalDeviceProperties2(gpu(), &pd_props2); - - VkVertexInputBindingDivisorDescriptionEXT vibdd = {}; - VkPipelineVertexInputDivisorStateCreateInfoEXT pvids_ci = {}; - pvids_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT; - pvids_ci.vertexBindingDivisorCount = 1; - pvids_ci.pVertexBindingDivisors = &vibdd; - VkVertexInputBindingDescription vibd = {}; - vibd.stride = 12; - vibd.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - if (pdvad_props.maxVertexAttribDivisor < pvids_ci.vertexBindingDivisorCount) { - printf("%sThis device does not support %d vertexBindingDivisors, skipping tests\n", kSkipPrefix, - pvids_ci.vertexBindingDivisorCount); - return; - } - - using std::vector; - struct TestCase { - uint32_t div_binding; - uint32_t div_divisor; - uint32_t desc_binding; - VkVertexInputRate desc_rate; - vector<std::string> vuids; - }; - - // clang-format off - vector<TestCase> test_cases = { - { 0, - 1, - 0, - VK_VERTEX_INPUT_RATE_VERTEX, - {"VUID-VkVertexInputBindingDivisorDescriptionEXT-inputRate-01871"} - }, - { dev_limits.maxVertexInputBindings + 1, - 1, - 0, - VK_VERTEX_INPUT_RATE_INSTANCE, - {"VUID-VkVertexInputBindingDivisorDescriptionEXT-binding-01869", - "VUID-VkVertexInputBindingDivisorDescriptionEXT-inputRate-01871"} - } - }; - - if (UINT32_MAX != pdvad_props.maxVertexAttribDivisor) { // Can't test overflow if maxVAD is UINT32_MAX - test_cases.push_back( - { 0, - pdvad_props.maxVertexAttribDivisor + 1, - 0, - VK_VERTEX_INPUT_RATE_INSTANCE, - {"VUID-VkVertexInputBindingDivisorDescriptionEXT-divisor-01870"} - } ); - } - // clang-format on - - for (const auto &test_case : test_cases) { - const auto bad_divisor_state = [&test_case, &vibdd, &pvids_ci, &vibd](CreatePipelineHelper &helper) { - vibdd.binding = test_case.div_binding; - vibdd.divisor = test_case.div_divisor; - vibd.binding = test_case.desc_binding; - vibd.inputRate = test_case.desc_rate; - helper.vi_ci_.pNext = &pvids_ci; - helper.vi_ci_.vertexBindingDescriptionCount = 1; - helper.vi_ci_.pVertexBindingDescriptions = &vibd; - }; - CreatePipelineHelper::OneshotTest(*this, bad_divisor_state, VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuids); - } -} - -TEST_F(VkLayerTest, VertexAttributeDivisorDisabled) { - TEST_DESCRIPTION("Test instance divisor feature disabled for VK_EXT_vertex_attribute_divisor extension."); - - bool inst_ext = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - if (inst_ext) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - } - if (inst_ext && DeviceExtensionSupported(gpu(), nullptr, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME); - return; - } - - VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vadf = {}; - vadf.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT; - vadf.vertexAttributeInstanceRateDivisor = VK_FALSE; - vadf.vertexAttributeInstanceRateZeroDivisor = VK_FALSE; - VkPhysicalDeviceFeatures2 pd_features2 = {}; - pd_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; - pd_features2.pNext = &vadf; - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &pd_features2)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT pdvad_props = {}; - pdvad_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT; - VkPhysicalDeviceProperties2 pd_props2 = {}; - pd_props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - pd_props2.pNext = &pdvad_props; - vkGetPhysicalDeviceProperties2(gpu(), &pd_props2); - - VkVertexInputBindingDivisorDescriptionEXT vibdd = {}; - vibdd.binding = 0; - vibdd.divisor = 2; - VkPipelineVertexInputDivisorStateCreateInfoEXT pvids_ci = {}; - pvids_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT; - pvids_ci.vertexBindingDivisorCount = 1; - pvids_ci.pVertexBindingDivisors = &vibdd; - VkVertexInputBindingDescription vibd = {}; - vibd.binding = vibdd.binding; - vibd.stride = 12; - vibd.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE; - - if (pdvad_props.maxVertexAttribDivisor < pvids_ci.vertexBindingDivisorCount) { - printf("%sThis device does not support %d vertexBindingDivisors, skipping tests\n", kSkipPrefix, - pvids_ci.vertexBindingDivisorCount); - return; - } - - const auto instance_rate = [&pvids_ci, &vibd](CreatePipelineHelper &helper) { - helper.vi_ci_.pNext = &pvids_ci; - helper.vi_ci_.vertexBindingDescriptionCount = 1; - helper.vi_ci_.pVertexBindingDescriptions = &vibd; - }; - CreatePipelineHelper::OneshotTest(*this, instance_rate, VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkVertexInputBindingDivisorDescriptionEXT-vertexAttributeInstanceRateDivisor-02229"); -} - -TEST_F(VkLayerTest, VertexAttributeDivisorInstanceRateZero) { - TEST_DESCRIPTION("Test instanceRateZero feature of VK_EXT_vertex_attribute_divisor extension."); - - bool inst_ext = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - if (inst_ext) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - } - if (inst_ext && DeviceExtensionSupported(gpu(), nullptr, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME); - return; - } - - VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vadf = {}; - vadf.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT; - vadf.vertexAttributeInstanceRateDivisor = VK_TRUE; - vadf.vertexAttributeInstanceRateZeroDivisor = VK_FALSE; - VkPhysicalDeviceFeatures2 pd_features2 = {}; - pd_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; - pd_features2.pNext = &vadf; - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &pd_features2)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkVertexInputBindingDivisorDescriptionEXT vibdd = {}; - vibdd.binding = 0; - vibdd.divisor = 0; - VkPipelineVertexInputDivisorStateCreateInfoEXT pvids_ci = {}; - pvids_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT; - pvids_ci.vertexBindingDivisorCount = 1; - pvids_ci.pVertexBindingDivisors = &vibdd; - VkVertexInputBindingDescription vibd = {}; - vibd.binding = vibdd.binding; - vibd.stride = 12; - vibd.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE; - - const auto instance_rate = [&pvids_ci, &vibd](CreatePipelineHelper &helper) { - helper.vi_ci_.pNext = &pvids_ci; - helper.vi_ci_.vertexBindingDescriptionCount = 1; - helper.vi_ci_.pVertexBindingDescriptions = &vibd; - }; - CreatePipelineHelper::OneshotTest( - *this, instance_rate, VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkVertexInputBindingDivisorDescriptionEXT-vertexAttributeInstanceRateZeroDivisor-02228"); -} - -/*// TODO : This test should be good, but needs Tess support in compiler to run -TEST_F(VkLayerTest, InvalidPatchControlPoints) -{ - // Attempt to Create Gfx Pipeline w/o a VS - VkResult err; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Invalid Pipeline CreateInfo State: VK_PRIMITIVE_TOPOLOGY_PATCH -primitive "); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool; - err = vkCreateDescriptorPool(m_device->device(), -VK_DESCRIPTOR_POOL_USAGE_NON_FREE, 1, &ds_pool_ci, NULL, &ds_pool); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 0; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding.pImmutableSamplers = NULL; - - VkDescriptorSetLayoutCreateInfo ds_layout_ci = {}; - ds_layout_ci.sType = -VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - ds_layout_ci.pNext = NULL; - ds_layout_ci.bindingCount = 1; - ds_layout_ci.pBindings = &dsl_binding; - - VkDescriptorSetLayout ds_layout; - err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, -&ds_layout); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSet descriptorSet; - err = vkAllocateDescriptorSets(m_device->device(), ds_pool, -VK_DESCRIPTOR_SET_USAGE_NON_FREE, 1, &ds_layout, &descriptorSet); - ASSERT_VK_SUCCESS(err); - - VkPipelineLayoutCreateInfo pipeline_layout_ci = {}; - pipeline_layout_ci.sType = -VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_ci.pNext = NULL; - pipeline_layout_ci.setLayoutCount = 1; - pipeline_layout_ci.pSetLayouts = &ds_layout; - - VkPipelineLayout pipeline_layout; - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, -&pipeline_layout); - ASSERT_VK_SUCCESS(err); - - VkPipelineShaderStageCreateInfo shaderStages[3]; - memset(&shaderStages, 0, 3 * sizeof(VkPipelineShaderStageCreateInfo)); - - VkShaderObj vs(m_device,bindStateVertShaderText,VK_SHADER_STAGE_VERTEX_BIT, -this); - // Just using VS txt for Tess shaders as we don't care about functionality - VkShaderObj -tc(m_device,bindStateVertShaderText,VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, -this); - VkShaderObj -te(m_device,bindStateVertShaderText,VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, -this); - - shaderStages[0].sType = -VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - shaderStages[0].shader = vs.handle(); - shaderStages[1].sType = -VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shaderStages[1].stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; - shaderStages[1].shader = tc.handle(); - shaderStages[2].sType = -VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shaderStages[2].stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; - shaderStages[2].shader = te.handle(); - - VkPipelineInputAssemblyStateCreateInfo iaCI = {}; - iaCI.sType = -VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - iaCI.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; - - VkPipelineTessellationStateCreateInfo tsCI = {}; - tsCI.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; - tsCI.patchControlPoints = 0; // This will cause an error - - VkGraphicsPipelineCreateInfo gp_ci = {}; - gp_ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - gp_ci.pNext = NULL; - gp_ci.stageCount = 3; - gp_ci.pStages = shaderStages; - gp_ci.pVertexInputState = NULL; - gp_ci.pInputAssemblyState = &iaCI; - gp_ci.pTessellationState = &tsCI; - gp_ci.pViewportState = NULL; - gp_ci.pRasterizationState = NULL; - gp_ci.pMultisampleState = NULL; - gp_ci.pDepthStencilState = NULL; - gp_ci.pColorBlendState = NULL; - gp_ci.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; - gp_ci.layout = pipeline_layout; - gp_ci.renderPass = renderPass(); - - VkPipelineCacheCreateInfo pc_ci = {}; - pc_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - pc_ci.pNext = NULL; - pc_ci.initialSize = 0; - pc_ci.initialData = 0; - pc_ci.maxSize = 0; - - VkPipeline pipeline; - VkPipelineCache pipelineCache; - - err = vkCreatePipelineCache(m_device->device(), &pc_ci, NULL, -&pipelineCache); - ASSERT_VK_SUCCESS(err); - err = vkCreateGraphicsPipelines(m_device->device(), pipelineCache, 1, -&gp_ci, NULL, &pipeline); - - m_errorMonitor->VerifyFound(); - - vkDestroyPipelineCache(m_device->device(), pipelineCache, NULL); - vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL); - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL); - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); -} -*/ - -TEST_F(VkLayerTest, PSOViewportStateTests) { - TEST_DESCRIPTION("Test VkPipelineViewportStateCreateInfo viewport and scissor count validation for non-multiViewport"); - - VkPhysicalDeviceFeatures features{}; - ASSERT_NO_FATAL_FAILURE(Init(&features)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const auto break_vp_state = [](CreatePipelineHelper &helper) { - helper.rs_state_ci_.rasterizerDiscardEnable = VK_FALSE; - helper.gp_ci_.pViewportState = nullptr; - }; - CreatePipelineHelper::OneshotTest(*this, break_vp_state, VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-00750"); - - VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; - VkViewport viewports[] = {viewport, viewport}; - VkRect2D scissor = {{0, 0}, {64, 64}}; - VkRect2D scissors[] = {scissor, scissor}; - - // test viewport and scissor arrays - using std::vector; - struct TestCase { - uint32_t viewport_count; - VkViewport *viewports; - uint32_t scissor_count; - VkRect2D *scissors; - - vector<std::string> vuids; - }; - - vector<TestCase> test_cases = { - {0, - viewports, - 1, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {2, - viewports, - 1, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {1, - viewports, - 0, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {1, - viewports, - 2, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {0, - viewports, - 0, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217"}}, - {2, - viewports, - 2, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217"}}, - {0, - viewports, - 2, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {2, - viewports, - 0, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {1, nullptr, 1, scissors, {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00747"}}, - {1, viewports, 1, nullptr, {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00748"}}, - {1, - nullptr, - 1, - nullptr, - {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00747", "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00748"}}, - {2, - nullptr, - 3, - nullptr, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220", "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00747", - "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00748"}}, - {0, - nullptr, - 0, - nullptr, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217"}}, - }; - - for (const auto &test_case : test_cases) { - const auto break_vp = [&test_case](CreatePipelineHelper &helper) { - helper.vp_state_ci_.viewportCount = test_case.viewport_count; - helper.vp_state_ci_.pViewports = test_case.viewports; - helper.vp_state_ci_.scissorCount = test_case.scissor_count; - helper.vp_state_ci_.pScissors = test_case.scissors; - }; - CreatePipelineHelper::OneshotTest(*this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuids); - } - - vector<TestCase> dyn_test_cases = { - {0, - viewports, - 1, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {2, - viewports, - 1, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {1, - viewports, - 0, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {1, - viewports, - 2, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {0, - viewports, - 0, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217"}}, - {2, - viewports, - 2, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217"}}, - {0, - viewports, - 2, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {2, - viewports, - 0, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {2, - nullptr, - 3, - nullptr, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {0, - nullptr, - 0, - nullptr, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217"}}, - }; - - const VkDynamicState dyn_states[] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - - for (const auto &test_case : dyn_test_cases) { - const auto break_vp = [&](CreatePipelineHelper &helper) { - VkPipelineDynamicStateCreateInfo dyn_state_ci = {}; - dyn_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dyn_state_ci.dynamicStateCount = size(dyn_states); - dyn_state_ci.pDynamicStates = dyn_states; - helper.dyn_state_ci_ = dyn_state_ci; - - helper.vp_state_ci_.viewportCount = test_case.viewport_count; - helper.vp_state_ci_.pViewports = test_case.viewports; - helper.vp_state_ci_.scissorCount = test_case.scissor_count; - helper.vp_state_ci_.pScissors = test_case.scissors; - }; - CreatePipelineHelper::OneshotTest(*this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuids); - } -} - -// Set Extension dynamic states without enabling the required Extensions. -TEST_F(VkLayerTest, ExtensionDynamicStatesSetWOExtensionEnabled) { - TEST_DESCRIPTION("Create a graphics pipeline with Extension dynamic states without enabling the required Extensions."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - using std::vector; - struct TestCase { - uint32_t dynamic_state_count; - VkDynamicState dynamic_state; - - char const *errmsg; - }; - - vector<TestCase> dyn_test_cases = { - {1, VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV, - "contains VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV, but VK_NV_clip_space_w_scaling"}, - {1, VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT, - "contains VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT, but VK_EXT_discard_rectangles"}, - {1, VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT, "contains VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT, but VK_EXT_sample_locations"}, - }; - - for (const auto &test_case : dyn_test_cases) { - VkDynamicState state[1]; - state[0] = test_case.dynamic_state; - const auto break_vp = [&](CreatePipelineHelper &helper) { - VkPipelineDynamicStateCreateInfo dyn_state_ci = {}; - dyn_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dyn_state_ci.dynamicStateCount = test_case.dynamic_state_count; - dyn_state_ci.pDynamicStates = state; - helper.dyn_state_ci_ = dyn_state_ci; - }; - CreatePipelineHelper::OneshotTest(*this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.errmsg); - } -} - -TEST_F(VkLayerTest, PSOViewportStateMultiViewportTests) { - TEST_DESCRIPTION("Test VkPipelineViewportStateCreateInfo viewport and scissor count validation for multiViewport feature"); - - ASSERT_NO_FATAL_FAILURE(Init()); // enables all supported features - - if (!m_device->phy().features().multiViewport) { - printf("%s VkPhysicalDeviceFeatures::multiViewport is not supported -- skipping test.\n", kSkipPrefix); - return; - } - // at least 16 viewports supported from here on - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; - VkViewport viewports[] = {viewport, viewport}; - VkRect2D scissor = {{0, 0}, {64, 64}}; - VkRect2D scissors[] = {scissor, scissor}; - - using std::vector; - struct TestCase { - uint32_t viewport_count; - VkViewport *viewports; - uint32_t scissor_count; - VkRect2D *scissors; - - vector<std::string> vuids; - }; - - vector<TestCase> test_cases = { - {0, - viewports, - 2, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-arraylength", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {2, - viewports, - 0, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-scissorCount-arraylength", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {0, - viewports, - 0, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-arraylength", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-arraylength"}}, - {2, nullptr, 2, scissors, {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00747"}}, - {2, viewports, 2, nullptr, {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00748"}}, - {2, - nullptr, - 2, - nullptr, - {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00747", "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00748"}}, - {0, - nullptr, - 0, - nullptr, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-arraylength", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-arraylength"}}, - }; - - const auto max_viewports = m_device->phy().properties().limits.maxViewports; - const bool max_viewports_maxxed = max_viewports == std::numeric_limits<decltype(max_viewports)>::max(); - if (max_viewports_maxxed) { - printf("%s VkPhysicalDeviceLimits::maxViewports is UINT32_MAX -- skipping part of test requiring to exceed maxViewports.\n", - kSkipPrefix); - } else { - const auto too_much_viewports = max_viewports + 1; - // avoid potentially big allocations by using only nullptr - test_cases.push_back({too_much_viewports, - nullptr, - 2, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220", - "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00747"}}); - test_cases.push_back({2, - viewports, - too_much_viewports, - nullptr, - {"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220", - "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00748"}}); - test_cases.push_back( - {too_much_viewports, - nullptr, - too_much_viewports, - nullptr, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219", "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00747", - "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00748"}}); - } - - for (const auto &test_case : test_cases) { - const auto break_vp = [&test_case](CreatePipelineHelper &helper) { - helper.vp_state_ci_.viewportCount = test_case.viewport_count; - helper.vp_state_ci_.pViewports = test_case.viewports; - helper.vp_state_ci_.scissorCount = test_case.scissor_count; - helper.vp_state_ci_.pScissors = test_case.scissors; - }; - CreatePipelineHelper::OneshotTest(*this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuids); - } - - vector<TestCase> dyn_test_cases = { - {0, - viewports, - 2, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-arraylength", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {2, - viewports, - 0, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-scissorCount-arraylength", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}, - {0, - viewports, - 0, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-arraylength", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-arraylength"}}, - {0, - nullptr, - 0, - nullptr, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-arraylength", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-arraylength"}}, - }; - - if (!max_viewports_maxxed) { - const auto too_much_viewports = max_viewports + 1; - // avoid potentially big allocations by using only nullptr - dyn_test_cases.push_back({too_much_viewports, - nullptr, - 2, - scissors, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}); - dyn_test_cases.push_back({2, - viewports, - too_much_viewports, - nullptr, - {"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}}); - dyn_test_cases.push_back({too_much_viewports, - nullptr, - too_much_viewports, - nullptr, - {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219"}}); - } - - const VkDynamicState dyn_states[] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - - for (const auto &test_case : dyn_test_cases) { - const auto break_vp = [&](CreatePipelineHelper &helper) { - VkPipelineDynamicStateCreateInfo dyn_state_ci = {}; - dyn_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dyn_state_ci.dynamicStateCount = size(dyn_states); - dyn_state_ci.pDynamicStates = dyn_states; - helper.dyn_state_ci_ = dyn_state_ci; - - helper.vp_state_ci_.viewportCount = test_case.viewport_count; - helper.vp_state_ci_.pViewports = test_case.viewports; - helper.vp_state_ci_.scissorCount = test_case.scissor_count; - helper.vp_state_ci_.pScissors = test_case.scissors; - }; - CreatePipelineHelper::OneshotTest(*this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuids); - } -} - -TEST_F(VkLayerTest, DynViewportAndScissorUndefinedDrawState) { - TEST_DESCRIPTION("Test viewport and scissor dynamic state that is not set before draw"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // TODO: should also test on !multiViewport - if (!m_device->phy().features().multiViewport) { - printf("%s Device does not support multiple viewports/scissors; skipped.\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - const VkPipelineLayoutObj pipeline_layout(m_device); - - VkPipelineObj pipeline_dyn_vp(m_device); - pipeline_dyn_vp.AddShader(&vs); - pipeline_dyn_vp.AddShader(&fs); - pipeline_dyn_vp.AddDefaultColorAttachment(); - pipeline_dyn_vp.MakeDynamic(VK_DYNAMIC_STATE_VIEWPORT); - pipeline_dyn_vp.SetScissor(m_scissors); - ASSERT_VK_SUCCESS(pipeline_dyn_vp.CreateVKPipeline(pipeline_layout.handle(), m_renderPass)); - - VkPipelineObj pipeline_dyn_sc(m_device); - pipeline_dyn_sc.AddShader(&vs); - pipeline_dyn_sc.AddShader(&fs); - pipeline_dyn_sc.AddDefaultColorAttachment(); - pipeline_dyn_sc.SetViewport(m_viewports); - pipeline_dyn_sc.MakeDynamic(VK_DYNAMIC_STATE_SCISSOR); - ASSERT_VK_SUCCESS(pipeline_dyn_sc.CreateVKPipeline(pipeline_layout.handle(), m_renderPass)); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Dynamic viewport(s) 0 are used by pipeline state object, "); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_dyn_vp.handle()); - vkCmdSetViewport(m_commandBuffer->handle(), 1, 1, - &m_viewports[0]); // Forgetting to set needed 0th viewport (PSO viewportCount == 1) - m_commandBuffer->Draw(1, 0, 0, 0); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Dynamic scissor(s) 0 are used by pipeline state object, "); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_dyn_sc.handle()); - vkCmdSetScissor(m_commandBuffer->handle(), 1, 1, - &m_scissors[0]); // Forgetting to set needed 0th scissor (PSO scissorCount == 1) - m_commandBuffer->Draw(1, 0, 0, 0); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, PSOLineWidthInvalid) { - TEST_DESCRIPTION("Test non-1.0 lineWidth errors when pipeline is created and in vkCmdSetLineWidth"); - VkPhysicalDeviceFeatures features{}; - ASSERT_NO_FATAL_FAILURE(Init(&features)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineShaderStageCreateInfo shader_state_cis[] = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; - - VkPipelineVertexInputStateCreateInfo vi_state_ci = {}; - vi_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - - VkPipelineInputAssemblyStateCreateInfo ia_state_ci = {}; - ia_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - ia_state_ci.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; - - VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; - VkRect2D scissor = {{0, 0}, {64, 64}}; - VkPipelineViewportStateCreateInfo vp_state_ci = {}; - vp_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - vp_state_ci.viewportCount = 1; - vp_state_ci.pViewports = &viewport; - vp_state_ci.scissorCount = 1; - vp_state_ci.pScissors = &scissor; - - VkPipelineRasterizationStateCreateInfo rs_state_ci = {}; - rs_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rs_state_ci.rasterizerDiscardEnable = VK_FALSE; - // lineWidth to be set by checks - - VkPipelineMultisampleStateCreateInfo ms_state_ci = {}; - ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; // must match subpass att. - - VkPipelineColorBlendAttachmentState cba_state = {}; - - VkPipelineColorBlendStateCreateInfo cb_state_ci = {}; - cb_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - cb_state_ci.attachmentCount = 1; // must match count in subpass - cb_state_ci.pAttachments = &cba_state; - - const VkPipelineLayoutObj pipeline_layout(m_device); - - VkGraphicsPipelineCreateInfo gp_ci = {}; - gp_ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - gp_ci.stageCount = sizeof(shader_state_cis) / sizeof(VkPipelineShaderStageCreateInfo); - gp_ci.pStages = shader_state_cis; - gp_ci.pVertexInputState = &vi_state_ci; - gp_ci.pInputAssemblyState = &ia_state_ci; - gp_ci.pViewportState = &vp_state_ci; - gp_ci.pRasterizationState = &rs_state_ci; - gp_ci.pMultisampleState = &ms_state_ci; - gp_ci.pColorBlendState = &cb_state_ci; - gp_ci.layout = pipeline_layout.handle(); - gp_ci.renderPass = renderPass(); - gp_ci.subpass = 0; - - const std::vector<float> test_cases = {-1.0f, 0.0f, NearestSmaller(1.0f), NearestGreater(1.0f), NAN}; - - // test VkPipelineRasterizationStateCreateInfo::lineWidth - for (const auto test_case : test_cases) { - rs_state_ci.lineWidth = test_case; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00749"); - VkPipeline pipeline; - vkCreateGraphicsPipelines(m_device->device(), VK_NULL_HANDLE, 1, &gp_ci, nullptr, &pipeline); - m_errorMonitor->VerifyFound(); - } - - // test vkCmdSetLineWidth - m_commandBuffer->begin(); - - for (const auto test_case : test_cases) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetLineWidth-lineWidth-00788"); - vkCmdSetLineWidth(m_commandBuffer->handle(), test_case); - m_errorMonitor->VerifyFound(); - } -} - -TEST_F(VkLayerTest, VUID_VkVertexInputBindingDescription_binding_00618) { - TEST_DESCRIPTION( - "Test VUID-VkVertexInputBindingDescription-binding-00618: binding must be less than " - "VkPhysicalDeviceLimits::maxVertexInputBindings"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkPipelineCache pipeline_cache; - { - VkPipelineCacheCreateInfo create_info{}; - create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - - VkResult err = vkCreatePipelineCache(m_device->device(), &create_info, nullptr, &pipeline_cache); - ASSERT_VK_SUCCESS(err); - } - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineShaderStageCreateInfo stages[2]{{}}; - stages[0] = vs.GetStageCreateInfo(); - stages[1] = fs.GetStageCreateInfo(); - - // Test when binding is greater than or equal to VkPhysicalDeviceLimits::maxVertexInputBindings. - VkVertexInputBindingDescription vertex_input_binding_description{}; - vertex_input_binding_description.binding = m_device->props.limits.maxVertexInputBindings; - - VkPipelineVertexInputStateCreateInfo vertex_input_state{}; - vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertex_input_state.pNext = nullptr; - vertex_input_state.vertexBindingDescriptionCount = 1; - vertex_input_state.pVertexBindingDescriptions = &vertex_input_binding_description; - vertex_input_state.vertexAttributeDescriptionCount = 0; - vertex_input_state.pVertexAttributeDescriptions = nullptr; - - VkPipelineInputAssemblyStateCreateInfo input_assembly_state{}; - input_assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; - - VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; - VkRect2D scissor = {{0, 0}, {64, 64}}; - VkPipelineViewportStateCreateInfo viewport_state{}; - viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewport_state.viewportCount = 1; - viewport_state.pViewports = &viewport; - viewport_state.scissorCount = 1; - viewport_state.pScissors = &scissor; - - VkPipelineMultisampleStateCreateInfo multisample_state{}; - multisample_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisample_state.pNext = nullptr; - multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - multisample_state.sampleShadingEnable = 0; - multisample_state.minSampleShading = 1.0; - multisample_state.pSampleMask = nullptr; - - VkPipelineRasterizationStateCreateInfo rasterization_state{}; - rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterization_state.polygonMode = VK_POLYGON_MODE_FILL; - rasterization_state.cullMode = VK_CULL_MODE_BACK_BIT; - rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rasterization_state.depthClampEnable = VK_FALSE; - rasterization_state.rasterizerDiscardEnable = VK_FALSE; - rasterization_state.depthBiasEnable = VK_FALSE; - rasterization_state.lineWidth = 1.0f; - - const VkPipelineLayoutObj pipeline_layout(m_device); - - { - VkGraphicsPipelineCreateInfo create_info{}; - create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - create_info.stageCount = 2; - create_info.pStages = stages; - create_info.pVertexInputState = &vertex_input_state; - create_info.pInputAssemblyState = &input_assembly_state; - create_info.pViewportState = &viewport_state; - create_info.pMultisampleState = &multisample_state; - create_info.pRasterizationState = &rasterization_state; - create_info.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; - create_info.layout = pipeline_layout.handle(); - create_info.renderPass = renderPass(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkVertexInputBindingDescription-binding-00618"); - VkPipeline pipeline; - vkCreateGraphicsPipelines(m_device->device(), pipeline_cache, 1, &create_info, nullptr, &pipeline); - m_errorMonitor->VerifyFound(); - } - - vkDestroyPipelineCache(m_device->device(), pipeline_cache, nullptr); -} - -TEST_F(VkLayerTest, VUID_VkVertexInputBindingDescription_stride_00619) { - TEST_DESCRIPTION( - "Test VUID-VkVertexInputBindingDescription-stride-00619: stride must be less than or equal to " - "VkPhysicalDeviceLimits::maxVertexInputBindingStride"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkPipelineCache pipeline_cache; - { - VkPipelineCacheCreateInfo create_info{}; - create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - - VkResult err = vkCreatePipelineCache(m_device->device(), &create_info, nullptr, &pipeline_cache); - ASSERT_VK_SUCCESS(err); - } - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineShaderStageCreateInfo stages[2]{{}}; - stages[0] = vs.GetStageCreateInfo(); - stages[1] = fs.GetStageCreateInfo(); - - // Test when stride is greater than VkPhysicalDeviceLimits::maxVertexInputBindingStride. - VkVertexInputBindingDescription vertex_input_binding_description{}; - vertex_input_binding_description.stride = m_device->props.limits.maxVertexInputBindingStride + 1; - - VkPipelineVertexInputStateCreateInfo vertex_input_state{}; - vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertex_input_state.pNext = nullptr; - vertex_input_state.vertexBindingDescriptionCount = 1; - vertex_input_state.pVertexBindingDescriptions = &vertex_input_binding_description; - vertex_input_state.vertexAttributeDescriptionCount = 0; - vertex_input_state.pVertexAttributeDescriptions = nullptr; - - VkPipelineInputAssemblyStateCreateInfo input_assembly_state{}; - input_assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; - - VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; - VkRect2D scissor = {{0, 0}, {64, 64}}; - VkPipelineViewportStateCreateInfo viewport_state{}; - viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewport_state.viewportCount = 1; - viewport_state.pViewports = &viewport; - viewport_state.scissorCount = 1; - viewport_state.pScissors = &scissor; - - VkPipelineMultisampleStateCreateInfo multisample_state{}; - multisample_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisample_state.pNext = nullptr; - multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - multisample_state.sampleShadingEnable = 0; - multisample_state.minSampleShading = 1.0; - multisample_state.pSampleMask = nullptr; - - VkPipelineRasterizationStateCreateInfo rasterization_state{}; - rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterization_state.polygonMode = VK_POLYGON_MODE_FILL; - rasterization_state.cullMode = VK_CULL_MODE_BACK_BIT; - rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rasterization_state.depthClampEnable = VK_FALSE; - rasterization_state.rasterizerDiscardEnable = VK_FALSE; - rasterization_state.depthBiasEnable = VK_FALSE; - rasterization_state.lineWidth = 1.0f; - - const VkPipelineLayoutObj pipeline_layout(m_device); - - { - VkGraphicsPipelineCreateInfo create_info{}; - create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - create_info.stageCount = 2; - create_info.pStages = stages; - create_info.pVertexInputState = &vertex_input_state; - create_info.pInputAssemblyState = &input_assembly_state; - create_info.pViewportState = &viewport_state; - create_info.pMultisampleState = &multisample_state; - create_info.pRasterizationState = &rasterization_state; - create_info.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; - create_info.layout = pipeline_layout.handle(); - create_info.renderPass = renderPass(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkVertexInputBindingDescription-stride-00619"); - VkPipeline pipeline; - vkCreateGraphicsPipelines(m_device->device(), pipeline_cache, 1, &create_info, nullptr, &pipeline); - m_errorMonitor->VerifyFound(); - } - - vkDestroyPipelineCache(m_device->device(), pipeline_cache, nullptr); -} - -TEST_F(VkLayerTest, VUID_VkVertexInputAttributeDescription_location_00620) { - TEST_DESCRIPTION( - "Test VUID-VkVertexInputAttributeDescription-location-00620: location must be less than " - "VkPhysicalDeviceLimits::maxVertexInputAttributes"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkPipelineCache pipeline_cache; - { - VkPipelineCacheCreateInfo create_info{}; - create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - - VkResult err = vkCreatePipelineCache(m_device->device(), &create_info, nullptr, &pipeline_cache); - ASSERT_VK_SUCCESS(err); - } - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineShaderStageCreateInfo stages[2]{{}}; - stages[0] = vs.GetStageCreateInfo(); - stages[1] = fs.GetStageCreateInfo(); - - // Test when location is greater than or equal to VkPhysicalDeviceLimits::maxVertexInputAttributes. - VkVertexInputAttributeDescription vertex_input_attribute_description{}; - vertex_input_attribute_description.location = m_device->props.limits.maxVertexInputAttributes; - - VkPipelineVertexInputStateCreateInfo vertex_input_state{}; - vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertex_input_state.pNext = nullptr; - vertex_input_state.vertexBindingDescriptionCount = 0; - vertex_input_state.pVertexBindingDescriptions = nullptr; - vertex_input_state.vertexAttributeDescriptionCount = 1; - vertex_input_state.pVertexAttributeDescriptions = &vertex_input_attribute_description; - - VkPipelineInputAssemblyStateCreateInfo input_assembly_state{}; - input_assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; - - VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; - VkRect2D scissor = {{0, 0}, {64, 64}}; - VkPipelineViewportStateCreateInfo viewport_state{}; - viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewport_state.viewportCount = 1; - viewport_state.pViewports = &viewport; - viewport_state.scissorCount = 1; - viewport_state.pScissors = &scissor; - - VkPipelineMultisampleStateCreateInfo multisample_state{}; - multisample_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisample_state.pNext = nullptr; - multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - multisample_state.sampleShadingEnable = 0; - multisample_state.minSampleShading = 1.0; - multisample_state.pSampleMask = nullptr; - - VkPipelineRasterizationStateCreateInfo rasterization_state{}; - rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterization_state.polygonMode = VK_POLYGON_MODE_FILL; - rasterization_state.cullMode = VK_CULL_MODE_BACK_BIT; - rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rasterization_state.depthClampEnable = VK_FALSE; - rasterization_state.rasterizerDiscardEnable = VK_FALSE; - rasterization_state.depthBiasEnable = VK_FALSE; - rasterization_state.lineWidth = 1.0f; - - const VkPipelineLayoutObj pipeline_layout(m_device); - - { - VkGraphicsPipelineCreateInfo create_info{}; - create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - create_info.stageCount = 2; - create_info.pStages = stages; - create_info.pVertexInputState = &vertex_input_state; - create_info.pInputAssemblyState = &input_assembly_state; - create_info.pViewportState = &viewport_state; - create_info.pMultisampleState = &multisample_state; - create_info.pRasterizationState = &rasterization_state; - create_info.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; - create_info.layout = pipeline_layout.handle(); - create_info.renderPass = renderPass(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkVertexInputAttributeDescription-location-00620"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineVertexInputStateCreateInfo-binding-00615"); - VkPipeline pipeline; - vkCreateGraphicsPipelines(m_device->device(), pipeline_cache, 1, &create_info, nullptr, &pipeline); - m_errorMonitor->VerifyFound(); - } - - vkDestroyPipelineCache(m_device->device(), pipeline_cache, nullptr); -} - -TEST_F(VkLayerTest, VUID_VkVertexInputAttributeDescription_binding_00621) { - TEST_DESCRIPTION( - "Test VUID-VkVertexInputAttributeDescription-binding-00621: binding must be less than " - "VkPhysicalDeviceLimits::maxVertexInputBindings"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkPipelineCache pipeline_cache; - { - VkPipelineCacheCreateInfo create_info{}; - create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - - VkResult err = vkCreatePipelineCache(m_device->device(), &create_info, nullptr, &pipeline_cache); - ASSERT_VK_SUCCESS(err); - } - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineShaderStageCreateInfo stages[2]{{}}; - stages[0] = vs.GetStageCreateInfo(); - stages[1] = fs.GetStageCreateInfo(); - - // Test when binding is greater than or equal to VkPhysicalDeviceLimits::maxVertexInputBindings. - VkVertexInputAttributeDescription vertex_input_attribute_description{}; - vertex_input_attribute_description.binding = m_device->props.limits.maxVertexInputBindings; - - VkPipelineVertexInputStateCreateInfo vertex_input_state{}; - vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertex_input_state.pNext = nullptr; - vertex_input_state.vertexBindingDescriptionCount = 0; - vertex_input_state.pVertexBindingDescriptions = nullptr; - vertex_input_state.vertexAttributeDescriptionCount = 1; - vertex_input_state.pVertexAttributeDescriptions = &vertex_input_attribute_description; - - VkPipelineInputAssemblyStateCreateInfo input_assembly_state{}; - input_assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; - - VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; - VkRect2D scissor = {{0, 0}, {64, 64}}; - VkPipelineViewportStateCreateInfo viewport_state{}; - viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewport_state.viewportCount = 1; - viewport_state.pViewports = &viewport; - viewport_state.scissorCount = 1; - viewport_state.pScissors = &scissor; - - VkPipelineMultisampleStateCreateInfo multisample_state{}; - multisample_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisample_state.pNext = nullptr; - multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - multisample_state.sampleShadingEnable = 0; - multisample_state.minSampleShading = 1.0; - multisample_state.pSampleMask = nullptr; - - VkPipelineRasterizationStateCreateInfo rasterization_state{}; - rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterization_state.polygonMode = VK_POLYGON_MODE_FILL; - rasterization_state.cullMode = VK_CULL_MODE_BACK_BIT; - rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rasterization_state.depthClampEnable = VK_FALSE; - rasterization_state.rasterizerDiscardEnable = VK_FALSE; - rasterization_state.depthBiasEnable = VK_FALSE; - rasterization_state.lineWidth = 1.0f; - - const VkPipelineLayoutObj pipeline_layout(m_device); - - { - VkGraphicsPipelineCreateInfo create_info{}; - create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - create_info.stageCount = 2; - create_info.pStages = stages; - create_info.pVertexInputState = &vertex_input_state; - create_info.pInputAssemblyState = &input_assembly_state; - create_info.pViewportState = &viewport_state; - create_info.pMultisampleState = &multisample_state; - create_info.pRasterizationState = &rasterization_state; - create_info.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; - create_info.layout = pipeline_layout.handle(); - create_info.renderPass = renderPass(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkVertexInputAttributeDescription-binding-00621"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineVertexInputStateCreateInfo-binding-00615"); - VkPipeline pipeline; - vkCreateGraphicsPipelines(m_device->device(), pipeline_cache, 1, &create_info, nullptr, &pipeline); - m_errorMonitor->VerifyFound(); - } - - vkDestroyPipelineCache(m_device->device(), pipeline_cache, nullptr); -} - -TEST_F(VkLayerTest, VUID_VkVertexInputAttributeDescription_offset_00622) { - TEST_DESCRIPTION( - "Test VUID-VkVertexInputAttributeDescription-offset-00622: offset must be less than or equal to " - "VkPhysicalDeviceLimits::maxVertexInputAttributeOffset"); - - EnableDeviceProfileLayer(); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - uint32_t maxVertexInputAttributeOffset = 0; - { - VkPhysicalDeviceProperties device_props = {}; - vkGetPhysicalDeviceProperties(gpu(), &device_props); - maxVertexInputAttributeOffset = device_props.limits.maxVertexInputAttributeOffset; - if (maxVertexInputAttributeOffset == 0xFFFFFFFF) { - // Attempt to artificially lower maximum offset - PFN_vkSetPhysicalDeviceLimitsEXT fpvkSetPhysicalDeviceLimitsEXT = - (PFN_vkSetPhysicalDeviceLimitsEXT)vkGetInstanceProcAddr(instance(), "vkSetPhysicalDeviceLimitsEXT"); - if (!fpvkSetPhysicalDeviceLimitsEXT) { - printf("%s All offsets are valid & device_profile_api not found; skipped.\n", kSkipPrefix); - return; - } - device_props.limits.maxVertexInputAttributeOffset = device_props.limits.maxVertexInputBindingStride - 2; - fpvkSetPhysicalDeviceLimitsEXT(gpu(), &device_props.limits); - maxVertexInputAttributeOffset = device_props.limits.maxVertexInputAttributeOffset; - } - } - ASSERT_NO_FATAL_FAILURE(InitState()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkPipelineCache pipeline_cache; - { - VkPipelineCacheCreateInfo create_info{}; - create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - - VkResult err = vkCreatePipelineCache(m_device->device(), &create_info, nullptr, &pipeline_cache); - ASSERT_VK_SUCCESS(err); - } - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineShaderStageCreateInfo stages[2]{{}}; - stages[0] = vs.GetStageCreateInfo(); - stages[1] = fs.GetStageCreateInfo(); - - VkVertexInputBindingDescription vertex_input_binding_description{}; - vertex_input_binding_description.binding = 0; - vertex_input_binding_description.stride = m_device->props.limits.maxVertexInputBindingStride; - vertex_input_binding_description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - // Test when offset is greater than maximum. - VkVertexInputAttributeDescription vertex_input_attribute_description{}; - vertex_input_attribute_description.format = VK_FORMAT_R8_UNORM; - vertex_input_attribute_description.offset = maxVertexInputAttributeOffset + 1; - - VkPipelineVertexInputStateCreateInfo vertex_input_state{}; - vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertex_input_state.pNext = nullptr; - vertex_input_state.vertexBindingDescriptionCount = 1; - vertex_input_state.pVertexBindingDescriptions = &vertex_input_binding_description; - vertex_input_state.vertexAttributeDescriptionCount = 1; - vertex_input_state.pVertexAttributeDescriptions = &vertex_input_attribute_description; - - VkPipelineInputAssemblyStateCreateInfo input_assembly_state{}; - input_assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; - - VkPipelineMultisampleStateCreateInfo multisample_state{}; - multisample_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisample_state.pNext = nullptr; - multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - multisample_state.sampleShadingEnable = 0; - multisample_state.minSampleShading = 1.0; - multisample_state.pSampleMask = nullptr; - - VkPipelineRasterizationStateCreateInfo rasterization_state{}; - rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterization_state.polygonMode = VK_POLYGON_MODE_FILL; - rasterization_state.cullMode = VK_CULL_MODE_BACK_BIT; - rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rasterization_state.depthClampEnable = VK_FALSE; - rasterization_state.rasterizerDiscardEnable = VK_TRUE; - rasterization_state.depthBiasEnable = VK_FALSE; - rasterization_state.lineWidth = 1.0f; - - const VkPipelineLayoutObj pipeline_layout(m_device); - - { - VkGraphicsPipelineCreateInfo create_info{}; - create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - create_info.stageCount = 2; - create_info.pStages = stages; - create_info.pVertexInputState = &vertex_input_state; - create_info.pInputAssemblyState = &input_assembly_state; - create_info.pViewportState = nullptr; // no viewport b/c rasterizer is disabled - create_info.pMultisampleState = &multisample_state; - create_info.pRasterizationState = &rasterization_state; - create_info.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; - create_info.layout = pipeline_layout.handle(); - create_info.renderPass = renderPass(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkVertexInputAttributeDescription-offset-00622"); - VkPipeline pipeline; - vkCreateGraphicsPipelines(m_device->device(), pipeline_cache, 1, &create_info, nullptr, &pipeline); - m_errorMonitor->VerifyFound(); - } - - vkDestroyPipelineCache(m_device->device(), pipeline_cache, nullptr); -} - -TEST_F(VkLayerTest, NullRenderPass) { - // Bind a NULL RenderPass - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkCmdBeginRenderPass: required parameter pRenderPassBegin specified as NULL"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - m_commandBuffer->begin(); - // Don't care about RenderPass handle b/c error should be flagged before - // that - vkCmdBeginRenderPass(m_commandBuffer->handle(), NULL, VK_SUBPASS_CONTENTS_INLINE); - - m_errorMonitor->VerifyFound(); - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, EndCommandBufferWithinRenderPass) { - TEST_DESCRIPTION("End a command buffer with an active render pass"); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "It is invalid to issue this call inside an active render pass"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkEndCommandBuffer(m_commandBuffer->handle()); - - m_errorMonitor->VerifyFound(); - - // End command buffer properly to avoid driver issues. This is safe -- the - // previous vkEndCommandBuffer should not have reached the driver. - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - - // TODO: Add test for VK_COMMAND_BUFFER_LEVEL_SECONDARY - // TODO: Add test for VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT -} - -TEST_F(VkLayerTest, FillBufferWithinRenderPass) { - // Call CmdFillBuffer within an active renderpass - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "It is invalid to issue this call inside an active render pass"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; - VkBufferObj dstBuffer; - dstBuffer.init_as_dst(*m_device, (VkDeviceSize)1024, reqs); - - m_commandBuffer->FillBuffer(dstBuffer.handle(), 0, 4, 0x11111111); - - m_errorMonitor->VerifyFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, InvalidDeviceMask) { - TEST_DESCRIPTION("Invalid deviceMask."); - SetTargetApiVersion(VK_API_VERSION_1_1); - - bool support_surface = false; -#ifdef VK_USE_PLATFORM_WIN32_KHR - if (InstanceExtensionSupported(VK_KHR_WIN32_SURFACE_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); - support_surface = true; - } else { - printf("%s VK_KHR_WIN32_SURFACE_EXTENSION_NAME extension not supported, skipping VkAcquireNextImageInfoKHR test\n", - kSkipPrefix); - } -#elif VK_USE_PLATFORM_XLIB_KHR - if (InstanceExtensionSupported(VK_KHR_XLIB_SURFACE_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); - support_surface = true; - } else { - printf("%s VK_KHR_XLIB_SURFACE_EXTENSION_NAME extension not supported, skipping VkAcquireNextImageInfoKHR test\n", - kSkipPrefix); - } -#elif defined(VK_USE_PLATFORM_ANDROID_KHR) && defined(VALIDATION_APK) - if (InstanceExtensionSupported(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); - support_surface = true; - } else { - printf("%s VK_KHR_ANDROID_SURFACE_EXTENSION_NAME extension not supported, skipping VkAcquireNextImageInfoKHR test\n", - kSkipPrefix); - } -#else - printf("%s VkSurface not supported, skipping VkAcquireNextImageInfoKHR test\n", kSkipPrefix); -#endif - - if (support_surface) { - if (InstanceExtensionSupported(VK_KHR_SURFACE_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_SURFACE_EXTENSION_NAME); - } else { - printf("%s VK_KHR_SURFACE_EXTENSION_NAM extension not supported, skipping VkAcquireNextImageInfoKHR test\n", - kSkipPrefix); - support_surface = false; - } - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if (DeviceValidationVersion() < VK_API_VERSION_1_1) { - printf("%s Device Groups requires Vulkan 1.1+, skipping test\n", kSkipPrefix); - return; - } - uint32_t physical_device_group_count = 0; - vkEnumeratePhysicalDeviceGroups(instance(), &physical_device_group_count, nullptr); - - if (physical_device_group_count == 0) { - printf("%s physical_device_group_count is 0, skipping test\n", kSkipPrefix); - return; - } - - if (support_surface) { - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); - } else { - printf("%s VK_KHR_SWAPCHAIN_EXTENSION_NAME extension not supported, skipping VkAcquireNextImageInfoKHR test\n", - kSkipPrefix); - support_surface = false; - } - } - - std::vector<VkPhysicalDeviceGroupProperties> physical_device_group(physical_device_group_count, - {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES}); - vkEnumeratePhysicalDeviceGroups(instance(), &physical_device_group_count, physical_device_group.data()); - VkDeviceGroupDeviceCreateInfo create_device_pnext = {}; - create_device_pnext.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO; - create_device_pnext.physicalDeviceCount = physical_device_group[0].physicalDeviceCount; - create_device_pnext.pPhysicalDevices = physical_device_group[0].physicalDevices; - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &create_device_pnext, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Test VkMemoryAllocateFlagsInfo - VkMemoryAllocateFlagsInfo alloc_flags_info = {}; - alloc_flags_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO; - alloc_flags_info.flags = VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT; - alloc_flags_info.deviceMask = 0xFFFFFFFF; - VkMemoryAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.pNext = &alloc_flags_info; - alloc_info.memoryTypeIndex = 0; - alloc_info.allocationSize = 32; - - VkDeviceMemory mem; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMemoryAllocateFlagsInfo-deviceMask-00675"); - vkAllocateMemory(m_device->device(), &alloc_info, NULL, &mem); - m_errorMonitor->VerifyFound(); - - alloc_flags_info.deviceMask = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMemoryAllocateFlagsInfo-deviceMask-00676"); - vkAllocateMemory(m_device->device(), &alloc_info, NULL, &mem); - m_errorMonitor->VerifyFound(); - - // Test VkDeviceGroupCommandBufferBeginInfo - VkDeviceGroupCommandBufferBeginInfo dev_grp_cmd_buf_info = {}; - dev_grp_cmd_buf_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO; - dev_grp_cmd_buf_info.deviceMask = 0xFFFFFFFF; - VkCommandBufferBeginInfo cmd_buf_info = {}; - cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - cmd_buf_info.pNext = &dev_grp_cmd_buf_info; - - m_commandBuffer->reset(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkDeviceGroupCommandBufferBeginInfo-deviceMask-00106"); - vkBeginCommandBuffer(m_commandBuffer->handle(), &cmd_buf_info); - m_errorMonitor->VerifyFound(); - - dev_grp_cmd_buf_info.deviceMask = 0; - m_commandBuffer->reset(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkDeviceGroupCommandBufferBeginInfo-deviceMask-00107"); - vkBeginCommandBuffer(m_commandBuffer->handle(), &cmd_buf_info); - m_errorMonitor->VerifyFound(); - - // Test VkDeviceGroupRenderPassBeginInfo - dev_grp_cmd_buf_info.deviceMask = 0x00000001; - m_commandBuffer->reset(); - vkBeginCommandBuffer(m_commandBuffer->handle(), &cmd_buf_info); - - VkDeviceGroupRenderPassBeginInfo dev_grp_rp_info = {}; - dev_grp_rp_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO; - dev_grp_rp_info.deviceMask = 0xFFFFFFFF; - m_renderPassBeginInfo.pNext = &dev_grp_rp_info; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDeviceGroupRenderPassBeginInfo-deviceMask-00905"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDeviceGroupRenderPassBeginInfo-deviceMask-00907"); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - m_errorMonitor->VerifyFound(); - - dev_grp_rp_info.deviceMask = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDeviceGroupRenderPassBeginInfo-deviceMask-00906"); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - m_errorMonitor->VerifyFound(); - - dev_grp_rp_info.deviceMask = 0x00000001; - dev_grp_rp_info.deviceRenderAreaCount = physical_device_group[0].physicalDeviceCount + 1; - std::vector<VkRect2D> device_render_areas(dev_grp_rp_info.deviceRenderAreaCount, m_renderPassBeginInfo.renderArea); - dev_grp_rp_info.pDeviceRenderAreas = device_render_areas.data(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkDeviceGroupRenderPassBeginInfo-deviceRenderAreaCount-00908"); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - m_errorMonitor->VerifyFound(); - - // Test vkCmdSetDeviceMask() - vkCmdSetDeviceMask(m_commandBuffer->handle(), 0x00000001); - - dev_grp_rp_info.deviceRenderAreaCount = physical_device_group[0].physicalDeviceCount; - vkCmdBeginRenderPass(m_commandBuffer->handle(), &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetDeviceMask-deviceMask-00108"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetDeviceMask-deviceMask-00110"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetDeviceMask-deviceMask-00111"); - vkCmdSetDeviceMask(m_commandBuffer->handle(), 0xFFFFFFFF); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetDeviceMask-deviceMask-00109"); - vkCmdSetDeviceMask(m_commandBuffer->handle(), 0); - m_errorMonitor->VerifyFound(); - - VkSemaphoreCreateInfo semaphore_create_info = {}; - semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - VkSemaphore semaphore; - ASSERT_VK_SUCCESS(vkCreateSemaphore(m_device->device(), &semaphore_create_info, nullptr, &semaphore)); - VkSemaphore semaphore2; - ASSERT_VK_SUCCESS(vkCreateSemaphore(m_device->device(), &semaphore_create_info, nullptr, &semaphore2)); - VkFenceCreateInfo fence_create_info = {}; - fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - VkFence fence; - ASSERT_VK_SUCCESS(vkCreateFence(m_device->device(), &fence_create_info, nullptr, &fence)); - - if (support_surface) { - // Test VkAcquireNextImageInfoKHR - ASSERT_NO_FATAL_FAILURE(InitSwapchain()); - - uint32_t imageIndex = 0; - VkAcquireNextImageInfoKHR acquire_next_image_info = {}; - acquire_next_image_info.sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR; - acquire_next_image_info.semaphore = semaphore; - acquire_next_image_info.swapchain = m_swapchain; - acquire_next_image_info.fence = fence; - acquire_next_image_info.deviceMask = 0xFFFFFFFF; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkAcquireNextImageInfoKHR-deviceMask-01290"); - vkAcquireNextImage2KHR(m_device->device(), &acquire_next_image_info, &imageIndex); - m_errorMonitor->VerifyFound(); - - vkWaitForFences(m_device->device(), 1, &fence, VK_TRUE, std::numeric_limits<int>::max()); - vkResetFences(m_device->device(), 1, &fence); - - acquire_next_image_info.semaphore = semaphore2; - acquire_next_image_info.deviceMask = 0; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkAcquireNextImageInfoKHR-deviceMask-01291"); - vkAcquireNextImage2KHR(m_device->device(), &acquire_next_image_info, &imageIndex); - m_errorMonitor->VerifyFound(); - DestroySwapchain(); - } - - // Test VkDeviceGroupSubmitInfo - VkDeviceGroupSubmitInfo device_group_submit_info = {}; - device_group_submit_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO; - device_group_submit_info.commandBufferCount = 1; - std::array<uint32_t, 1> command_buffer_device_masks = {0xFFFFFFFF}; - device_group_submit_info.pCommandBufferDeviceMasks = command_buffer_device_masks.data(); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.pNext = &device_group_submit_info; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - - m_commandBuffer->reset(); - vkBeginCommandBuffer(m_commandBuffer->handle(), &cmd_buf_info); - vkEndCommandBuffer(m_commandBuffer->handle()); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkDeviceGroupSubmitInfo-pCommandBufferDeviceMasks-00086"); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - vkQueueWaitIdle(m_device->m_queue); - - vkWaitForFences(m_device->device(), 1, &fence, VK_TRUE, std::numeric_limits<int>::max()); - vkDestroyFence(m_device->device(), fence, nullptr); - vkDestroySemaphore(m_device->device(), semaphore, nullptr); - vkDestroySemaphore(m_device->device(), semaphore2, nullptr); -} - -TEST_F(VkLayerTest, UpdateBufferWithinRenderPass) { - // Call CmdUpdateBuffer within an active renderpass - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "It is invalid to issue this call inside an active render pass"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; - VkBufferObj dstBuffer; - dstBuffer.init_as_dst(*m_device, (VkDeviceSize)1024, reqs); - - VkDeviceSize dstOffset = 0; - uint32_t Data[] = {1, 2, 3, 4, 5, 6, 7, 8}; - VkDeviceSize dataSize = sizeof(Data) / sizeof(uint32_t); - vkCmdUpdateBuffer(m_commandBuffer->handle(), dstBuffer.handle(), dstOffset, dataSize, &Data); - - m_errorMonitor->VerifyFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, ClearColorImageWithBadRange) { - TEST_DESCRIPTION("Record clear color with an invalid VkImageSubresourceRange"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkImageObj image(m_device); - image.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(image.create_info().arrayLayers == 1); - ASSERT_TRUE(image.initialized()); - image.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - const VkClearColorValue clear_color = {{0.0f, 0.0f, 0.0f, 1.0f}}; - - m_commandBuffer->begin(); - const auto cb_handle = m_commandBuffer->handle(); - - // Try baseMipLevel >= image.mipLevels with VK_REMAINING_MIP_LEVELS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearColorImage-baseMipLevel-01470"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 1, VK_REMAINING_MIP_LEVELS, 0, 1}; - vkCmdClearColorImage(cb_handle, image.handle(), image.Layout(), &clear_color, 1, &range); - m_errorMonitor->VerifyFound(); - } - - // Try baseMipLevel >= image.mipLevels without VK_REMAINING_MIP_LEVELS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearColorImage-baseMipLevel-01470"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearColorImage-pRanges-01692"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 0, 1}; - vkCmdClearColorImage(cb_handle, image.handle(), image.Layout(), &clear_color, 1, &range); - m_errorMonitor->VerifyFound(); - } - - // Try levelCount = 0 - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearColorImage-pRanges-01692"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 0, 1}; - vkCmdClearColorImage(cb_handle, image.handle(), image.Layout(), &clear_color, 1, &range); - m_errorMonitor->VerifyFound(); - } - - // Try baseMipLevel + levelCount > image.mipLevels - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearColorImage-pRanges-01692"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 2, 0, 1}; - vkCmdClearColorImage(cb_handle, image.handle(), image.Layout(), &clear_color, 1, &range); - m_errorMonitor->VerifyFound(); - } - - // Try baseArrayLayer >= image.arrayLayers with VK_REMAINING_ARRAY_LAYERS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearColorImage-baseArrayLayer-01472"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 1, VK_REMAINING_ARRAY_LAYERS}; - vkCmdClearColorImage(cb_handle, image.handle(), image.Layout(), &clear_color, 1, &range); - m_errorMonitor->VerifyFound(); - } - - // Try baseArrayLayer >= image.arrayLayers without VK_REMAINING_ARRAY_LAYERS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearColorImage-baseArrayLayer-01472"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearColorImage-pRanges-01693"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 1, 1}; - vkCmdClearColorImage(cb_handle, image.handle(), image.Layout(), &clear_color, 1, &range); - m_errorMonitor->VerifyFound(); - } - - // Try layerCount = 0 - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearColorImage-pRanges-01693"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 0}; - vkCmdClearColorImage(cb_handle, image.handle(), image.Layout(), &clear_color, 1, &range); - m_errorMonitor->VerifyFound(); - } - - // Try baseArrayLayer + layerCount > image.arrayLayers - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearColorImage-pRanges-01693"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 2}; - vkCmdClearColorImage(cb_handle, image.handle(), image.Layout(), &clear_color, 1, &range); - m_errorMonitor->VerifyFound(); - } -} - -TEST_F(VkLayerTest, ClearDepthStencilWithBadRange) { - TEST_DESCRIPTION("Record clear depth with an invalid VkImageSubresourceRange"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const auto depth_format = FindSupportedDepthStencilFormat(gpu()); - if (!depth_format) { - printf("%s No Depth + Stencil format found. Skipped.\n", kSkipPrefix); - return; - } - - VkImageObj image(m_device); - image.Init(32, 32, 1, depth_format, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(image.create_info().arrayLayers == 1); - ASSERT_TRUE(image.initialized()); - const VkImageAspectFlags ds_aspect = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - image.SetLayout(ds_aspect, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - const VkClearDepthStencilValue clear_value = {}; - - m_commandBuffer->begin(); - const auto cb_handle = m_commandBuffer->handle(); - - // Try baseMipLevel >= image.mipLevels with VK_REMAINING_MIP_LEVELS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearDepthStencilImage-baseMipLevel-01474"); - const VkImageSubresourceRange range = {ds_aspect, 1, VK_REMAINING_MIP_LEVELS, 0, 1}; - vkCmdClearDepthStencilImage(cb_handle, image.handle(), image.Layout(), &clear_value, 1, &range); - m_errorMonitor->VerifyFound(); - } - - // Try baseMipLevel >= image.mipLevels without VK_REMAINING_MIP_LEVELS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearDepthStencilImage-baseMipLevel-01474"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearDepthStencilImage-pRanges-01694"); - const VkImageSubresourceRange range = {ds_aspect, 1, 1, 0, 1}; - vkCmdClearDepthStencilImage(cb_handle, image.handle(), image.Layout(), &clear_value, 1, &range); - m_errorMonitor->VerifyFound(); - } - - // Try levelCount = 0 - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearDepthStencilImage-pRanges-01694"); - const VkImageSubresourceRange range = {ds_aspect, 0, 0, 0, 1}; - vkCmdClearDepthStencilImage(cb_handle, image.handle(), image.Layout(), &clear_value, 1, &range); - m_errorMonitor->VerifyFound(); - } - - // Try baseMipLevel + levelCount > image.mipLevels - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearDepthStencilImage-pRanges-01694"); - const VkImageSubresourceRange range = {ds_aspect, 0, 2, 0, 1}; - vkCmdClearDepthStencilImage(cb_handle, image.handle(), image.Layout(), &clear_value, 1, &range); - m_errorMonitor->VerifyFound(); - } - - // Try baseArrayLayer >= image.arrayLayers with VK_REMAINING_ARRAY_LAYERS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdClearDepthStencilImage-baseArrayLayer-01476"); - const VkImageSubresourceRange range = {ds_aspect, 0, 1, 1, VK_REMAINING_ARRAY_LAYERS}; - vkCmdClearDepthStencilImage(cb_handle, image.handle(), image.Layout(), &clear_value, 1, &range); - m_errorMonitor->VerifyFound(); - } - - // Try baseArrayLayer >= image.arrayLayers without VK_REMAINING_ARRAY_LAYERS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdClearDepthStencilImage-baseArrayLayer-01476"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearDepthStencilImage-pRanges-01695"); - const VkImageSubresourceRange range = {ds_aspect, 0, 1, 1, 1}; - vkCmdClearDepthStencilImage(cb_handle, image.handle(), image.Layout(), &clear_value, 1, &range); - m_errorMonitor->VerifyFound(); - } - - // Try layerCount = 0 - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearDepthStencilImage-pRanges-01695"); - const VkImageSubresourceRange range = {ds_aspect, 0, 1, 0, 0}; - vkCmdClearDepthStencilImage(cb_handle, image.handle(), image.Layout(), &clear_value, 1, &range); - m_errorMonitor->VerifyFound(); - } - - // Try baseArrayLayer + layerCount > image.arrayLayers - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearDepthStencilImage-pRanges-01695"); - const VkImageSubresourceRange range = {ds_aspect, 0, 1, 0, 2}; - vkCmdClearDepthStencilImage(cb_handle, image.handle(), image.Layout(), &clear_value, 1, &range); - m_errorMonitor->VerifyFound(); - } -} - -TEST_F(VkLayerTest, ClearColorImageWithinRenderPass) { - // Call CmdClearColorImage within an active RenderPass - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "It is invalid to issue this call inside an active render pass"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - VkClearColorValue clear_color; - memset(clear_color.uint32, 0, sizeof(uint32_t) * 4); - const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; - const int32_t tex_width = 32; - const int32_t tex_height = 32; - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = tex_format; - image_create_info.extent.width = tex_width; - image_create_info.extent.height = tex_height; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - - vk_testing::Image dstImage; - dstImage.init(*m_device, (const VkImageCreateInfo &)image_create_info); - - const VkImageSubresourceRange range = vk_testing::Image::subresource_range(image_create_info, VK_IMAGE_ASPECT_COLOR_BIT); - - vkCmdClearColorImage(m_commandBuffer->handle(), dstImage.handle(), VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &range); - - m_errorMonitor->VerifyFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, ClearDepthStencilImageErrors) { - // Hit errors related to vkCmdClearDepthStencilImage() - // 1. Use an image that doesn't have VK_IMAGE_USAGE_TRANSFER_DST_BIT set - // 2. Call CmdClearDepthStencilImage within an active RenderPass - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - auto depth_format = FindSupportedDepthStencilFormat(gpu()); - if (!depth_format) { - printf("%s No Depth + Stencil format found. Skipped.\n", kSkipPrefix); - return; - } - - VkClearDepthStencilValue clear_value = {0}; - VkMemoryPropertyFlags reqs = 0; - VkImageCreateInfo image_create_info = vk_testing::Image::create_info(); - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = depth_format; - image_create_info.extent.width = 64; - image_create_info.extent.height = 64; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - // Error here is that VK_IMAGE_USAGE_TRANSFER_DST_BIT is excluded for DS image that we'll call Clear on below - image_create_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - - vk_testing::Image dst_image_bad_usage; - dst_image_bad_usage.init(*m_device, (const VkImageCreateInfo &)image_create_info, reqs); - const VkImageSubresourceRange range = vk_testing::Image::subresource_range(image_create_info, VK_IMAGE_ASPECT_DEPTH_BIT); - - m_commandBuffer->begin(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearDepthStencilImage-image-00009"); - vkCmdClearDepthStencilImage(m_commandBuffer->handle(), dst_image_bad_usage.handle(), VK_IMAGE_LAYOUT_GENERAL, &clear_value, 1, - &range); - m_errorMonitor->VerifyFound(); - - // Fix usage for next test case - image_create_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_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_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearDepthStencilImage-renderpass"); - vkCmdClearDepthStencilImage(m_commandBuffer->handle(), dst_image.handle(), VK_IMAGE_LAYOUT_GENERAL, &clear_value, 1, &range); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, ClearColorAttachmentsOutsideRenderPass) { - // Call CmdClearAttachmentss outside of an active RenderPass - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkCmdClearAttachments(): This call must be issued inside an active render pass"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Start no RenderPass - m_commandBuffer->begin(); - - VkClearAttachment color_attachment; - color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - color_attachment.clearValue.color.float32[0] = 0; - color_attachment.clearValue.color.float32[1] = 0; - color_attachment.clearValue.color.float32[2] = 0; - color_attachment.clearValue.color.float32[3] = 0; - color_attachment.colorAttachment = 0; - VkClearRect clear_rect = {{{0, 0}, {32, 32}}}; - vkCmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, BufferMemoryBarrierNoBuffer) { - // Try to add a buffer memory barrier with no buffer. - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "required parameter pBufferMemoryBarriers[0].buffer specified as VK_NULL_HANDLE"); - - ASSERT_NO_FATAL_FAILURE(Init()); - m_commandBuffer->begin(); - - VkBufferMemoryBarrier buf_barrier = {}; - buf_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - buf_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; - buf_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - buf_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - buf_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - buf_barrier.buffer = VK_NULL_HANDLE; - buf_barrier.offset = 0; - buf_barrier.size = VK_WHOLE_SIZE; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, - 1, &buf_barrier, 0, nullptr); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, InvalidBarriers) { - TEST_DESCRIPTION("A variety of ways to get VK_INVALID_BARRIER "); - - ASSERT_NO_FATAL_FAILURE(Init()); - auto depth_format = FindSupportedDepthStencilFormat(gpu()); - if (!depth_format) { - printf("%s No Depth + Stencil format found. Skipped.\n", kSkipPrefix); - return; - } - // Add a token self-dependency for this test to avoid unexpected errors - m_addRenderPassSelfDependency = true; - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - m_commandBuffer->begin(); - - // Use image unbound to memory in barrier - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - " used with no memory bound. Memory should be bound by calling vkBindImageMemory()"); - vk_testing::Image unbound_image; - auto unbound_image_info = vk_testing::Image::create_info(); - unbound_image_info.format = VK_FORMAT_B8G8R8A8_UNORM; - unbound_image_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; - unbound_image.init_no_mem(*m_device, unbound_image_info); - auto unbound_subresource = vk_testing::Image::subresource_range(unbound_image_info, VK_IMAGE_ASPECT_COLOR_BIT); - auto unbound_image_barrier = unbound_image.image_memory_barrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, unbound_subresource); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, - nullptr, 0, nullptr, 1, &unbound_image_barrier); - m_errorMonitor->VerifyFound(); - - // Use buffer unbound to memory in barrier - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - " used with no memory bound. Memory should be bound by calling vkBindBufferMemory()"); - VkBufferObj unbound_buffer; - auto unbound_buffer_info = VkBufferObj::create_info(16, VK_IMAGE_USAGE_TRANSFER_DST_BIT); - unbound_buffer.init_no_mem(*m_device, unbound_buffer_info); - auto unbound_buffer_barrier = unbound_buffer.buffer_memory_barrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, 0, 16); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, - nullptr, 1, &unbound_buffer_barrier, 0, nullptr); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-newLayout-01198"); - VkImageObj image(m_device); - image.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - VkImageMemoryBarrier img_barrier = {}; - img_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - img_barrier.pNext = NULL; - img_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - img_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - img_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - // New layout can't be UNDEFINED - img_barrier.newLayout = VK_IMAGE_LAYOUT_UNDEFINED; - img_barrier.image = m_renderTargets[0]->handle(); - img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - img_barrier.subresourceRange.baseArrayLayer = 0; - img_barrier.subresourceRange.baseMipLevel = 0; - img_barrier.subresourceRange.layerCount = 1; - img_barrier.subresourceRange.levelCount = 1; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - - // Transition image to color attachment optimal - img_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - - // TODO: this looks vestigal or incomplete... - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - img_barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - // Can't send buffer memory barrier during a render pass - vkCmdEndRenderPass(m_commandBuffer->handle()); - - // Duplicate barriers that change layout - img_barrier.image = image.handle(); - img_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - VkImageMemoryBarrier img_barriers[2] = {img_barrier, img_barrier}; - - // Transitions from UNDEFINED are valid, even if duplicated - m_errorMonitor->ExpectSuccess(); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 2, - img_barriers); - m_errorMonitor->VerifyNotFound(); - - // Duplication of layout transitions (not from undefined) are not valid - img_barriers[0].oldLayout = VK_IMAGE_LAYOUT_GENERAL; - img_barriers[0].newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - img_barriers[1].oldLayout = img_barriers[0].oldLayout; - img_barriers[1].newLayout = img_barriers[0].newLayout; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-oldLayout-01197"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 2, - img_barriers); - m_errorMonitor->VerifyFound(); - - VkBufferObj buffer; - VkMemoryPropertyFlags mem_reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; - buffer.init_as_src_and_dst(*m_device, 256, mem_reqs); - VkBufferMemoryBarrier buf_barrier = {}; - buf_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - buf_barrier.pNext = NULL; - buf_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - buf_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - buf_barrier.buffer = buffer.handle(); - buf_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - buf_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - buf_barrier.offset = 0; - buf_barrier.size = VK_WHOLE_SIZE; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferMemoryBarrier-offset-01187"); - // Exceed the buffer size - buf_barrier.offset = buffer.create_info().size + 1; - // Offset greater than total size - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 1, &buf_barrier, 0, - nullptr); - m_errorMonitor->VerifyFound(); - buf_barrier.offset = 0; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferMemoryBarrier-size-01189"); - buf_barrier.size = buffer.create_info().size + 1; - // Size greater than total size - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 1, &buf_barrier, 0, - nullptr); - m_errorMonitor->VerifyFound(); - - // Now exercise barrier aspect bit errors, first DS - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageSubresource-aspectMask-parameter"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-image-01207"); - VkDepthStencilObj ds_image(m_device); - ds_image.Init(m_device, 128, 128, depth_format); - ASSERT_TRUE(ds_image.initialized()); - img_barrier.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - img_barrier.image = ds_image.handle(); - - // Not having DEPTH or STENCIL set is an error - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - - // Having only one of depth or stencil set for DS image is an error - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-image-01207"); - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - - // Having anything other than DEPTH and STENCIL is an error - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageSubresource-aspectMask-parameter"); - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_COLOR_BIT; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - - // Now test depth-only - VkFormatProperties format_props; - vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), VK_FORMAT_D16_UNORM, &format_props); - if (format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) { - VkDepthStencilObj d_image(m_device); - d_image.Init(m_device, 128, 128, VK_FORMAT_D16_UNORM); - ASSERT_TRUE(d_image.initialized()); - img_barrier.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - img_barrier.image = d_image.handle(); - - // DEPTH bit must be set - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Depth-only image formats must have the VK_IMAGE_ASPECT_DEPTH_BIT set."); - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - - // No bits other than DEPTH may be set - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Depth-only image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT set."); - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_COLOR_BIT; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - } - - // Now test stencil-only - vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), VK_FORMAT_S8_UINT, &format_props); - if (format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) { - VkDepthStencilObj s_image(m_device); - s_image.Init(m_device, 128, 128, VK_FORMAT_S8_UINT); - ASSERT_TRUE(s_image.initialized()); - img_barrier.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - img_barrier.image = s_image.handle(); - // Use of COLOR aspect on depth image is error - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Stencil-only image formats must have the VK_IMAGE_ASPECT_STENCIL_BIT set."); - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - } - - // Finally test color - VkImageObj c_image(m_device); - c_image.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(c_image.initialized()); - img_barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - img_barrier.image = c_image.handle(); - - // COLOR bit must be set - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Color image formats must have the VK_IMAGE_ASPECT_COLOR_BIT set."); - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - - // No bits other than COLOR may be set - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Color image formats must have ONLY the VK_IMAGE_ASPECT_COLOR_BIT set."); - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - - // A barrier's new and old VkImageLayout must be compatible with an image's VkImageUsageFlags. - { - VkImageObj img_color(m_device); - img_color.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(img_color.initialized()); - - VkImageObj img_ds(m_device); - img_ds.Init(128, 128, 1, depth_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(img_ds.initialized()); - - VkImageObj img_xfer_src(m_device); - img_xfer_src.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(img_xfer_src.initialized()); - - VkImageObj img_xfer_dst(m_device); - img_xfer_dst.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(img_xfer_dst.initialized()); - - VkImageObj img_sampled(m_device); - img_sampled.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(img_sampled.initialized()); - - VkImageObj img_input(m_device); - img_input.Init(128, 128, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(img_input.initialized()); - - const struct { - VkImageObj &image_obj; - VkImageLayout bad_layout; - std::string msg_code; - } bad_buffer_layouts[] = { - // clang-format off - // images _without_ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT - {img_ds, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01208"}, - {img_xfer_src, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01208"}, - {img_xfer_dst, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01208"}, - {img_sampled, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01208"}, - {img_input, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01208"}, - // images _without_ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT - {img_color, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01209"}, - {img_xfer_src, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01209"}, - {img_xfer_dst, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01209"}, - {img_sampled, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01209"}, - {img_input, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01209"}, - {img_color, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01210"}, - {img_xfer_src, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01210"}, - {img_xfer_dst, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01210"}, - {img_sampled, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01210"}, - {img_input, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01210"}, - // images _without_ VK_IMAGE_USAGE_SAMPLED_BIT or VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT - {img_color, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01211"}, - {img_ds, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01211"}, - {img_xfer_src, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01211"}, - {img_xfer_dst, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01211"}, - // images _without_ VK_IMAGE_USAGE_TRANSFER_SRC_BIT - {img_color, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01212"}, - {img_ds, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01212"}, - {img_xfer_dst, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01212"}, - {img_sampled, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01212"}, - {img_input, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01212"}, - // images _without_ VK_IMAGE_USAGE_TRANSFER_DST_BIT - {img_color, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01213"}, - {img_ds, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01213"}, - {img_xfer_src, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01213"}, - {img_sampled, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01213"}, - {img_input, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01213"}, - // clang-format on - }; - const uint32_t layout_count = sizeof(bad_buffer_layouts) / sizeof(bad_buffer_layouts[0]); - - for (uint32_t i = 0; i < layout_count; ++i) { - img_barrier.image = bad_buffer_layouts[i].image_obj.handle(); - const VkImageUsageFlags usage = bad_buffer_layouts[i].image_obj.usage(); - img_barrier.subresourceRange.aspectMask = (usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) - ? (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) - : VK_IMAGE_ASPECT_COLOR_BIT; - - img_barrier.oldLayout = bad_buffer_layouts[i].bad_layout; - img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, bad_buffer_layouts[i].msg_code); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - - img_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - img_barrier.newLayout = bad_buffer_layouts[i].bad_layout; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, bad_buffer_layouts[i].msg_code); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, - &img_barrier); - m_errorMonitor->VerifyFound(); - } - - img_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - } - // Attempt barrier where srcAccessMask is not supported by srcStageMask - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-pMemoryBarriers-01184"); - // Have lower-order bit that's supported (shader write), but higher-order bit not supported to verify multi-bit validation - buf_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT; - buf_barrier.offset = 0; - buf_barrier.size = VK_WHOLE_SIZE; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 1, &buf_barrier, 0, nullptr); - m_errorMonitor->VerifyFound(); - // Attempt barrier where dsAccessMask is not supported by dstStageMask - buf_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-pMemoryBarriers-01185"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 1, &buf_barrier, 0, - nullptr); - m_errorMonitor->VerifyFound(); - - // Attempt to mismatch barriers/waitEvents calls with incompatible queues - // Create command pool with incompatible queueflags - const std::vector<VkQueueFamilyProperties> queue_props = m_device->queue_props; - uint32_t queue_family_index = m_device->QueueFamilyMatching(VK_QUEUE_GRAPHICS_BIT, VK_QUEUE_COMPUTE_BIT); - if (queue_family_index == UINT32_MAX) { - printf("%s No non-compute queue supporting graphics found; skipped.\n", kSkipPrefix); - return; // NOTE: this exits the test function! - } - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-srcStageMask-01183"); - - VkCommandPoolObj command_pool(m_device, queue_family_index, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); - VkCommandBufferObj bad_command_buffer(m_device, &command_pool); - - bad_command_buffer.begin(); - buf_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - // Set two bits that should both be supported as a bonus positive check - buf_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT; - vkCmdPipelineBarrier(bad_command_buffer.handle(), VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 1, &buf_barrier, 0, nullptr); - m_errorMonitor->VerifyFound(); - - // Check for error for trying to wait on pipeline stage not supported by this queue. Specifically since our queue is not a - // compute queue, vkCmdWaitEvents cannot have it's source stage mask be VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdWaitEvents-srcStageMask-01164"); - VkEvent event; - VkEventCreateInfo event_create_info{}; - event_create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - vkCreateEvent(m_device->device(), &event_create_info, nullptr, &event); - vkCmdWaitEvents(bad_command_buffer.handle(), 1, &event, /*source stage mask*/ VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, nullptr, 0, nullptr, 0, nullptr); - m_errorMonitor->VerifyFound(); - bad_command_buffer.end(); - - vkDestroyEvent(m_device->device(), event, nullptr); -} - -// Helpers for the tests below -static void ValidOwnershipTransferOp(ErrorMonitor *monitor, VkCommandBufferObj *cb, VkPipelineStageFlags src_stages, - VkPipelineStageFlags dst_stages, const VkBufferMemoryBarrier *buf_barrier, - const VkImageMemoryBarrier *img_barrier) { - monitor->ExpectSuccess(); - cb->begin(); - uint32_t num_buf_barrier = (buf_barrier) ? 1 : 0; - uint32_t num_img_barrier = (img_barrier) ? 1 : 0; - cb->PipelineBarrier(src_stages, dst_stages, 0, 0, nullptr, num_buf_barrier, buf_barrier, num_img_barrier, img_barrier); - cb->end(); - cb->QueueCommandBuffer(); // Implicitly waits - monitor->VerifyNotFound(); -} -static void ValidOwnershipTransfer(ErrorMonitor *monitor, VkCommandBufferObj *cb_from, VkCommandBufferObj *cb_to, - VkPipelineStageFlags src_stages, VkPipelineStageFlags dst_stages, - const VkBufferMemoryBarrier *buf_barrier, const VkImageMemoryBarrier *img_barrier) { - ValidOwnershipTransferOp(monitor, cb_from, src_stages, dst_stages, buf_barrier, img_barrier); - ValidOwnershipTransferOp(monitor, cb_to, src_stages, dst_stages, buf_barrier, img_barrier); -} - -TEST_F(VkPositiveLayerTest, OwnershipTranfersImage) { - TEST_DESCRIPTION("Valid image ownership transfers that shouldn't create errors"); - ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - - uint32_t no_gfx = m_device->QueueFamilyWithoutCapabilities(VK_QUEUE_GRAPHICS_BIT); - if (no_gfx == UINT32_MAX) { - printf("%s Required queue families not present (non-graphics capable required).\n", kSkipPrefix); - return; - } - VkQueueObj *no_gfx_queue = m_device->queue_family_queues(no_gfx)[0].get(); - - VkCommandPoolObj no_gfx_pool(m_device, no_gfx, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); - VkCommandBufferObj no_gfx_cb(m_device, &no_gfx_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, no_gfx_queue); - - // Create an "exclusive" image owned by the graphics queue. - VkImageObj image(m_device); - VkFlags image_use = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - image.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, image_use, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - auto image_subres = image.subresource_range(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1); - auto image_barrier = image.image_memory_barrier(0, 0, image.Layout(), image.Layout(), image_subres); - image_barrier.srcQueueFamilyIndex = m_device->graphics_queue_node_index_; - image_barrier.dstQueueFamilyIndex = no_gfx; - - ValidOwnershipTransfer(m_errorMonitor, m_commandBuffer, &no_gfx_cb, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, nullptr, &image_barrier); - - // Change layouts while changing ownership - image_barrier.srcQueueFamilyIndex = no_gfx; - image_barrier.dstQueueFamilyIndex = m_device->graphics_queue_node_index_; - image_barrier.oldLayout = image.Layout(); - // Make sure the new layout is different from the old - if (image_barrier.oldLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { - image_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } else { - image_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - } - - ValidOwnershipTransfer(m_errorMonitor, &no_gfx_cb, m_commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, nullptr, &image_barrier); -} - -TEST_F(VkPositiveLayerTest, OwnershipTranfersBuffer) { - TEST_DESCRIPTION("Valid buffer ownership transfers that shouldn't create errors"); - ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - - uint32_t no_gfx = m_device->QueueFamilyWithoutCapabilities(VK_QUEUE_GRAPHICS_BIT); - if (no_gfx == UINT32_MAX) { - printf("%s Required queue families not present (non-graphics capable required).\n", kSkipPrefix); - return; - } - VkQueueObj *no_gfx_queue = m_device->queue_family_queues(no_gfx)[0].get(); - - VkCommandPoolObj no_gfx_pool(m_device, no_gfx, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); - VkCommandBufferObj no_gfx_cb(m_device, &no_gfx_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, no_gfx_queue); - - // Create a buffer - const VkDeviceSize buffer_size = 256; - uint8_t data[buffer_size] = {0xFF}; - VkConstantBufferObj buffer(m_device, buffer_size, data, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT); - ASSERT_TRUE(buffer.initialized()); - auto buffer_barrier = buffer.buffer_memory_barrier(0, 0, 0, VK_WHOLE_SIZE); - - // Let gfx own it. - buffer_barrier.srcQueueFamilyIndex = m_device->graphics_queue_node_index_; - buffer_barrier.dstQueueFamilyIndex = m_device->graphics_queue_node_index_; - ValidOwnershipTransferOp(m_errorMonitor, m_commandBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - &buffer_barrier, nullptr); - - // Transfer it to non-gfx - buffer_barrier.dstQueueFamilyIndex = no_gfx; - ValidOwnershipTransfer(m_errorMonitor, m_commandBuffer, &no_gfx_cb, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, &buffer_barrier, nullptr); - - // Transfer it to gfx - buffer_barrier.srcQueueFamilyIndex = no_gfx; - buffer_barrier.dstQueueFamilyIndex = m_device->graphics_queue_node_index_; - ValidOwnershipTransfer(m_errorMonitor, &no_gfx_cb, m_commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, &buffer_barrier, nullptr); -} - -class BarrierQueueFamilyTestHelper { - public: - struct QueueFamilyObjs { - uint32_t index; - // We would use std::unique_ptr, but this triggers a compiler error on older compilers - VkQueueObj *queue = nullptr; - VkCommandPoolObj *command_pool = nullptr; - VkCommandBufferObj *command_buffer = nullptr; - VkCommandBufferObj *command_buffer2 = nullptr; - ~QueueFamilyObjs() { - delete command_buffer2; - delete command_buffer; - delete command_pool; - delete queue; - } - - void Init(VkDeviceObj *device, uint32_t qf_index, VkQueue qf_queue, VkCommandPoolCreateFlags cp_flags) { - index = qf_index; - queue = new VkQueueObj(qf_queue, qf_index); - command_pool = new VkCommandPoolObj(device, qf_index, cp_flags); - command_buffer = new VkCommandBufferObj(device, command_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, queue); - command_buffer2 = new VkCommandBufferObj(device, command_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, queue); - }; - }; - - struct Context { - VkLayerTest *layer_test; - uint32_t default_index; - std::unordered_map<uint32_t, QueueFamilyObjs> queue_families; - Context(VkLayerTest *test, const std::vector<uint32_t> &queue_family_indices) : layer_test(test) { - if (0 == queue_family_indices.size()) { - return; // This is invalid - } - VkDeviceObj *device_obj = layer_test->DeviceObj(); - queue_families.reserve(queue_family_indices.size()); - default_index = queue_family_indices[0]; - for (auto qfi : queue_family_indices) { - VkQueue queue = device_obj->queue_family_queues(qfi)[0]->handle(); - queue_families.emplace(std::make_pair(qfi, QueueFamilyObjs())); - queue_families[qfi].Init(device_obj, qfi, queue, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); - } - Reset(); - } - void Reset() { - layer_test->DeviceObj()->wait(); - for (auto &qf : queue_families) { - vkResetCommandPool(layer_test->device(), qf.second.command_pool->handle(), 0); - } - } - }; - - BarrierQueueFamilyTestHelper(Context *context) : context_(context), image_(context->layer_test->DeviceObj()) {} - // Init with queue families non-null for CONCURRENT sharing mode (which requires them) - void Init(std::vector<uint32_t> *families) { - VkDeviceObj *device_obj = context_->layer_test->DeviceObj(); - image_.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0, families); - ASSERT_TRUE(image_.initialized()); - - image_barrier_ = - image_.image_memory_barrier(VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_TRANSFER_READ_BIT, image_.Layout(), image_.Layout(), - image_.subresource_range(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1)); - - VkMemoryPropertyFlags mem_prop = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - buffer_.init_as_src_and_dst(*device_obj, 256, mem_prop, families); - ASSERT_TRUE(buffer_.initialized()); - buffer_barrier_ = buffer_.buffer_memory_barrier(VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_TRANSFER_READ_BIT, 0, VK_WHOLE_SIZE); - } - - QueueFamilyObjs *GetQueueFamilyInfo(Context *context, uint32_t qfi) { - QueueFamilyObjs *qf; - - auto qf_it = context->queue_families.find(qfi); - if (qf_it != context->queue_families.end()) { - qf = &(qf_it->second); - } else { - qf = &(context->queue_families[context->default_index]); - } - return qf; - } - enum Modifier { - NONE, - DOUBLE_RECORD, - DOUBLE_COMMAND_BUFFER, - }; - - void operator()(std::string img_err, std::string buf_err, uint32_t src, uint32_t dst, bool positive = false, - uint32_t queue_family_index = kInvalidQueueFamily, Modifier mod = Modifier::NONE) { - auto monitor = context_->layer_test->Monitor(); - monitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT, img_err); - monitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT, buf_err); - - image_barrier_.srcQueueFamilyIndex = src; - image_barrier_.dstQueueFamilyIndex = dst; - buffer_barrier_.srcQueueFamilyIndex = src; - buffer_barrier_.dstQueueFamilyIndex = dst; - - QueueFamilyObjs *qf = GetQueueFamilyInfo(context_, queue_family_index); - - VkCommandBufferObj *command_buffer = qf->command_buffer; - for (int cb_repeat = 0; cb_repeat < (mod == Modifier::DOUBLE_COMMAND_BUFFER ? 2 : 1); cb_repeat++) { - command_buffer->begin(); - for (int repeat = 0; repeat < (mod == Modifier::DOUBLE_RECORD ? 2 : 1); repeat++) { - vkCmdPipelineBarrier(command_buffer->handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 1, &buffer_barrier_, 1, &image_barrier_); - } - command_buffer->end(); - command_buffer = qf->command_buffer2; // Second pass (if any) goes to the secondary command_buffer. - } - - if (queue_family_index != kInvalidQueueFamily) { - if (mod == Modifier::DOUBLE_COMMAND_BUFFER) { - // the Fence resolves to VK_NULL_HANLE... i.e. no fence - qf->queue->submit({{qf->command_buffer, qf->command_buffer2}}, vk_testing::Fence(), positive); - } else { - qf->command_buffer->QueueCommandBuffer(positive); // Check for success on positive tests only - } - } - - if (positive) { - monitor->VerifyNotFound(); - } else { - monitor->VerifyFound(); - } - context_->Reset(); - }; - - protected: - static const uint32_t kInvalidQueueFamily = UINT32_MAX; - Context *context_; - VkImageObj image_; - VkImageMemoryBarrier image_barrier_; - VkBufferObj buffer_; - VkBufferMemoryBarrier buffer_barrier_; -}; - -TEST_F(VkLayerTest, InvalidBarrierQueueFamily) { - TEST_DESCRIPTION("Create and submit barriers with invalid queue families"); - ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - - // Find queues of two families - const uint32_t submit_family = m_device->graphics_queue_node_index_; - const uint32_t invalid = static_cast<uint32_t>(m_device->queue_props.size()); - const uint32_t other_family = submit_family != 0 ? 0 : 1; - const bool only_one_family = (invalid == 1) || (m_device->queue_props[other_family].queueCount == 0); - - std::vector<uint32_t> qf_indices{{submit_family, other_family}}; - if (only_one_family) { - qf_indices.resize(1); - } - BarrierQueueFamilyTestHelper::Context test_context(this, qf_indices); - - if (m_device->props.apiVersion >= VK_API_VERSION_1_1) { - printf( - "%s Device has apiVersion greater than 1.0 -- skipping test cases that require external memory " - "to be " - "disabled.\n", - kSkipPrefix); - } else { - if (only_one_family) { - printf("%s Single queue family found -- VK_SHARING_MODE_CONCURRENT testcases skipped.\n", kSkipPrefix); - } else { - std::vector<uint32_t> families = {submit_family, other_family}; - BarrierQueueFamilyTestHelper conc_test(&test_context); - conc_test.Init(&families); - // core_validation::barrier_queue_families::kSrcAndDestMustBeIgnore - conc_test("VUID-VkImageMemoryBarrier-image-01199", "VUID-VkBufferMemoryBarrier-buffer-01190", VK_QUEUE_FAMILY_IGNORED, - submit_family); - conc_test("VUID-VkImageMemoryBarrier-image-01199", "VUID-VkBufferMemoryBarrier-buffer-01190", submit_family, - VK_QUEUE_FAMILY_IGNORED); - conc_test("VUID-VkImageMemoryBarrier-image-01199", "VUID-VkBufferMemoryBarrier-buffer-01190", submit_family, - submit_family); - // true -> positive test - conc_test("VUID-VkImageMemoryBarrier-image-01199", "VUID-VkBufferMemoryBarrier-buffer-01190", VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, true); - } - - BarrierQueueFamilyTestHelper excl_test(&test_context); - excl_test.Init(nullptr); // no queue families means *exclusive* sharing mode. - - // core_validation::barrier_queue_families::kBothIgnoreOrBothValid - excl_test("VUID-VkImageMemoryBarrier-image-01200", "VUID-VkBufferMemoryBarrier-buffer-01192", VK_QUEUE_FAMILY_IGNORED, - submit_family); - excl_test("VUID-VkImageMemoryBarrier-image-01200", "VUID-VkBufferMemoryBarrier-buffer-01192", submit_family, - VK_QUEUE_FAMILY_IGNORED); - // true -> positive test - excl_test("VUID-VkImageMemoryBarrier-image-01200", "VUID-VkBufferMemoryBarrier-buffer-01192", submit_family, submit_family, - true); - excl_test("VUID-VkImageMemoryBarrier-image-01200", "VUID-VkBufferMemoryBarrier-buffer-01192", VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, true); - } - - if (only_one_family) { - printf("%s Single queue family found -- VK_SHARING_MODE_EXCLUSIVE submit testcases skipped.\n", kSkipPrefix); - } else { - BarrierQueueFamilyTestHelper excl_test(&test_context); - excl_test.Init(nullptr); - - // core_validation::barrier_queue_families::kSubmitQueueMustMatchSrcOrDst - excl_test("VUID-VkImageMemoryBarrier-image-01205", "VUID-VkBufferMemoryBarrier-buffer-01196", other_family, other_family, - false, submit_family); - - // true -> positive test (testing both the index logic and the QFO transfer tracking. - excl_test("POSITIVE_TEST", "POSITIVE_TEST", submit_family, other_family, true, submit_family); - excl_test("POSITIVE_TEST", "POSITIVE_TEST", submit_family, other_family, true, other_family); - excl_test("POSITIVE_TEST", "POSITIVE_TEST", other_family, submit_family, true, other_family); - excl_test("POSITIVE_TEST", "POSITIVE_TEST", other_family, submit_family, true, submit_family); - - // negative testing for QFO transfer tracking - // Duplicate release in one CB - excl_test("UNASSIGNED-VkImageMemoryBarrier-image-00001", "UNASSIGNED-VkBufferMemoryBarrier-buffer-00001", submit_family, - other_family, false, submit_family, BarrierQueueFamilyTestHelper::DOUBLE_RECORD); - // Duplicate pending release - excl_test("UNASSIGNED-VkImageMemoryBarrier-image-00003", "UNASSIGNED-VkBufferMemoryBarrier-buffer-00003", submit_family, - other_family, false, submit_family); - // Duplicate acquire in one CB - excl_test("UNASSIGNED-VkImageMemoryBarrier-image-00001", "UNASSIGNED-VkBufferMemoryBarrier-buffer-00001", submit_family, - other_family, false, other_family, BarrierQueueFamilyTestHelper::DOUBLE_RECORD); - // No pending release - excl_test("UNASSIGNED-VkImageMemoryBarrier-image-00004", "UNASSIGNED-VkBufferMemoryBarrier-buffer-00004", submit_family, - other_family, false, other_family); - // Duplicate release in two CB - excl_test("UNASSIGNED-VkImageMemoryBarrier-image-00002", "UNASSIGNED-VkBufferMemoryBarrier-buffer-00002", submit_family, - other_family, false, submit_family, BarrierQueueFamilyTestHelper::DOUBLE_COMMAND_BUFFER); - // Duplicate acquire in two CB - excl_test("POSITIVE_TEST", "POSITIVE_TEST", submit_family, other_family, true, submit_family); // need a succesful release - excl_test("UNASSIGNED-VkImageMemoryBarrier-image-00002", "UNASSIGNED-VkBufferMemoryBarrier-buffer-00002", submit_family, - other_family, false, other_family, BarrierQueueFamilyTestHelper::DOUBLE_COMMAND_BUFFER); - } -} - -TEST_F(VkLayerTest, InvalidBarrierQueueFamilyWithMemExt) { - TEST_DESCRIPTION("Create and submit barriers with invalid queue families when memory extension is enabled "); - std::vector<const char *> reqd_instance_extensions = { - {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME}}; - for (auto extension_name : reqd_instance_extensions) { - if (InstanceExtensionSupported(extension_name)) { - m_instance_extension_names.push_back(extension_name); - } else { - printf("%s Required instance extension %s not supported, skipping test\n", kSkipPrefix, extension_name); - return; - } - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - // Check for external memory device extensions - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME); - } else { - printf("%s External memory extension not supported, skipping test\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - - // Find queues of two families - const uint32_t submit_family = m_device->graphics_queue_node_index_; - const uint32_t invalid = static_cast<uint32_t>(m_device->queue_props.size()); - const uint32_t other_family = submit_family != 0 ? 0 : 1; - const bool only_one_family = (invalid == 1) || (m_device->queue_props[other_family].queueCount == 0); - - std::vector<uint32_t> qf_indices{{submit_family, other_family}}; - if (only_one_family) { - qf_indices.resize(1); - } - BarrierQueueFamilyTestHelper::Context test_context(this, qf_indices); - - if (only_one_family) { - printf("%s Single queue family found -- VK_SHARING_MODE_CONCURRENT testcases skipped.\n", kSkipPrefix); - } else { - std::vector<uint32_t> families = {submit_family, other_family}; - BarrierQueueFamilyTestHelper conc_test(&test_context); - - // core_validation::barrier_queue_families::kSrcOrDstMustBeIgnore - conc_test.Init(&families); - conc_test("VUID-VkImageMemoryBarrier-image-01381", "VUID-VkBufferMemoryBarrier-buffer-01191", submit_family, submit_family); - // true -> positive test - conc_test("VUID-VkImageMemoryBarrier-image-01381", "VUID-VkBufferMemoryBarrier-buffer-01191", VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, true); - conc_test("VUID-VkImageMemoryBarrier-image-01381", "VUID-VkBufferMemoryBarrier-buffer-01191", VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_EXTERNAL_KHR, true); - conc_test("VUID-VkImageMemoryBarrier-image-01381", "VUID-VkBufferMemoryBarrier-buffer-01191", VK_QUEUE_FAMILY_EXTERNAL_KHR, - VK_QUEUE_FAMILY_IGNORED, true); - - // core_validation::barrier_queue_families::kSpecialOrIgnoreOnly - conc_test("VUID-VkImageMemoryBarrier-image-01766", "VUID-VkBufferMemoryBarrier-buffer-01763", submit_family, - VK_QUEUE_FAMILY_IGNORED); - conc_test("VUID-VkImageMemoryBarrier-image-01766", "VUID-VkBufferMemoryBarrier-buffer-01763", VK_QUEUE_FAMILY_IGNORED, - submit_family); - // This is to flag the errors that would be considered only "unexpected" in the parallel case above - // true -> positive test - conc_test("VUID-VkImageMemoryBarrier-image-01766", "VUID-VkBufferMemoryBarrier-buffer-01763", VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_EXTERNAL_KHR, true); - conc_test("VUID-VkImageMemoryBarrier-image-01766", "VUID-VkBufferMemoryBarrier-buffer-01763", VK_QUEUE_FAMILY_EXTERNAL_KHR, - VK_QUEUE_FAMILY_IGNORED, true); - } - - BarrierQueueFamilyTestHelper excl_test(&test_context); - excl_test.Init(nullptr); // no queue families means *exclusive* sharing mode. - - // core_validation::barrier_queue_families::kSrcIgnoreRequiresDstIgnore - excl_test("VUID-VkImageMemoryBarrier-image-01201", "VUID-VkBufferMemoryBarrier-buffer-01193", VK_QUEUE_FAMILY_IGNORED, - submit_family); - excl_test("VUID-VkImageMemoryBarrier-image-01201", "VUID-VkBufferMemoryBarrier-buffer-01193", VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_EXTERNAL_KHR); - // true -> positive test - excl_test("VUID-VkImageMemoryBarrier-image-01201", "VUID-VkBufferMemoryBarrier-buffer-01193", VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, true); - - // core_validation::barrier_queue_families::kDstValidOrSpecialIfNotIgnore - excl_test("VUID-VkImageMemoryBarrier-image-01768", "VUID-VkBufferMemoryBarrier-buffer-01765", submit_family, invalid); - // true -> positive test - excl_test("VUID-VkImageMemoryBarrier-image-01768", "VUID-VkBufferMemoryBarrier-buffer-01765", submit_family, submit_family, - true); - excl_test("VUID-VkImageMemoryBarrier-image-01768", "VUID-VkBufferMemoryBarrier-buffer-01765", submit_family, - VK_QUEUE_FAMILY_IGNORED, true); - excl_test("VUID-VkImageMemoryBarrier-image-01768", "VUID-VkBufferMemoryBarrier-buffer-01765", submit_family, - VK_QUEUE_FAMILY_EXTERNAL_KHR, true); - - // core_validation::barrier_queue_families::kSrcValidOrSpecialIfNotIgnore - excl_test("VUID-VkImageMemoryBarrier-image-01767", "VUID-VkBufferMemoryBarrier-buffer-01764", invalid, submit_family); - // true -> positive test - excl_test("VUID-VkImageMemoryBarrier-image-01767", "VUID-VkBufferMemoryBarrier-buffer-01764", submit_family, submit_family, - true); - excl_test("VUID-VkImageMemoryBarrier-image-01767", "VUID-VkBufferMemoryBarrier-buffer-01764", VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, true); - excl_test("VUID-VkImageMemoryBarrier-image-01767", "VUID-VkBufferMemoryBarrier-buffer-01764", VK_QUEUE_FAMILY_EXTERNAL_KHR, - submit_family, true); -} - -TEST_F(VkLayerTest, ImageBarrierWithBadRange) { - TEST_DESCRIPTION("VkImageMemoryBarrier with an invalid subresourceRange"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkImageObj image(m_device); - image.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(image.create_info().arrayLayers == 1); - ASSERT_TRUE(image.initialized()); - - VkImageMemoryBarrier img_barrier_template = {}; - img_barrier_template.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - img_barrier_template.pNext = NULL; - img_barrier_template.srcAccessMask = 0; - img_barrier_template.dstAccessMask = 0; - img_barrier_template.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - img_barrier_template.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - img_barrier_template.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier_template.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier_template.image = image.handle(); - // subresourceRange to be set later for the for the purposes of this test - img_barrier_template.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - img_barrier_template.subresourceRange.baseArrayLayer = 0; - img_barrier_template.subresourceRange.baseMipLevel = 0; - img_barrier_template.subresourceRange.layerCount = 0; - img_barrier_template.subresourceRange.levelCount = 0; - - m_commandBuffer->begin(); - - // Nested scope here confuses clang-format, somehow - // clang-format off - - // try for vkCmdPipelineBarrier - { - // Try baseMipLevel >= image.mipLevels with VK_REMAINING_MIP_LEVELS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01486"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 1, VK_REMAINING_MIP_LEVELS, 0, 1}; - VkImageMemoryBarrier img_barrier = img_barrier_template; - img_barrier.subresourceRange = range; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - } - - // Try baseMipLevel >= image.mipLevels without VK_REMAINING_MIP_LEVELS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01486"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01724"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 0, 1}; - VkImageMemoryBarrier img_barrier = img_barrier_template; - img_barrier.subresourceRange = range; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - } - - // Try levelCount = 0 - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01724"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 0, 1}; - VkImageMemoryBarrier img_barrier = img_barrier_template; - img_barrier.subresourceRange = range; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - } - - // Try baseMipLevel + levelCount > image.mipLevels - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01724"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 2, 0, 1}; - VkImageMemoryBarrier img_barrier = img_barrier_template; - img_barrier.subresourceRange = range; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - } - - // Try baseArrayLayer >= image.arrayLayers with VK_REMAINING_ARRAY_LAYERS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01488"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 1, VK_REMAINING_ARRAY_LAYERS}; - VkImageMemoryBarrier img_barrier = img_barrier_template; - img_barrier.subresourceRange = range; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - } - - // Try baseArrayLayer >= image.arrayLayers without VK_REMAINING_ARRAY_LAYERS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01488"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01725"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 1, 1}; - VkImageMemoryBarrier img_barrier = img_barrier_template; - img_barrier.subresourceRange = range; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - } - - // Try layerCount = 0 - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01725"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 0}; - VkImageMemoryBarrier img_barrier = img_barrier_template; - img_barrier.subresourceRange = range; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - } - - // Try baseArrayLayer + layerCount > image.arrayLayers - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01725"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 2}; - VkImageMemoryBarrier img_barrier = img_barrier_template; - img_barrier.subresourceRange = range; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - } - } - - // try for vkCmdWaitEvents - { - VkEvent event; - VkEventCreateInfo eci{VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, NULL, 0}; - VkResult err = vkCreateEvent(m_device->handle(), &eci, nullptr, &event); - ASSERT_VK_SUCCESS(err); - - // Try baseMipLevel >= image.mipLevels with VK_REMAINING_MIP_LEVELS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01486"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 1, VK_REMAINING_MIP_LEVELS, 0, 1}; - VkImageMemoryBarrier img_barrier = img_barrier_template; - img_barrier.subresourceRange = range; - vkCmdWaitEvents(m_commandBuffer->handle(), 1, &event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - } - - // Try baseMipLevel >= image.mipLevels without VK_REMAINING_MIP_LEVELS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01486"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01724"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 0, 1}; - VkImageMemoryBarrier img_barrier = img_barrier_template; - img_barrier.subresourceRange = range; - vkCmdWaitEvents(m_commandBuffer->handle(), 1, &event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - } - - // Try levelCount = 0 - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01724"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 0, 1}; - VkImageMemoryBarrier img_barrier = img_barrier_template; - img_barrier.subresourceRange = range; - vkCmdWaitEvents(m_commandBuffer->handle(), 1, &event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - } - - // Try baseMipLevel + levelCount > image.mipLevels - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01724"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 2, 0, 1}; - VkImageMemoryBarrier img_barrier = img_barrier_template; - img_barrier.subresourceRange = range; - vkCmdWaitEvents(m_commandBuffer->handle(), 1, &event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - } - - // Try baseArrayLayer >= image.arrayLayers with VK_REMAINING_ARRAY_LAYERS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01488"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 1, VK_REMAINING_ARRAY_LAYERS}; - VkImageMemoryBarrier img_barrier = img_barrier_template; - img_barrier.subresourceRange = range; - vkCmdWaitEvents(m_commandBuffer->handle(), 1, &event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - } - - // Try baseArrayLayer >= image.arrayLayers without VK_REMAINING_ARRAY_LAYERS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01488"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01725"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 1, 1}; - VkImageMemoryBarrier img_barrier = img_barrier_template; - img_barrier.subresourceRange = range; - vkCmdWaitEvents(m_commandBuffer->handle(), 1, &event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - } - - // Try layerCount = 0 - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01725"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 0}; - VkImageMemoryBarrier img_barrier = img_barrier_template; - img_barrier.subresourceRange = range; - vkCmdWaitEvents(m_commandBuffer->handle(), 1, &event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - } - - // Try baseArrayLayer + layerCount > image.arrayLayers - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01725"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 2}; - VkImageMemoryBarrier img_barrier = img_barrier_template; - img_barrier.subresourceRange = range; - vkCmdWaitEvents(m_commandBuffer->handle(), 1, &event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - } - - vkDestroyEvent(m_device->handle(), event, nullptr); - } -// clang-format on -} - -TEST_F(VkLayerTest, ValidationCacheTestBadMerge) { - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), "VK_LAYER_LUNARG_core_validation", VK_EXT_VALIDATION_CACHE_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_EXT_VALIDATION_CACHE_EXTENSION_NAME); - } else { - printf("%s %s not supported, skipping test\n", kSkipPrefix, VK_EXT_VALIDATION_CACHE_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - // Load extension functions - auto fpCreateValidationCache = - (PFN_vkCreateValidationCacheEXT)vkGetDeviceProcAddr(m_device->device(), "vkCreateValidationCacheEXT"); - auto fpDestroyValidationCache = - (PFN_vkDestroyValidationCacheEXT)vkGetDeviceProcAddr(m_device->device(), "vkDestroyValidationCacheEXT"); - auto fpMergeValidationCaches = - (PFN_vkMergeValidationCachesEXT)vkGetDeviceProcAddr(m_device->device(), "vkMergeValidationCachesEXT"); - if (!fpCreateValidationCache || !fpDestroyValidationCache || !fpMergeValidationCaches) { - printf("%s Failed to load function pointers for %s\n", kSkipPrefix, VK_EXT_VALIDATION_CACHE_EXTENSION_NAME); - return; - } - - VkValidationCacheCreateInfoEXT validationCacheCreateInfo; - validationCacheCreateInfo.sType = VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT; - validationCacheCreateInfo.pNext = NULL; - validationCacheCreateInfo.initialDataSize = 0; - validationCacheCreateInfo.pInitialData = NULL; - validationCacheCreateInfo.flags = 0; - VkValidationCacheEXT validationCache = VK_NULL_HANDLE; - VkResult res = fpCreateValidationCache(m_device->device(), &validationCacheCreateInfo, nullptr, &validationCache); - ASSERT_VK_SUCCESS(res); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkMergeValidationCachesEXT-dstCache-01536"); - res = fpMergeValidationCaches(m_device->device(), validationCache, 1, &validationCache); - m_errorMonitor->VerifyFound(); - - fpDestroyValidationCache(m_device->device(), validationCache, nullptr); -} - -TEST_F(VkPositiveLayerTest, LayoutFromPresentWithoutAccessMemoryRead) { - // Transition an image away from PRESENT_SRC_KHR without ACCESS_MEMORY_READ - // in srcAccessMask. - - // The required behavior here was a bit unclear in earlier versions of the - // spec, but there is no memory dependency required here, so this should - // work without warnings. - - m_errorMonitor->ExpectSuccess(); - ASSERT_NO_FATAL_FAILURE(Init()); - VkImageObj image(m_device); - image.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT), - VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - VkImageMemoryBarrier barrier = {}; - VkImageSubresourceRange range; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - barrier.dstAccessMask = 0; - barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - barrier.image = image.handle(); - range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - range.baseMipLevel = 0; - range.levelCount = 1; - range.baseArrayLayer = 0; - range.layerCount = 1; - barrier.subresourceRange = range; - VkCommandBufferObj cmdbuf(m_device, m_commandPool); - cmdbuf.begin(); - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1, - &barrier); - barrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - barrier.srcAccessMask = 0; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1, - &barrier); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkLayerTest, IdxBufferAlignmentError) { - // Bind a BeginRenderPass within an active RenderPass - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - uint32_t const indices[] = {0}; - VkBufferCreateInfo buf_info = {}; - buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buf_info.size = 1024; - buf_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; - buf_info.queueFamilyIndexCount = 1; - buf_info.pQueueFamilyIndices = indices; - - VkBuffer buffer; - VkResult err = vkCreateBuffer(m_device->device(), &buf_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - VkMemoryRequirements requirements; - vkGetBufferMemoryRequirements(m_device->device(), buffer, &requirements); - - VkMemoryAllocateInfo alloc_info{}; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.pNext = NULL; - alloc_info.memoryTypeIndex = 0; - alloc_info.allocationSize = requirements.size; - bool pass = m_device->phy().set_memory_type(requirements.memoryTypeBits, &alloc_info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - ASSERT_TRUE(pass); - - VkDeviceMemory memory; - err = vkAllocateMemory(m_device->device(), &alloc_info, NULL, &memory); - ASSERT_VK_SUCCESS(err); - - err = vkBindBufferMemory(m_device->device(), buffer, memory, 0); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - ASSERT_VK_SUCCESS(err); - - // vkCmdBindPipeline(m_commandBuffer->handle(), - // VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - // Should error before calling to driver so don't care about actual data - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "vkCmdBindIndexBuffer() offset (0x7) does not fall on "); - vkCmdBindIndexBuffer(m_commandBuffer->handle(), buffer, 7, VK_INDEX_TYPE_UINT16); - m_errorMonitor->VerifyFound(); - - vkFreeMemory(m_device->device(), memory, NULL); - vkDestroyBuffer(m_device->device(), buffer, NULL); -} - -TEST_F(VkLayerTest, InvalidQueueFamilyIndex) { - // Miscellaneous queueFamilyIndex validation tests - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - VkBufferCreateInfo buffCI = {}; - buffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffCI.size = 1024; - buffCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; - buffCI.queueFamilyIndexCount = 2; - // Introduce failure by specifying invalid queue_family_index - uint32_t qfi[2]; - qfi[0] = 777; - qfi[1] = 0; - - buffCI.pQueueFamilyIndices = qfi; - buffCI.sharingMode = VK_SHARING_MODE_CONCURRENT; // qfi only matters in CONCURRENT mode - - VkBuffer ib; - // Test for queue family index out of range - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferCreateInfo-sharingMode-01419"); - vkCreateBuffer(m_device->device(), &buffCI, NULL, &ib); - m_errorMonitor->VerifyFound(); - - // Test for non-unique QFI in array - qfi[0] = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferCreateInfo-sharingMode-01419"); - vkCreateBuffer(m_device->device(), &buffCI, NULL, &ib); - m_errorMonitor->VerifyFound(); - - if (m_device->queue_props.size() > 2) { - VkBuffer ib2; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "which was not created allowing concurrent"); - - // Create buffer shared to queue families 1 and 2, but submitted on queue family 0 - buffCI.queueFamilyIndexCount = 2; - qfi[0] = 1; - qfi[1] = 2; - vkCreateBuffer(m_device->device(), &buffCI, NULL, &ib2); - VkDeviceMemory mem; - VkMemoryRequirements mem_reqs; - vkGetBufferMemoryRequirements(m_device->device(), ib2, &mem_reqs); - - VkMemoryAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.allocationSize = mem_reqs.size; - bool pass = false; - pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &alloc_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - if (!pass) { - printf("%s Failed to allocate required memory.\n", kSkipPrefix); - vkDestroyBuffer(m_device->device(), ib2, NULL); - return; - } - vkAllocateMemory(m_device->device(), &alloc_info, NULL, &mem); - vkBindBufferMemory(m_device->device(), ib2, mem, 0); - - m_commandBuffer->begin(); - vkCmdFillBuffer(m_commandBuffer->handle(), ib2, 0, 16, 5); - m_commandBuffer->end(); - m_commandBuffer->QueueCommandBuffer(false); - m_errorMonitor->VerifyFound(); - vkDestroyBuffer(m_device->device(), ib2, NULL); - vkFreeMemory(m_device->device(), mem, NULL); - } -} - -TEST_F(VkLayerTest, ExecuteCommandsPrimaryCB) { - TEST_DESCRIPTION("Attempt vkCmdExecuteCommands with a primary command buffer (should only be secondary)"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // An empty primary command buffer - VkCommandBufferObj cb(m_device, m_commandPool); - cb.begin(); - cb.end(); - - m_commandBuffer->begin(); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &renderPassBeginInfo(), VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); - VkCommandBuffer handle = cb.handle(); - - 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 in the pending state"); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, DSUsageBitsErrors) { - TEST_DESCRIPTION("Attempt to update descriptor sets for images and buffers that do not have correct usage bits sets."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - const VkFormat buffer_format = VK_FORMAT_R8_UNORM; - VkFormatProperties format_properties; - vkGetPhysicalDeviceFormatProperties(gpu(), buffer_format, &format_properties); - if (!(format_properties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT)) { - printf("%s Device does not support VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT for this format; skipped.\n", kSkipPrefix); - return; - } - - std::array<VkDescriptorPoolSize, VK_DESCRIPTOR_TYPE_RANGE_SIZE> ds_type_count; - for (uint32_t i = 0; i < ds_type_count.size(); ++i) { - ds_type_count[i].type = VkDescriptorType(i); - ds_type_count[i].descriptorCount = 1; - } - - vk_testing::DescriptorPool ds_pool; - ds_pool.init(*m_device, vk_testing::DescriptorPool::create_info(0, VK_DESCRIPTOR_TYPE_RANGE_SIZE, ds_type_count)); - ASSERT_TRUE(ds_pool.initialized()); - - std::vector<VkDescriptorSetLayoutBinding> dsl_bindings(1); - dsl_bindings[0].binding = 0; - dsl_bindings[0].descriptorType = VkDescriptorType(0); - dsl_bindings[0].descriptorCount = 1; - dsl_bindings[0].stageFlags = VK_SHADER_STAGE_ALL; - dsl_bindings[0].pImmutableSamplers = NULL; - - // Create arrays of layout and descriptor objects - using UpDescriptorSet = std::unique_ptr<vk_testing::DescriptorSet>; - std::vector<UpDescriptorSet> descriptor_sets; - using UpDescriptorSetLayout = std::unique_ptr<VkDescriptorSetLayoutObj>; - std::vector<UpDescriptorSetLayout> ds_layouts; - descriptor_sets.reserve(VK_DESCRIPTOR_TYPE_RANGE_SIZE); - ds_layouts.reserve(VK_DESCRIPTOR_TYPE_RANGE_SIZE); - for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; ++i) { - dsl_bindings[0].descriptorType = VkDescriptorType(i); - ds_layouts.push_back(UpDescriptorSetLayout(new VkDescriptorSetLayoutObj(m_device, dsl_bindings))); - descriptor_sets.push_back(UpDescriptorSet(ds_pool.alloc_sets(*m_device, *ds_layouts.back()))); - ASSERT_TRUE(descriptor_sets.back()->initialized()); - } - - // Create a buffer & bufferView to be used for invalid updates - const VkDeviceSize buffer_size = 256; - uint8_t data[buffer_size]; - VkConstantBufferObj buffer(m_device, buffer_size, data, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT); - VkConstantBufferObj storage_texel_buffer(m_device, buffer_size, data, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT); - ASSERT_TRUE(buffer.initialized() && storage_texel_buffer.initialized()); - - auto buff_view_ci = vk_testing::BufferView::createInfo(buffer.handle(), VK_FORMAT_R8_UNORM); - vk_testing::BufferView buffer_view_obj, storage_texel_buffer_view_obj; - buffer_view_obj.init(*m_device, buff_view_ci); - buff_view_ci.buffer = storage_texel_buffer.handle(); - storage_texel_buffer_view_obj.init(*m_device, buff_view_ci); - ASSERT_TRUE(buffer_view_obj.initialized() && storage_texel_buffer_view_obj.initialized()); - VkBufferView buffer_view = buffer_view_obj.handle(); - VkBufferView storage_texel_buffer_view = storage_texel_buffer_view_obj.handle(); - - // Create an image to be used for invalid updates - VkImageObj image_obj(m_device); - image_obj.InitNoLayout(64, 64, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image_obj.initialized()); - VkImageView image_view = image_obj.targetView(VK_FORMAT_R8G8B8A8_UNORM); - - VkDescriptorBufferInfo buff_info = {}; - buff_info.buffer = buffer.handle(); - VkDescriptorImageInfo img_info = {}; - img_info.imageView = image_view; - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.pTexelBufferView = &buffer_view; - descriptor_write.pBufferInfo = &buff_info; - descriptor_write.pImageInfo = &img_info; - - // These error messages align with VkDescriptorType struct - std::string error_codes[] = { - "VUID-VkWriteDescriptorSet-descriptorType-00326", // placeholder, no error for SAMPLER descriptor - "VUID-VkWriteDescriptorSet-descriptorType-00326", // COMBINED_IMAGE_SAMPLER - "VUID-VkWriteDescriptorSet-descriptorType-00326", // SAMPLED_IMAGE - "VUID-VkWriteDescriptorSet-descriptorType-00326", // STORAGE_IMAGE - "VUID-VkWriteDescriptorSet-descriptorType-00334", // UNIFORM_TEXEL_BUFFER - "VUID-VkWriteDescriptorSet-descriptorType-00335", // STORAGE_TEXEL_BUFFER - "VUID-VkWriteDescriptorSet-descriptorType-00330", // UNIFORM_BUFFER - "VUID-VkWriteDescriptorSet-descriptorType-00331", // STORAGE_BUFFER - "VUID-VkWriteDescriptorSet-descriptorType-00330", // UNIFORM_BUFFER_DYNAMIC - "VUID-VkWriteDescriptorSet-descriptorType-00331", // STORAGE_BUFFER_DYNAMIC - "VUID-VkWriteDescriptorSet-descriptorType-00326" // INPUT_ATTACHMENT - }; - // Start loop at 1 as SAMPLER desc type has no usage bit error - for (uint32_t i = 1; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; ++i) { - if (VkDescriptorType(i) == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) { - // Now check for UNIFORM_TEXEL_BUFFER using storage_texel_buffer_view - descriptor_write.pTexelBufferView = &storage_texel_buffer_view; - } - descriptor_write.descriptorType = VkDescriptorType(i); - descriptor_write.dstSet = descriptor_sets[i]->handle(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, error_codes[i]); - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - m_errorMonitor->VerifyFound(); - if (VkDescriptorType(i) == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) { - descriptor_write.pTexelBufferView = &buffer_view; - } - } -} - -TEST_F(VkLayerTest, DSBufferInfoErrors) { - TEST_DESCRIPTION( - "Attempt to update buffer descriptor set that has incorrect parameters in VkDescriptorBufferInfo struct. This includes:\n" - "1. offset value greater than or equal to buffer size\n" - "2. range value of 0\n" - "3. range value greater than buffer (size - offset)"); - VkResult err; - - // GPDDP2 needed for push descriptors support below - bool gpdp2_support = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION); - if (gpdp2_support) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - bool update_template_support = DeviceExtensionSupported(gpu(), nullptr, VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME); - if (update_template_support) { - m_device_extension_names.push_back(VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME); - } else { - printf("%s Descriptor Update Template Extensions not supported, template cases skipped.\n", kSkipPrefix); - } - - // Note: Includes workaround for some implementations which incorrectly return 0 maxPushDescriptors - bool push_descriptor_support = gpdp2_support && - DeviceExtensionSupported(gpu(), nullptr, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME) && - (GetPushDescriptorProperties(instance(), gpu()).maxPushDescriptors > 0); - if (push_descriptor_support) { - m_device_extension_names.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - } else { - printf("%s Push Descriptor Extension not supported, push descriptor cases skipped.\n", kSkipPrefix); - } - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - - std::vector<VkDescriptorSetLayoutBinding> ds_bindings = { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}; - OneOffDescriptorSet ds(m_device, ds_bindings); - - // Create a buffer to be used for invalid updates - VkBufferCreateInfo buff_ci = {}; - buff_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buff_ci.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - buff_ci.size = m_device->props.limits.minUniformBufferOffsetAlignment; - buff_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VkBuffer buffer; - err = vkCreateBuffer(m_device->device(), &buff_ci, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - // Have to bind memory to buffer before descriptor update - VkMemoryRequirements mem_reqs; - vkGetBufferMemoryRequirements(m_device->device(), buffer, &mem_reqs); - VkMemoryAllocateInfo mem_alloc = {}; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.allocationSize = mem_reqs.size; - mem_alloc.memoryTypeIndex = 0; - bool pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &mem_alloc, 0); - if (!pass) { - printf("%s Failed to allocate memory.\n", kSkipPrefix); - vkDestroyBuffer(m_device->device(), buffer, NULL); - return; - } - - VkDeviceMemory mem; - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &mem); - ASSERT_VK_SUCCESS(err); - err = vkBindBufferMemory(m_device->device(), buffer, mem, 0); - ASSERT_VK_SUCCESS(err); - - VkDescriptorBufferInfo buff_info = {}; - buff_info.buffer = buffer; - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.pTexelBufferView = nullptr; - descriptor_write.pBufferInfo = &buff_info; - descriptor_write.pImageInfo = nullptr; - - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_write.dstSet = ds.set_; - - // Relying on the "return nullptr for non-enabled extensions - auto vkCreateDescriptorUpdateTemplateKHR = - (PFN_vkCreateDescriptorUpdateTemplateKHR)vkGetDeviceProcAddr(m_device->device(), "vkCreateDescriptorUpdateTemplateKHR"); - auto vkDestroyDescriptorUpdateTemplateKHR = - (PFN_vkDestroyDescriptorUpdateTemplateKHR)vkGetDeviceProcAddr(m_device->device(), "vkDestroyDescriptorUpdateTemplateKHR"); - auto vkUpdateDescriptorSetWithTemplateKHR = - (PFN_vkUpdateDescriptorSetWithTemplateKHR)vkGetDeviceProcAddr(m_device->device(), "vkUpdateDescriptorSetWithTemplateKHR"); - - if (update_template_support) { - ASSERT_NE(vkCreateDescriptorUpdateTemplateKHR, nullptr); - ASSERT_NE(vkDestroyDescriptorUpdateTemplateKHR, nullptr); - ASSERT_NE(vkUpdateDescriptorSetWithTemplateKHR, nullptr); - } - - // Setup for update w/ template tests - // Create a template of descriptor set updates - struct SimpleTemplateData { - uint8_t padding[7]; - VkDescriptorBufferInfo buff_info; - uint32_t other_padding[4]; - }; - SimpleTemplateData update_template_data = {}; - - VkDescriptorUpdateTemplateEntry update_template_entry = {}; - update_template_entry.dstBinding = 0; - update_template_entry.dstArrayElement = 0; - update_template_entry.descriptorCount = 1; - update_template_entry.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - update_template_entry.offset = offsetof(SimpleTemplateData, buff_info); - update_template_entry.stride = sizeof(SimpleTemplateData); - - auto update_template_ci = lvl_init_struct<VkDescriptorUpdateTemplateCreateInfoKHR>(); - update_template_ci.descriptorUpdateEntryCount = 1; - update_template_ci.pDescriptorUpdateEntries = &update_template_entry; - update_template_ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET; - update_template_ci.descriptorSetLayout = ds.layout_.handle(); - - VkDescriptorUpdateTemplate update_template = VK_NULL_HANDLE; - if (update_template_support) { - auto result = vkCreateDescriptorUpdateTemplateKHR(m_device->device(), &update_template_ci, nullptr, &update_template); - ASSERT_VK_SUCCESS(result); - } - - // VK_KHR_push_descriptor support - auto vkCmdPushDescriptorSetKHR = - (PFN_vkCmdPushDescriptorSetKHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdPushDescriptorSetKHR"); - auto vkCmdPushDescriptorSetWithTemplateKHR = - (PFN_vkCmdPushDescriptorSetWithTemplateKHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdPushDescriptorSetWithTemplateKHR"); - - std::unique_ptr<VkDescriptorSetLayoutObj> push_dsl = nullptr; - std::unique_ptr<VkPipelineLayoutObj> pipeline_layout = nullptr; - VkDescriptorUpdateTemplate push_template = VK_NULL_HANDLE; - if (push_descriptor_support) { - ASSERT_NE(vkCmdPushDescriptorSetKHR, nullptr); - push_dsl.reset( - new VkDescriptorSetLayoutObj(m_device, ds_bindings, VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR)); - pipeline_layout.reset(new VkPipelineLayoutObj(m_device, {push_dsl.get()})); - ASSERT_TRUE(push_dsl->initialized()); - - if (update_template_support) { - ASSERT_NE(vkCmdPushDescriptorSetWithTemplateKHR, nullptr); - auto push_template_ci = lvl_init_struct<VkDescriptorUpdateTemplateCreateInfoKHR>(); - push_template_ci.descriptorUpdateEntryCount = 1; - push_template_ci.pDescriptorUpdateEntries = &update_template_entry; - push_template_ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR; - push_template_ci.descriptorSetLayout = VK_NULL_HANDLE; - push_template_ci.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - push_template_ci.pipelineLayout = pipeline_layout->handle(); - push_template_ci.set = 0; - auto result = vkCreateDescriptorUpdateTemplateKHR(m_device->device(), &push_template_ci, nullptr, &push_template); - ASSERT_VK_SUCCESS(result); - } - } - - auto do_test = [&](const char *desired_failure) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, desired_failure); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - - if (push_descriptor_support) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, desired_failure); - m_commandBuffer->begin(); - vkCmdPushDescriptorSetKHR(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout->handle(), 0, 1, - &descriptor_write); - m_commandBuffer->end(); - m_errorMonitor->VerifyFound(); - } - - if (update_template_support) { - update_template_data.buff_info = buff_info; // copy the test case information into our "pData" - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, desired_failure); - vkUpdateDescriptorSetWithTemplateKHR(m_device->device(), ds.set_, update_template, &update_template_data); - m_errorMonitor->VerifyFound(); - if (push_descriptor_support) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, desired_failure); - m_commandBuffer->begin(); - vkCmdPushDescriptorSetWithTemplateKHR(m_commandBuffer->handle(), push_template, pipeline_layout->handle(), 0, - &update_template_data); - m_commandBuffer->end(); - m_errorMonitor->VerifyFound(); - } - } - }; - - // Cause error due to offset out of range - buff_info.offset = buff_ci.size; - buff_info.range = VK_WHOLE_SIZE; - do_test("VUID-VkDescriptorBufferInfo-offset-00340"); - - // Now cause error due to range of 0 - buff_info.offset = 0; - buff_info.range = 0; - do_test("VUID-VkDescriptorBufferInfo-range-00341"); - - // Now cause error due to range exceeding buffer size - offset - buff_info.offset = 0; - buff_info.range = buff_ci.size + 1; - do_test("VUID-VkDescriptorBufferInfo-range-00342"); - - if (update_template_support) { - vkDestroyDescriptorUpdateTemplateKHR(m_device->device(), update_template, nullptr); - if (push_descriptor_support) { - vkDestroyDescriptorUpdateTemplateKHR(m_device->device(), push_template, nullptr); - } - } - vkFreeMemory(m_device->device(), mem, NULL); - vkDestroyBuffer(m_device->device(), buffer, NULL); -} - -TEST_F(VkLayerTest, DSBufferLimitErrors) { - TEST_DESCRIPTION( - "Attempt to update buffer descriptor set that has VkDescriptorBufferInfo values that violate device limits.\n" - "Test cases include:\n" - "1. range of uniform buffer update exceeds maxUniformBufferRange\n" - "2. offset of uniform buffer update is not multiple of minUniformBufferOffsetAlignment\n" - "3. using VK_WHOLE_SIZE with uniform buffer size exceeding maxUniformBufferRange\n" - "4. range of storage buffer update exceeds maxStorageBufferRange\n" - "5. offset of storage buffer update is not multiple of minStorageBufferOffsetAlignment\n" - "6. using VK_WHOLE_SIZE with storage buffer size exceeding maxStorageBufferRange"); - VkResult err; - - ASSERT_NO_FATAL_FAILURE(Init()); - - struct TestCase { - VkDescriptorType descriptor_type; - VkBufferUsageFlagBits buffer_usage; - VkDeviceSize max_range; - std::string max_range_vu; - VkDeviceSize min_align; - std::string min_align_vu; - }; - - for (const auto &test_case : { - TestCase({VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - m_device->props.limits.maxUniformBufferRange, "VUID-VkWriteDescriptorSet-descriptorType-00332", - m_device->props.limits.minUniformBufferOffsetAlignment, "VUID-VkWriteDescriptorSet-descriptorType-00327"}), - TestCase({VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - m_device->props.limits.maxStorageBufferRange, "VUID-VkWriteDescriptorSet-descriptorType-00333", - m_device->props.limits.minStorageBufferOffsetAlignment, "VUID-VkWriteDescriptorSet-descriptorType-00328"}), - }) { - // Create layout with single buffer - OneOffDescriptorSet ds(m_device, { - {0, test_case.descriptor_type, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - // Create a buffer to be used for invalid updates - VkBufferCreateInfo bci = {}; - bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bci.usage = test_case.buffer_usage; - bci.size = test_case.max_range + test_case.min_align; // Make buffer bigger than range limit - bci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VkBuffer buffer; - err = vkCreateBuffer(m_device->device(), &bci, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - // Have to bind memory to buffer before descriptor update - VkMemoryRequirements mem_reqs; - vkGetBufferMemoryRequirements(m_device->device(), buffer, &mem_reqs); - - VkMemoryAllocateInfo mem_alloc = {}; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.allocationSize = mem_reqs.size; - bool pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &mem_alloc, 0); - if (!pass) { - printf("%s Failed to allocate memory in DSBufferLimitErrors; skipped.\n", kSkipPrefix); - vkDestroyBuffer(m_device->device(), buffer, NULL); - continue; - } - - VkDeviceMemory mem; - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &mem); - if (VK_SUCCESS != err) { - printf("%s Failed to allocate memory in DSBufferLimitErrors; skipped.\n", kSkipPrefix); - vkDestroyBuffer(m_device->device(), buffer, NULL); - continue; - } - err = vkBindBufferMemory(m_device->device(), buffer, mem, 0); - ASSERT_VK_SUCCESS(err); - - VkDescriptorBufferInfo buff_info = {}; - buff_info.buffer = buffer; - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.pTexelBufferView = nullptr; - descriptor_write.pBufferInfo = &buff_info; - descriptor_write.pImageInfo = nullptr; - descriptor_write.descriptorType = test_case.descriptor_type; - descriptor_write.dstSet = ds.set_; - - // Exceed range limit - if (test_case.max_range != UINT32_MAX) { - buff_info.range = test_case.max_range + 1; - buff_info.offset = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.max_range_vu); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - } - - // Reduce size of range to acceptable limit and cause offset error - if (test_case.min_align > 1) { - buff_info.range = test_case.max_range; - buff_info.offset = test_case.min_align - 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.min_align_vu); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - } - - // Exceed effective range limit by using VK_WHOLE_SIZE - buff_info.range = VK_WHOLE_SIZE; - buff_info.offset = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.max_range_vu); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - - // Cleanup - vkFreeMemory(m_device->device(), mem, NULL); - vkDestroyBuffer(m_device->device(), buffer, NULL); - } -} - -TEST_F(VkLayerTest, DSAspectBitsErrors) { - // TODO : Initially only catching case where DEPTH & STENCIL aspect bits - // are set, but could expand this test to hit more cases. - TEST_DESCRIPTION("Attempt to update descriptor sets for images that do not have correct aspect bits sets."); - VkResult err; - - ASSERT_NO_FATAL_FAILURE(Init()); - auto depth_format = FindSupportedDepthStencilFormat(gpu()); - if (!depth_format) { - printf("%s No Depth + Stencil format found. Skipped.\n", kSkipPrefix); - return; - } - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - // Create an image to be used for invalid updates - VkImageObj image_obj(m_device); - image_obj.Init(64, 64, 1, depth_format, VK_IMAGE_USAGE_SAMPLED_BIT); - if (!image_obj.initialized()) { - printf("%s Depth + Stencil format cannot be sampled. Skipped.\n", kSkipPrefix); - return; - } - VkImage image = image_obj.image(); - - // Now create view for image - VkImageViewCreateInfo image_view_ci = {}; - image_view_ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - image_view_ci.image = image; - image_view_ci.format = depth_format; - image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D; - image_view_ci.subresourceRange.layerCount = 1; - image_view_ci.subresourceRange.baseArrayLayer = 0; - image_view_ci.subresourceRange.levelCount = 1; - // Setting both depth & stencil aspect bits is illegal for an imageView used - // to populate a descriptor set. - image_view_ci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - - VkImageView image_view; - err = vkCreateImageView(m_device->device(), &image_view_ci, NULL, &image_view); - ASSERT_VK_SUCCESS(err); - - VkDescriptorImageInfo img_info = {}; - img_info.imageView = image_view; - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.pTexelBufferView = NULL; - descriptor_write.pBufferInfo = NULL; - descriptor_write.pImageInfo = &img_info; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; - descriptor_write.dstSet = ds.set_; - // TODO(whenning42): Update this check to look for a VUID when this error is - // assigned one. - const char *error_msg = " please only set either VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT "; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, error_msg); - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - m_errorMonitor->VerifyFound(); - vkDestroyImageView(m_device->device(), image_view, NULL); -} - -TEST_F(VkLayerTest, DSTypeMismatch) { - // Create DS w/ layout of one type and attempt Update w/ mis-matched type - VkResult err; - - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - " binding #0 with type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER but update type is VK_DESCRIPTOR_TYPE_SAMPLER"); - - ASSERT_NO_FATAL_FAILURE(Init()); - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - VkSampler sampler; - err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler); - ASSERT_VK_SUCCESS(err); - - VkDescriptorImageInfo info = {}; - info.sampler = sampler; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.descriptorCount = 1; - // This is a mismatched type for the layout which expects BUFFER - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - descriptor_write.pImageInfo = &info; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - m_errorMonitor->VerifyFound(); - - vkDestroySampler(m_device->device(), sampler, NULL); -} - -TEST_F(VkLayerTest, DSUpdateOutOfBounds) { - // For overlapping Update, have arrayIndex exceed that of layout - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-dstArrayElement-00321"); - - ASSERT_NO_FATAL_FAILURE(Init()); - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - VkBufferTest buffer_test(m_device, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); - if (!buffer_test.GetBufferCurrent()) { - // Something prevented creation of buffer so abort - printf("%s Buffer creation failed, skipping test\n", kSkipPrefix); - return; - } - - // Correctly update descriptor to avoid "NOT_UPDATED" error - VkDescriptorBufferInfo buff_info = {}; - buff_info.buffer = buffer_test.GetBuffer(); - buff_info.offset = 0; - buff_info.range = 1024; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstArrayElement = 1; /* This index out of bounds for the update */ - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_write.pBufferInfo = &buff_info; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, InvalidDSUpdateIndex) { - // Create layout w/ count of 1 and attempt update to that layout w/ binding index 2 - VkResult err; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-dstBinding-00315"); - - ASSERT_NO_FATAL_FAILURE(Init()); - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - VkSampler sampler; - err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler); - ASSERT_VK_SUCCESS(err); - - VkDescriptorImageInfo info = {}; - info.sampler = sampler; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstBinding = 2; - descriptor_write.descriptorCount = 1; - // This is the wrong type, but out of bounds will be flagged first - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - descriptor_write.pImageInfo = &info; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - m_errorMonitor->VerifyFound(); - - vkDestroySampler(m_device->device(), sampler, NULL); -} - -TEST_F(VkLayerTest, DSUpdateEmptyBinding) { - // Create layout w/ empty binding and attempt to update it - VkResult err; - - ASSERT_NO_FATAL_FAILURE(Init()); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_SAMPLER, 0 /* !! */, VK_SHADER_STAGE_ALL, nullptr}, - }); - - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - VkSampler sampler; - err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler); - ASSERT_VK_SUCCESS(err); - - VkDescriptorImageInfo info = {}; - info.sampler = sampler; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; // Lie here to avoid parameter_validation error - // This is the wrong type, but empty binding error will be flagged first - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - descriptor_write.pImageInfo = &info; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-dstBinding-00316"); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - - vkDestroySampler(m_device->device(), sampler, NULL); -} - -TEST_F(VkLayerTest, InvalidDSUpdateStruct) { - // Call UpdateDS w/ struct type other than valid VK_STRUCTUR_TYPE_UPDATE_* - // types - VkResult err; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, ".sType must be VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - VkSampler sampler; - err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler); - ASSERT_VK_SUCCESS(err); - - VkDescriptorImageInfo info = {}; - info.sampler = sampler; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; /* Intentionally broken struct type */ - descriptor_write.dstSet = ds.set_; - descriptor_write.descriptorCount = 1; - // This is the wrong type, but out of bounds will be flagged first - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - descriptor_write.pImageInfo = &info; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - m_errorMonitor->VerifyFound(); - - vkDestroySampler(m_device->device(), sampler, NULL); -} - -TEST_F(VkLayerTest, SampleDescriptorUpdateError) { - // Create a single Sampler descriptor and send it an invalid Sampler - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-00325"); - - ASSERT_NO_FATAL_FAILURE(Init()); - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - VkSampler sampler = (VkSampler)((size_t)0xbaadbeef); // Sampler with invalid handle - - VkDescriptorImageInfo descriptor_info; - memset(&descriptor_info, 0, sizeof(VkDescriptorImageInfo)); - descriptor_info.sampler = sampler; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - descriptor_write.pImageInfo = &descriptor_info; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, ImageViewDescriptorUpdateError) { - // Create a single combined Image/Sampler descriptor and send it an invalid - // imageView - VkResult err; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-00326"); - - ASSERT_NO_FATAL_FAILURE(Init()); - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - VkSampler sampler; - err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler); - ASSERT_VK_SUCCESS(err); - - VkImageView view = (VkImageView)((size_t)0xbaadbeef); // invalid imageView object - - VkDescriptorImageInfo descriptor_info; - memset(&descriptor_info, 0, sizeof(VkDescriptorImageInfo)); - descriptor_info.sampler = sampler; - descriptor_info.imageView = view; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_write.pImageInfo = &descriptor_info; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - m_errorMonitor->VerifyFound(); - - vkDestroySampler(m_device->device(), sampler, NULL); -} - -TEST_F(VkLayerTest, CopyDescriptorUpdateErrors) { - // Create DS w/ layout of 2 types, write update 1 and attempt to copy-update - // into the other - VkResult err; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - " binding #1 with type VK_DESCRIPTOR_TYPE_SAMPLER. Types do not match."); - - ASSERT_NO_FATAL_FAILURE(Init()); - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - {1, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - VkSampler sampler; - err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler); - ASSERT_VK_SUCCESS(err); - - VkDescriptorImageInfo info = {}; - info.sampler = sampler; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(VkWriteDescriptorSet)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstBinding = 1; // SAMPLER binding from layout above - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - descriptor_write.pImageInfo = &info; - // This write update should succeed - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - // Now perform a copy update that fails due to type mismatch - VkCopyDescriptorSet copy_ds_update; - memset(©_ds_update, 0, sizeof(VkCopyDescriptorSet)); - copy_ds_update.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; - copy_ds_update.srcSet = ds.set_; - copy_ds_update.srcBinding = 1; // Copy from SAMPLER binding - copy_ds_update.dstSet = ds.set_; - copy_ds_update.dstBinding = 0; // ERROR : copy to UNIFORM binding - copy_ds_update.descriptorCount = 1; // copy 1 descriptor - vkUpdateDescriptorSets(m_device->device(), 0, NULL, 1, ©_ds_update); - - m_errorMonitor->VerifyFound(); - // Now perform a copy update that fails due to binding out of bounds - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " does not have copy update src binding of 3."); - memset(©_ds_update, 0, sizeof(VkCopyDescriptorSet)); - copy_ds_update.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; - copy_ds_update.srcSet = ds.set_; - copy_ds_update.srcBinding = 3; // ERROR : Invalid binding for matching layout - copy_ds_update.dstSet = ds.set_; - copy_ds_update.dstBinding = 0; - copy_ds_update.descriptorCount = 1; // Copy 1 descriptor - vkUpdateDescriptorSets(m_device->device(), 0, NULL, 1, ©_ds_update); - - m_errorMonitor->VerifyFound(); - - // Now perform a copy update that fails due to binding out of bounds - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - " binding#1 with offset index of 1 plus update array offset of 0 and update of 5 " - "descriptors oversteps total number of descriptors in set: 2."); - - memset(©_ds_update, 0, sizeof(VkCopyDescriptorSet)); - copy_ds_update.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; - copy_ds_update.srcSet = ds.set_; - copy_ds_update.srcBinding = 1; - copy_ds_update.dstSet = ds.set_; - copy_ds_update.dstBinding = 0; - copy_ds_update.descriptorCount = 5; // ERROR copy 5 descriptors (out of bounds for layout) - vkUpdateDescriptorSets(m_device->device(), 0, NULL, 1, ©_ds_update); - - m_errorMonitor->VerifyFound(); - - vkDestroySampler(m_device->device(), sampler, NULL); -} - -TEST_F(VkPositiveLayerTest, CopyNonupdatedDescriptors) { - TEST_DESCRIPTION("Copy non-updated descriptors"); - unsigned int i; - - ASSERT_NO_FATAL_FAILURE(Init()); - OneOffDescriptorSet src_ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - {1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_ALL, nullptr}, - {2, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - OneOffDescriptorSet dst_ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - {1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - m_errorMonitor->ExpectSuccess(); - - const unsigned int copy_size = 2; - VkCopyDescriptorSet copy_ds_update[copy_size]; - memset(copy_ds_update, 0, sizeof(copy_ds_update)); - for (i = 0; i < copy_size; i++) { - copy_ds_update[i].sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; - copy_ds_update[i].srcSet = src_ds.set_; - copy_ds_update[i].srcBinding = i; - copy_ds_update[i].dstSet = dst_ds.set_; - copy_ds_update[i].dstBinding = i; - copy_ds_update[i].descriptorCount = 1; - } - vkUpdateDescriptorSets(m_device->device(), 0, NULL, copy_size, copy_ds_update); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkLayerTest, NumSamplesMismatch) { - // Create CommandBuffer where MSAA samples doesn't match RenderPass - // sampleCount - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Num samples mismatch! "); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = {}; - pipe_ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - pipe_ms_state_ci.pNext = NULL; - pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT; - pipe_ms_state_ci.sampleShadingEnable = 0; - pipe_ms_state_ci.minSampleShading = 1.0; - pipe_ms_state_ci.pSampleMask = NULL; - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); // We shouldn't need a fragment shader - // but add it to be able to run on more devices - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.SetMSAA(&pipe_ms_state_ci); - - m_errorMonitor->SetUnexpectedError("VUID-VkGraphicsPipelineCreateInfo-subpass-00757"); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - - // Render triangle (the error should trigger on the attempt to draw). - m_commandBuffer->Draw(3, 1, 0, 0); - - // Finalize recording of the command buffer - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, DrawWithPipelineIncompatibleWithRenderPass) { - TEST_DESCRIPTION( - "Hit RenderPass incompatible cases. Initial case is drawing with an active renderpass that's not compatible with the bound " - "pipeline state object's creation renderpass"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); // We shouldn't need a fragment shader - // but add it to be able to run on more devices - // Create a renderpass that will be incompatible with default renderpass - VkAttachmentReference color_att = {}; - color_att.layout = VK_IMAGE_LAYOUT_GENERAL; - VkSubpassDescription subpass = {}; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &color_att; - VkRenderPassCreateInfo rpci = {}; - rpci.subpassCount = 1; - rpci.pSubpasses = &subpass; - rpci.attachmentCount = 1; - VkAttachmentDescription attach_desc = {}; - attach_desc.samples = VK_SAMPLE_COUNT_1_BIT; - // Format incompatible with PSO RP color attach format B8G8R8A8_UNORM - attach_desc.format = VK_FORMAT_R8G8B8A8_UNORM; - attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL; - rpci.pAttachments = &attach_desc; - rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - VkRenderPass rp; - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; - m_viewports.push_back(viewport); - pipe.SetViewport(m_viewports); - VkRect2D rect = {{0, 0}, {64, 64}}; - m_scissors.push_back(rect); - pipe.SetScissor(m_scissors); - pipe.CreateVKPipeline(pipeline_layout.handle(), rp); - - VkCommandBufferInheritanceInfo cbii = {}; - cbii.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; - cbii.renderPass = rp; - cbii.subpass = 0; - VkCommandBufferBeginInfo cbbi = {}; - cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - cbbi.pInheritanceInfo = &cbii; - vkBeginCommandBuffer(m_commandBuffer->handle(), &cbbi); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDraw-renderPass-02684"); - // Render triangle (the error should trigger on the attempt to draw). - m_commandBuffer->Draw(3, 1, 0, 0); - - // Finalize recording of the command buffer - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - - m_errorMonitor->VerifyFound(); - - vkDestroyRenderPass(m_device->device(), rp, NULL); -} - -TEST_F(VkLayerTest, NumBlendAttachMismatch) { - // Create Pipeline where the number of blend attachments doesn't match the - // number of color attachments. In this case, we don't add any color - // blend attachments even though we have a color attachment. - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkGraphicsPipelineCreateInfo-attachmentCount-00746"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = {}; - pipe_ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - pipe_ms_state_ci.pNext = NULL; - pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - pipe_ms_state_ci.sampleShadingEnable = 0; - pipe_ms_state_ci.minSampleShading = 1.0; - pipe_ms_state_ci.pSampleMask = NULL; - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); // We shouldn't need a fragment shader - // but add it to be able to run on more devices - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.SetMSAA(&pipe_ms_state_ci); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, Bad2DArrayImageType) { - TEST_DESCRIPTION("Create an image with a flag specifying 2D_ARRAY_COMPATIBLE but not of imageType 3D."); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - } else { - printf("%s %s is not supported; skipping\n", kSkipPrefix, VK_KHR_MAINTENANCE1_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - // Trigger check by setting imagecreateflags to 2d_array_compat and imageType to 2D - VkImageCreateInfo ici = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - nullptr, - VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR, - VK_IMAGE_TYPE_2D, - VK_FORMAT_R8G8B8A8_UNORM, - {32, 32, 1}, - 1, - 1, - VK_SAMPLE_COUNT_1_BIT, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_SAMPLED_BIT, - VK_SHARING_MODE_EXCLUSIVE, - 0, - nullptr, - VK_IMAGE_LAYOUT_UNDEFINED}; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-flags-00950"); - VkImage image; - vkCreateImage(m_device->device(), &ici, NULL, &image); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, Maint1BindingSliceOf3DImage) { - TEST_DESCRIPTION( - "Attempt to bind a slice of a 3D texture in a descriptor set. This is explicitly disallowed by KHR_maintenance1 to keep " - "things simple for drivers."); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - } else { - printf("%s %s is not supported; skipping\n", kSkipPrefix, VK_KHR_MAINTENANCE1_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkResult err; - - OneOffDescriptorSet set(m_device, { - {0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}, - }); - - VkImageCreateInfo ici = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - nullptr, - VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR, - VK_IMAGE_TYPE_3D, - VK_FORMAT_R8G8B8A8_UNORM, - {32, 32, 32}, - 1, - 1, - VK_SAMPLE_COUNT_1_BIT, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_SAMPLED_BIT, - VK_SHARING_MODE_EXCLUSIVE, - 0, - nullptr, - VK_IMAGE_LAYOUT_UNDEFINED}; - VkImageObj image(m_device); - image.init(&ici); - ASSERT_TRUE(image.initialized()); - - VkImageViewCreateInfo ivci = { - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - nullptr, - 0, - image.handle(), - VK_IMAGE_VIEW_TYPE_2D, - VK_FORMAT_R8G8B8A8_UNORM, - {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, - VK_COMPONENT_SWIZZLE_IDENTITY}, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}, - }; - VkImageView view; - err = vkCreateImageView(m_device->device(), &ivci, nullptr, &view); - ASSERT_VK_SUCCESS(err); - - // Meat of the test. - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorImageInfo-imageView-00343"); - - VkDescriptorImageInfo dii = {VK_NULL_HANDLE, view, VK_IMAGE_LAYOUT_GENERAL}; - VkWriteDescriptorSet write = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr, set.set_, 0, 0, 1, - VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &dii, nullptr, nullptr}; - vkUpdateDescriptorSets(m_device->device(), 1, &write, 0, nullptr); - - m_errorMonitor->VerifyFound(); - - vkDestroyImageView(m_device->device(), view, nullptr); -} - -TEST_F(VkLayerTest, MissingClearAttachment) { - TEST_DESCRIPTION("Points to a wrong colorAttachment index in a VkClearAttachment structure passed to vkCmdClearAttachments"); - ASSERT_NO_FATAL_FAILURE(Init()); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearAttachments-aspectMask-02501"); - - VKTriangleTest(BsoFailCmdClearAttachments); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkPositiveLayerTest, ConfirmNoVLErrorWhenVkCmdClearAttachmentsCalledInSecondaryCB) { - TEST_DESCRIPTION( - "This test is to verify that when vkCmdClearAttachments is called by a secondary commandbuffer, the validation layers do " - "not throw an error if the primary commandbuffer begins a renderpass before executing the secondary commandbuffer."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkCommandBufferObj secondary(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); - - VkCommandBufferBeginInfo info = {}; - VkCommandBufferInheritanceInfo hinfo = {}; - info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; - info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - info.pInheritanceInfo = &hinfo; - hinfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; - hinfo.pNext = NULL; - hinfo.renderPass = renderPass(); - hinfo.subpass = 0; - hinfo.framebuffer = m_framebuffer; - hinfo.occlusionQueryEnable = VK_FALSE; - hinfo.queryFlags = 0; - hinfo.pipelineStatistics = 0; - - secondary.begin(&info); - VkClearAttachment color_attachment; - color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - color_attachment.clearValue.color.float32[0] = 0.0; - color_attachment.clearValue.color.float32[1] = 0.0; - color_attachment.clearValue.color.float32[2] = 0.0; - color_attachment.clearValue.color.float32[3] = 0.0; - color_attachment.colorAttachment = 0; - VkClearRect clear_rect = {{{0, 0}, {(uint32_t)m_width, (uint32_t)m_height}}, 0, 1}; - vkCmdClearAttachments(secondary.handle(), 1, &color_attachment, 1, &clear_rect); - secondary.end(); - // Modify clear rect here to verify that it doesn't cause validation error - clear_rect = {{{0, 0}, {99999999, 99999999}}, 0, 0}; - - m_commandBuffer->begin(); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary.handle()); - vkCmdEndRenderPass(m_commandBuffer->handle()); - m_commandBuffer->end(); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkLayerTest, CmdClearAttachmentTests) { - TEST_DESCRIPTION("Various tests for validating usage of vkCmdClearAttachments"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = {}; - pipe_ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - pipe_ms_state_ci.pNext = NULL; - pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - pipe_ms_state_ci.sampleShadingEnable = 0; - pipe_ms_state_ci.minSampleShading = 1.0; - pipe_ms_state_ci.pSampleMask = NULL; - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - // We shouldn't need a fragment shader but add it to be able to run - // on more devices - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.SetMSAA(&pipe_ms_state_ci); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - // Main thing we care about for this test is that the VkImage obj we're - // clearing matches Color Attachment of FB - // Also pass down other dummy params to keep driver and paramchecker happy - VkClearAttachment color_attachment; - color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - color_attachment.clearValue.color.float32[0] = 1.0; - color_attachment.clearValue.color.float32[1] = 1.0; - color_attachment.clearValue.color.float32[2] = 1.0; - color_attachment.clearValue.color.float32[3] = 1.0; - color_attachment.colorAttachment = 0; - VkClearRect clear_rect = {{{0, 0}, {(uint32_t)m_width, (uint32_t)m_height}}, 0, 1}; - - // Call for full-sized FB Color attachment prior to issuing a Draw - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, - "vkCmdClearAttachments() issued on command buffer object "); - vkCmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect); - m_errorMonitor->VerifyFound(); - - clear_rect.rect.extent.width = renderPassBeginInfo().renderArea.extent.width + 4; - clear_rect.rect.extent.height = clear_rect.rect.extent.height / 2; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearAttachments-pRects-00016"); - vkCmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect); - m_errorMonitor->VerifyFound(); - - // baseLayer >= view layers - clear_rect.rect.extent.width = (uint32_t)m_width; - clear_rect.baseArrayLayer = 1; - clear_rect.layerCount = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearAttachments-pRects-00017"); - vkCmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect); - m_errorMonitor->VerifyFound(); - - // baseLayer + layerCount > view layers - clear_rect.rect.extent.width = (uint32_t)m_width; - clear_rect.baseArrayLayer = 0; - clear_rect.layerCount = 2; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearAttachments-pRects-00017"); - vkCmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, VtxBufferBadIndex) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, - "but no vertex buffers are attached to this Pipeline State Object"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = {}; - pipe_ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - pipe_ms_state_ci.pNext = NULL; - pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - pipe_ms_state_ci.sampleShadingEnable = 0; - pipe_ms_state_ci.minSampleShading = 1.0; - pipe_ms_state_ci.pSampleMask = NULL; - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); // We shouldn't need a fragment shader - // but add it to be able to run on more devices - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.SetMSAA(&pipe_ms_state_ci); - pipe.SetViewport(m_viewports); - pipe.SetScissor(m_scissors); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - // Don't care about actual data, just need to get to draw to flag error - static const float vbo_data[3] = {1.f, 0.f, 1.f}; - VkConstantBufferObj vbo(m_device, sizeof(vbo_data), (const void *)&vbo_data, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); - m_commandBuffer->BindVertexBuffer(&vbo, (VkDeviceSize)0, 1); // VBO idx 1, but no VBO in PSO - m_commandBuffer->Draw(1, 0, 0, 0); - - m_errorMonitor->VerifyFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, InvalidQueryPoolCreate) { - TEST_DESCRIPTION("Attempt to create a query pool for PIPELINE_STATISTICS without enabling pipeline stats for the device."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - vk_testing::QueueCreateInfoArray queue_info(m_device->queue_props); - - VkDevice local_device; - VkDeviceCreateInfo device_create_info = {}; - auto features = m_device->phy().features(); - // Intentionally disable pipeline stats - features.pipelineStatisticsQuery = VK_FALSE; - device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - device_create_info.pNext = NULL; - device_create_info.queueCreateInfoCount = queue_info.size(); - device_create_info.pQueueCreateInfos = queue_info.data(); - device_create_info.enabledLayerCount = 0; - device_create_info.ppEnabledLayerNames = NULL; - device_create_info.pEnabledFeatures = &features; - VkResult err = vkCreateDevice(gpu(), &device_create_info, nullptr, &local_device); - ASSERT_VK_SUCCESS(err); - - VkQueryPoolCreateInfo qpci{}; - qpci.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; - qpci.queryType = VK_QUERY_TYPE_PIPELINE_STATISTICS; - qpci.queryCount = 1; - VkQueryPool query_pool; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkQueryPoolCreateInfo-queryType-00791"); - vkCreateQueryPool(local_device, &qpci, nullptr, &query_pool); - m_errorMonitor->VerifyFound(); - - vkDestroyDevice(local_device, nullptr); -} - -TEST_F(VkLayerTest, UnclosedQuery) { - TEST_DESCRIPTION("End a command buffer with a query still in progress."); - - const char *invalid_query = "Ending command buffer with in progress query: queryPool 0x"; - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkEvent event; - VkEventCreateInfo event_create_info{}; - event_create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - vkCreateEvent(m_device->device(), &event_create_info, nullptr, &event); - - VkQueue queue = VK_NULL_HANDLE; - vkGetDeviceQueue(m_device->device(), m_device->graphics_queue_node_index_, 0, &queue); - - m_commandBuffer->begin(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, invalid_query); - - VkQueryPool query_pool; - VkQueryPoolCreateInfo query_pool_create_info = {}; - query_pool_create_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; - query_pool_create_info.queryType = VK_QUERY_TYPE_OCCLUSION; - query_pool_create_info.queryCount = 1; - vkCreateQueryPool(m_device->device(), &query_pool_create_info, nullptr, &query_pool); - - vkCmdResetQueryPool(m_commandBuffer->handle(), query_pool, 0 /*startQuery*/, 1 /*queryCount*/); - vkCmdBeginQuery(m_commandBuffer->handle(), query_pool, 0, 0); - - vkEndCommandBuffer(m_commandBuffer->handle()); - m_errorMonitor->VerifyFound(); - - vkDestroyQueryPool(m_device->device(), query_pool, nullptr); - vkDestroyEvent(m_device->device(), event, nullptr); -} - -TEST_F(VkLayerTest, QueryPreciseBit) { - TEST_DESCRIPTION("Check for correct Query Precise Bit circumstances."); - ASSERT_NO_FATAL_FAILURE(Init()); - - // These tests require that the device support pipeline statistics query - VkPhysicalDeviceFeatures device_features = {}; - ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features)); - if (VK_TRUE != device_features.pipelineStatisticsQuery) { - printf("%s Test requires unsupported pipelineStatisticsQuery feature. Skipped.\n", kSkipPrefix); - return; - } - - std::vector<const char *> device_extension_names; - auto features = m_device->phy().features(); - - // Test for precise bit when query type is not OCCLUSION - if (features.occlusionQueryPrecise) { - VkEvent event; - VkEventCreateInfo event_create_info{}; - event_create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - vkCreateEvent(m_device->handle(), &event_create_info, nullptr, &event); - - m_commandBuffer->begin(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBeginQuery-queryType-00800"); - - VkQueryPool query_pool; - VkQueryPoolCreateInfo query_pool_create_info = {}; - query_pool_create_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; - query_pool_create_info.queryType = VK_QUERY_TYPE_PIPELINE_STATISTICS; - query_pool_create_info.queryCount = 1; - vkCreateQueryPool(m_device->handle(), &query_pool_create_info, nullptr, &query_pool); - - vkCmdResetQueryPool(m_commandBuffer->handle(), query_pool, 0, 1); - vkCmdBeginQuery(m_commandBuffer->handle(), query_pool, 0, VK_QUERY_CONTROL_PRECISE_BIT); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->end(); - vkDestroyQueryPool(m_device->handle(), query_pool, nullptr); - vkDestroyEvent(m_device->handle(), event, nullptr); - } - - // Test for precise bit when precise feature is not available - features.occlusionQueryPrecise = false; - VkDeviceObj test_device(0, gpu(), device_extension_names, &features); - - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = test_device.graphics_queue_node_index_; - - VkCommandPool command_pool; - vkCreateCommandPool(test_device.handle(), &pool_create_info, nullptr, &command_pool); - - VkCommandBufferAllocateInfo cmd = {}; - cmd.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - cmd.pNext = NULL; - cmd.commandPool = command_pool; - cmd.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - cmd.commandBufferCount = 1; - - VkCommandBuffer cmd_buffer; - VkResult err = vkAllocateCommandBuffers(test_device.handle(), &cmd, &cmd_buffer); - ASSERT_VK_SUCCESS(err); - - VkEvent event; - VkEventCreateInfo event_create_info{}; - event_create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - vkCreateEvent(test_device.handle(), &event_create_info, nullptr, &event); - - VkCommandBufferBeginInfo begin_info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr}; - - vkBeginCommandBuffer(cmd_buffer, &begin_info); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBeginQuery-queryType-00800"); - - VkQueryPool query_pool; - VkQueryPoolCreateInfo query_pool_create_info = {}; - query_pool_create_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; - query_pool_create_info.queryType = VK_QUERY_TYPE_OCCLUSION; - query_pool_create_info.queryCount = 1; - vkCreateQueryPool(test_device.handle(), &query_pool_create_info, nullptr, &query_pool); - - vkCmdResetQueryPool(cmd_buffer, query_pool, 0, 1); - vkCmdBeginQuery(cmd_buffer, query_pool, 0, VK_QUERY_CONTROL_PRECISE_BIT); - m_errorMonitor->VerifyFound(); - - vkEndCommandBuffer(cmd_buffer); - vkDestroyQueryPool(test_device.handle(), query_pool, nullptr); - vkDestroyEvent(test_device.handle(), event, nullptr); - vkDestroyCommandPool(test_device.handle(), command_pool, nullptr); -} - -TEST_F(VkLayerTest, VertexBufferInvalid) { - TEST_DESCRIPTION( - "Submit a command buffer using deleted vertex buffer, delete a buffer twice, use an invalid offset for each buffer type, " - "and attempt to bind a null buffer"); - - const char *deleted_buffer_in_command_buffer = "Cannot submit cmd buffer using deleted buffer "; - const char *invalid_offset_message = "VUID-vkBindBufferMemory-memoryOffset-01036"; - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = {}; - pipe_ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - pipe_ms_state_ci.pNext = NULL; - pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - pipe_ms_state_ci.sampleShadingEnable = 0; - pipe_ms_state_ci.minSampleShading = 1.0; - pipe_ms_state_ci.pSampleMask = nullptr; - - const VkPipelineLayoutObj pipeline_layout(m_device); - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.SetMSAA(&pipe_ms_state_ci); - pipe.SetViewport(m_viewports); - pipe.SetScissor(m_scissors); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - - { - // Create and bind a vertex buffer in a reduced scope, which will cause - // it to be deleted upon leaving this scope - const float vbo_data[3] = {1.f, 0.f, 1.f}; - VkVerticesObj draw_verticies(m_device, 1, 1, sizeof(vbo_data[0]), sizeof(vbo_data) / sizeof(vbo_data[0]), vbo_data); - draw_verticies.BindVertexBuffers(m_commandBuffer->handle()); - draw_verticies.AddVertexInputToPipe(pipe); - } - - m_commandBuffer->Draw(1, 0, 0, 0); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, deleted_buffer_in_command_buffer); - m_commandBuffer->QueueCommandBuffer(false); - m_errorMonitor->VerifyFound(); - - { - // Create and bind a vertex buffer in a reduced scope, and delete it - // twice, the second through the destructor - VkBufferTest buffer_test(m_device, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VkBufferTest::eDoubleDelete); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkDestroyBuffer-buffer-parameter"); - buffer_test.TestDoubleDestroy(); - } - 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(); - } - - { - // Attempt to bind a null buffer. - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkBindBufferMemory: required parameter buffer specified as VK_NULL_HANDLE"); - VkBufferTest buffer_test(m_device, 0, VkBufferTest::eBindNullBuffer); - (void)buffer_test; - m_errorMonitor->VerifyFound(); - } - - { - // Attempt to bind a fake buffer. - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindBufferMemory-buffer-parameter"); - VkBufferTest buffer_test(m_device, 0, VkBufferTest::eBindFakeBuffer); - (void)buffer_test; - m_errorMonitor->VerifyFound(); - } - - { - // Attempt to use an invalid handle to delete a buffer. - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkFreeMemory-memory-parameter"); - VkBufferTest buffer_test(m_device, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VkBufferTest::eFreeInvalidHandle); - (void)buffer_test; - } - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, BadVertexBufferOffset) { - TEST_DESCRIPTION("Submit an offset past the end of a vertex buffer"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - static const float vbo_data[3] = {1.f, 0.f, 1.f}; - VkConstantBufferObj vbo(m_device, sizeof(vbo_data), (const void *)&vbo_data, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindVertexBuffers-pOffsets-00626"); - m_commandBuffer->BindVertexBuffer(&vbo, (VkDeviceSize)(3 * sizeof(float)), 1); // Offset at the end of the buffer - m_errorMonitor->VerifyFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, InvalidVertexAttributeAlignment) { - TEST_DESCRIPTION("Check for proper aligment of attribAddress which depends on a bound pipeline and on a bound vertex buffer"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const VkPipelineLayoutObj pipeline_layout(m_device); - - struct VboEntry { - uint16_t input0[2]; - uint32_t input1; - float input2[4]; - }; - - const unsigned vbo_entry_count = 3; - const VboEntry vbo_data[vbo_entry_count] = {}; - - VkConstantBufferObj vbo(m_device, static_cast<int>(sizeof(VboEntry) * vbo_entry_count), - reinterpret_cast<const void *>(vbo_data), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); - - VkVertexInputBindingDescription input_binding; - input_binding.binding = 0; - input_binding.stride = sizeof(VboEntry); - input_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - VkVertexInputAttributeDescription input_attribs[3]; - - input_attribs[0].binding = 0; - // Location switch between attrib[0] and attrib[1] is intentional - input_attribs[0].location = 1; - input_attribs[0].format = VK_FORMAT_A8B8G8R8_UNORM_PACK32; - input_attribs[0].offset = offsetof(VboEntry, input1); - - input_attribs[1].binding = 0; - input_attribs[1].location = 0; - input_attribs[1].format = VK_FORMAT_R16G16_UNORM; - input_attribs[1].offset = offsetof(VboEntry, input0); - - input_attribs[2].binding = 0; - input_attribs[2].location = 2; - input_attribs[2].format = VK_FORMAT_R32G32B32A32_SFLOAT; - input_attribs[2].offset = offsetof(VboEntry, input2); - - char const *vsSource = - "#version 450\n" - "\n" - "layout(location = 0) in vec2 input0;" - "layout(location = 1) in vec4 input1;" - "layout(location = 2) in vec4 input2;" - "\n" - "void main(){\n" - " gl_Position = input1 + input2;\n" - " gl_Position.xy += input0;\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe1(m_device); - pipe1.AddDefaultColorAttachment(); - pipe1.AddShader(&vs); - pipe1.AddShader(&fs); - pipe1.AddVertexInputBindings(&input_binding, 1); - pipe1.AddVertexInputAttribs(&input_attribs[0], 3); - pipe1.SetViewport(m_viewports); - pipe1.SetScissor(m_scissors); - pipe1.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - input_binding.stride = 6; - - VkPipelineObj pipe2(m_device); - pipe2.AddDefaultColorAttachment(); - pipe2.AddShader(&vs); - pipe2.AddShader(&fs); - pipe2.AddVertexInputBindings(&input_binding, 1); - pipe2.AddVertexInputAttribs(&input_attribs[0], 3); - pipe2.SetViewport(m_viewports); - pipe2.SetScissor(m_scissors); - pipe2.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - // Test with invalid buffer offset - VkDeviceSize offset = 1; - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe1.handle()); - vkCmdBindVertexBuffers(m_commandBuffer->handle(), 0, 1, &vbo.handle(), &offset); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Invalid attribAddress alignment for vertex attribute 0"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Invalid attribAddress alignment for vertex attribute 1"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Invalid attribAddress alignment for vertex attribute 2"); - m_commandBuffer->Draw(1, 0, 0, 0); - m_errorMonitor->VerifyFound(); - - // Test with invalid buffer stride - offset = 0; - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe2.handle()); - vkCmdBindVertexBuffers(m_commandBuffer->handle(), 0, 1, &vbo.handle(), &offset); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Invalid attribAddress alignment for vertex attribute 0"); - // Attribute[1] is aligned properly even with a wrong stride - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Invalid attribAddress alignment for vertex attribute 2"); - m_commandBuffer->Draw(1, 0, 0, 0); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, InvalidVertexBindingDescriptions) { - TEST_DESCRIPTION( - "Attempt to create a graphics pipeline where:" - "1) count of vertex bindings exceeds device's maxVertexInputBindings limit" - "2) requested bindings include a duplicate binding value"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const VkPipelineLayoutObj pipeline_layout(m_device); - - const uint32_t binding_count = m_device->props.limits.maxVertexInputBindings + 1; - - std::vector<VkVertexInputBindingDescription> input_bindings(binding_count); - for (uint32_t i = 0; i < binding_count; ++i) { - input_bindings[i].binding = i; - input_bindings[i].stride = 4; - input_bindings[i].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - } - // Let the last binding description use same binding as the first one - input_bindings[binding_count - 1].binding = 0; - - VkVertexInputAttributeDescription input_attrib; - input_attrib.binding = 0; - input_attrib.location = 0; - input_attrib.format = VK_FORMAT_R32G32B32_SFLOAT; - input_attrib.offset = 0; - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddVertexInputBindings(input_bindings.data(), binding_count); - pipe.AddVertexInputAttribs(&input_attrib, 1); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineVertexInputStateCreateInfo-vertexBindingDescriptionCount-00613"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineVertexInputStateCreateInfo-pVertexBindingDescriptions-00616"); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, InvalidVertexAttributeDescriptions) { - TEST_DESCRIPTION( - "Attempt to create a graphics pipeline where:" - "1) count of vertex attributes exceeds device's maxVertexInputAttributes limit" - "2) requested location include a duplicate location value" - "3) binding used by one attribute is not defined by a binding description"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const VkPipelineLayoutObj pipeline_layout(m_device); - - VkVertexInputBindingDescription input_binding; - input_binding.binding = 0; - input_binding.stride = 4; - input_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - const uint32_t attribute_count = m_device->props.limits.maxVertexInputAttributes + 1; - std::vector<VkVertexInputAttributeDescription> input_attribs(attribute_count); - for (uint32_t i = 0; i < attribute_count; ++i) { - input_attribs[i].binding = 0; - input_attribs[i].location = i; - input_attribs[i].format = VK_FORMAT_R32G32B32_SFLOAT; - input_attribs[i].offset = 0; - } - // Let the last input_attribs description use same location as the first one - input_attribs[attribute_count - 1].location = 0; - // Let the last input_attribs description use binding which is not defined - input_attribs[attribute_count - 1].binding = 1; - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddVertexInputBindings(&input_binding, 1); - pipe.AddVertexInputAttribs(input_attribs.data(), attribute_count); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineVertexInputStateCreateInfo-vertexAttributeDescriptionCount-00614"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineVertexInputStateCreateInfo-binding-00615"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineVertexInputStateCreateInfo-pVertexAttributeDescriptions-00617"); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - m_errorMonitor->VerifyFound(); -} - -// INVALID_IMAGE_LAYOUT tests (one other case is hit by MapMemWithoutHostVisibleBit and not here) -TEST_F(VkLayerTest, InvalidImageLayout) { - TEST_DESCRIPTION( - "Hit all possible validation checks associated with the UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout error. " - "Generally these involve having images in the wrong layout when they're copied or transitioned."); - // 3 in ValidateCmdBufImageLayouts - // * -1 Attempt to submit cmd buf w/ deleted image - // * -2 Cmd buf submit of image w/ layout not matching first use w/ subresource - // * -3 Cmd buf submit of image w/ layout not matching first use w/o subresource - - ASSERT_NO_FATAL_FAILURE(Init()); - auto depth_format = FindSupportedDepthStencilFormat(gpu()); - if (!depth_format) { - printf("%s No Depth + Stencil format found. Skipped.\n", kSkipPrefix); - return; - } - // Create src & dst images to use for copy operations - VkImage src_image; - VkImage dst_image; - VkImage depth_image; - - const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; - const int32_t tex_width = 32; - const int32_t tex_height = 32; - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = tex_format; - image_create_info.extent.width = tex_width; - image_create_info.extent.height = tex_height; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 4; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - image_create_info.flags = 0; - - VkResult err = vkCreateImage(m_device->device(), &image_create_info, NULL, &src_image); - ASSERT_VK_SUCCESS(err); - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &dst_image); - ASSERT_VK_SUCCESS(err); - image_create_info.format = VK_FORMAT_D16_UNORM; - image_create_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &depth_image); - ASSERT_VK_SUCCESS(err); - - // Allocate memory - VkMemoryRequirements img_mem_reqs = {}; - VkMemoryAllocateInfo mem_alloc = {}; - VkDeviceMemory src_image_mem, dst_image_mem, depth_image_mem; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.allocationSize = 0; - mem_alloc.memoryTypeIndex = 0; - - vkGetImageMemoryRequirements(m_device->device(), src_image, &img_mem_reqs); - mem_alloc.allocationSize = img_mem_reqs.size; - bool pass = m_device->phy().set_memory_type(img_mem_reqs.memoryTypeBits, &mem_alloc, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &src_image_mem); - ASSERT_VK_SUCCESS(err); - - vkGetImageMemoryRequirements(m_device->device(), dst_image, &img_mem_reqs); - mem_alloc.allocationSize = img_mem_reqs.size; - pass = m_device->phy().set_memory_type(img_mem_reqs.memoryTypeBits, &mem_alloc, 0); - ASSERT_VK_SUCCESS(err); - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &dst_image_mem); - ASSERT_VK_SUCCESS(err); - - vkGetImageMemoryRequirements(m_device->device(), depth_image, &img_mem_reqs); - mem_alloc.allocationSize = img_mem_reqs.size; - pass = m_device->phy().set_memory_type(img_mem_reqs.memoryTypeBits, &mem_alloc, 0); - ASSERT_VK_SUCCESS(err); - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &depth_image_mem); - ASSERT_VK_SUCCESS(err); - - err = vkBindImageMemory(m_device->device(), src_image, src_image_mem, 0); - ASSERT_VK_SUCCESS(err); - err = vkBindImageMemory(m_device->device(), dst_image, dst_image_mem, 0); - ASSERT_VK_SUCCESS(err); - err = vkBindImageMemory(m_device->device(), depth_image, depth_image_mem, 0); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - VkImageCopy copy_region; - copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.srcSubresource.mipLevel = 0; - copy_region.srcSubresource.baseArrayLayer = 0; - copy_region.srcSubresource.layerCount = 1; - copy_region.srcOffset.x = 0; - copy_region.srcOffset.y = 0; - copy_region.srcOffset.z = 0; - copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.dstSubresource.mipLevel = 0; - copy_region.dstSubresource.baseArrayLayer = 0; - copy_region.dstSubresource.layerCount = 1; - copy_region.dstOffset.x = 0; - copy_region.dstOffset.y = 0; - copy_region.dstOffset.z = 0; - copy_region.extent.width = 1; - copy_region.extent.height = 1; - copy_region.extent.depth = 1; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, - "layout should be VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL instead of GENERAL."); - m_errorMonitor->SetUnexpectedError("layout should be VK_IMAGE_LAYOUT_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(); - // The first call hits the expected WARNING and skips the call down the chain, so call a second time to call down chain and - // update layer state - m_errorMonitor->SetUnexpectedError("layout should be VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL instead of GENERAL."); - m_errorMonitor->SetUnexpectedError("layout should be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL instead of GENERAL."); - m_commandBuffer->CopyImage(src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); - // Now cause error due to src image layout changing - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImage-srcImageLayout-00128"); - m_errorMonitor->SetUnexpectedError("is VK_IMAGE_LAYOUT_UNDEFINED but can only be VK_IMAGE_LAYOUT"); - 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, "VUID-vkCmdCopyImage-srcImageLayout-00129"); - m_errorMonitor->SetUnexpectedError( - "with specific layout VK_IMAGE_LAYOUT_UNDEFINED that doesn't match the previously used 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 should be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL instead of GENERAL."); - m_errorMonitor->SetUnexpectedError("layout should be VK_IMAGE_LAYOUT_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 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImage-dstImageLayout-00133"); - m_errorMonitor->SetUnexpectedError( - "is VK_IMAGE_LAYOUT_UNDEFINED but can only be 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, "VUID-vkCmdCopyImage-dstImageLayout-00134"); - m_errorMonitor->SetUnexpectedError( - "with specific layout VK_IMAGE_LAYOUT_UNDEFINED that doesn't match the previously used 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(); - - // Convert dst and depth images to TRANSFER_DST for subsequent tests - VkImageMemoryBarrier transfer_dst_image_barrier[1] = {}; - transfer_dst_image_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - transfer_dst_image_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - transfer_dst_image_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - transfer_dst_image_barrier[0].srcAccessMask = 0; - transfer_dst_image_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - transfer_dst_image_barrier[0].image = dst_image; - transfer_dst_image_barrier[0].subresourceRange.layerCount = image_create_info.arrayLayers; - transfer_dst_image_barrier[0].subresourceRange.levelCount = image_create_info.mipLevels; - transfer_dst_image_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - NULL, 0, NULL, 1, transfer_dst_image_barrier); - transfer_dst_image_barrier[0].image = depth_image; - transfer_dst_image_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - NULL, 0, NULL, 1, transfer_dst_image_barrier); - - // Cause errors due to clearing with invalid image layouts - VkClearColorValue color_clear_value = {}; - VkImageSubresourceRange clear_range; - clear_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - clear_range.baseMipLevel = 0; - clear_range.baseArrayLayer = 0; - clear_range.layerCount = 1; - clear_range.levelCount = 1; - - // Fail due to explicitly prohibited layout for color clear (only GENERAL and TRANSFER_DST are permitted). - // Since the image is currently not in UNDEFINED layout, this will emit two errors. - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearColorImage-imageLayout-00005"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearColorImage-imageLayout-00004"); - m_commandBuffer->ClearColorImage(dst_image, VK_IMAGE_LAYOUT_UNDEFINED, &color_clear_value, 1, &clear_range); - m_errorMonitor->VerifyFound(); - // Fail due to provided layout not matching actual current layout for color clear. - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearColorImage-imageLayout-00004"); - m_commandBuffer->ClearColorImage(dst_image, VK_IMAGE_LAYOUT_GENERAL, &color_clear_value, 1, &clear_range); - m_errorMonitor->VerifyFound(); - - VkClearDepthStencilValue depth_clear_value = {}; - clear_range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - - // Fail due to explicitly prohibited layout for depth clear (only GENERAL and TRANSFER_DST are permitted). - // Since the image is currently not in UNDEFINED layout, this will emit two errors. - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearDepthStencilImage-imageLayout-00012"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearDepthStencilImage-imageLayout-00011"); - m_commandBuffer->ClearDepthStencilImage(depth_image, VK_IMAGE_LAYOUT_UNDEFINED, &depth_clear_value, 1, &clear_range); - m_errorMonitor->VerifyFound(); - // Fail due to provided layout not matching actual current layout for depth clear. - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearDepthStencilImage-imageLayout-00011"); - m_commandBuffer->ClearDepthStencilImage(depth_image, VK_IMAGE_LAYOUT_GENERAL, &depth_clear_value, 1, &clear_range); - m_errorMonitor->VerifyFound(); - - // Now cause error due to bad image layout transition in PipelineBarrier - VkImageMemoryBarrier image_barrier[1] = {}; - image_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - image_barrier[0].oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - image_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - image_barrier[0].image = src_image; - image_barrier[0].subresourceRange.layerCount = image_create_info.arrayLayers; - image_barrier[0].subresourceRange.levelCount = image_create_info.mipLevels; - image_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-oldLayout-01197"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-oldLayout-01210"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - NULL, 0, NULL, 1, image_barrier); - m_errorMonitor->VerifyFound(); - - // Finally some layout errors at RenderPass create time - // Just hacking in specific state to get to the errors we want so don't copy this unless you know what you're doing. - VkAttachmentReference attach = {}; - // perf warning for GENERAL layout w/ non-DS input attachment - attach.layout = VK_IMAGE_LAYOUT_GENERAL; - VkSubpassDescription subpass = {}; - subpass.inputAttachmentCount = 1; - subpass.pInputAttachments = &attach; - VkRenderPassCreateInfo rpci = {}; - rpci.subpassCount = 1; - rpci.pSubpasses = &subpass; - rpci.attachmentCount = 1; - VkAttachmentDescription attach_desc = {}; - attach_desc.format = VK_FORMAT_UNDEFINED; - attach_desc.samples = VK_SAMPLE_COUNT_1_BIT; - attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL; - rpci.pAttachments = &attach_desc; - rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - VkRenderPass rp; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, - "Layout for input attachment is GENERAL but should be READ_ONLY_OPTIMAL."); - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - m_errorMonitor->VerifyFound(); - // error w/ non-general layout - attach.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Layout for input attachment is VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL but can only be READ_ONLY_OPTIMAL or GENERAL."); - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - m_errorMonitor->VerifyFound(); - subpass.inputAttachmentCount = 0; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &attach; - attach.layout = VK_IMAGE_LAYOUT_GENERAL; - // perf warning for GENERAL layout on color attachment - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, - "Layout for color attachment is GENERAL but should be COLOR_ATTACHMENT_OPTIMAL."); - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - m_errorMonitor->VerifyFound(); - // error w/ non-color opt or GENERAL layout for color attachment - attach.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Layout for color attachment is VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL but can only be COLOR_ATTACHMENT_OPTIMAL or GENERAL."); - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - m_errorMonitor->VerifyFound(); - subpass.colorAttachmentCount = 0; - subpass.pDepthStencilAttachment = &attach; - attach.layout = VK_IMAGE_LAYOUT_GENERAL; - // perf warning for GENERAL layout on DS attachment - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, - "GENERAL layout for depth attachment may not give optimal performance."); - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - m_errorMonitor->VerifyFound(); - // error w/ non-ds opt or GENERAL layout for color attachment - attach.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Layout for depth attachment is VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL but can only be " - "DEPTH_STENCIL_ATTACHMENT_OPTIMAL, DEPTH_STENCIL_READ_ONLY_OPTIMAL or GENERAL."); - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - m_errorMonitor->VerifyFound(); - // For this error we need a valid renderpass so create default one - attach.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - attach.attachment = 0; - attach_desc.format = depth_format; - attach_desc.samples = VK_SAMPLE_COUNT_1_BIT; - attach_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attach_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attach_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - // Can't do a CLEAR load on READ_ONLY initialLayout - attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - attach_desc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "with invalid first layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL"); - vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - m_errorMonitor->VerifyFound(); - - vkFreeMemory(m_device->device(), src_image_mem, NULL); - vkFreeMemory(m_device->device(), dst_image_mem, NULL); - vkFreeMemory(m_device->device(), depth_image_mem, NULL); - vkDestroyImage(m_device->device(), src_image, NULL); - vkDestroyImage(m_device->device(), dst_image, NULL); - vkDestroyImage(m_device->device(), depth_image, NULL); -} - -TEST_F(VkLayerTest, InvalidStorageImageLayout) { - TEST_DESCRIPTION("Attempt to update a STORAGE_IMAGE descriptor w/o GENERAL layout."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - const VkFormat tex_format = VK_FORMAT_R8G8B8A8_UNORM; - VkImageTiling tiling; - VkFormatProperties format_properties; - vkGetPhysicalDeviceFormatProperties(gpu(), tex_format, &format_properties); - if (format_properties.linearTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) { - tiling = VK_IMAGE_TILING_LINEAR; - } else if (format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) { - tiling = VK_IMAGE_TILING_OPTIMAL; - } else { - printf("%s Device does not support VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT; skipped.\n", kSkipPrefix); - return; - } - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}, - }); - - VkImageObj image(m_device); - image.Init(32, 32, 1, tex_format, VK_IMAGE_USAGE_STORAGE_BIT, tiling, 0); - ASSERT_TRUE(image.initialized()); - VkImageView view = image.targetView(tex_format); - - VkDescriptorImageInfo image_info = {}; - image_info.imageView = view; - image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - descriptor_write.pImageInfo = &image_info; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - " of VK_DESCRIPTOR_TYPE_STORAGE_IMAGE type is being updated with layout " - "VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL but according to spec "); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, NonSimultaneousSecondaryMarksPrimary) { - ASSERT_NO_FATAL_FAILURE(Init()); - const char *simultaneous_use_message = - "does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set and will cause primary command buffer"; - - VkCommandBufferObj secondary(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); - - secondary.begin(); - secondary.end(); - - VkCommandBufferBeginInfo cbbi = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - nullptr, - VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, - nullptr, - }; - - m_commandBuffer->begin(&cbbi); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, simultaneous_use_message); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary.handle()); - m_errorMonitor->VerifyFound(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, SimultaneousUseSecondaryTwoExecutes) { - ASSERT_NO_FATAL_FAILURE(Init()); - - const char *simultaneous_use_message = "without VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set!"; - - VkCommandBufferObj secondary(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); - - VkCommandBufferInheritanceInfo inh = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, - nullptr, - }; - VkCommandBufferBeginInfo cbbi = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, 0, &inh}; - - secondary.begin(&cbbi); - secondary.end(); - - m_commandBuffer->begin(); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary.handle()); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, simultaneous_use_message); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary.handle()); - m_errorMonitor->VerifyFound(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, SimultaneousUseSecondarySingleExecute) { - ASSERT_NO_FATAL_FAILURE(Init()); - - // variation on previous test executing the same CB twice in the same - // CmdExecuteCommands call - - const char *simultaneous_use_message = "without VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set!"; - - VkCommandBufferObj secondary(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); - - VkCommandBufferInheritanceInfo inh = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, - nullptr, - }; - VkCommandBufferBeginInfo cbbi = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, 0, &inh}; - - secondary.begin(&cbbi); - secondary.end(); - - m_commandBuffer->begin(); - VkCommandBuffer cbs[] = {secondary.handle(), secondary.handle()}; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, simultaneous_use_message); - vkCmdExecuteCommands(m_commandBuffer->handle(), 2, cbs); - m_errorMonitor->VerifyFound(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, SimultaneousUseOneShot) { - TEST_DESCRIPTION("Submit the same command buffer twice in one submit looking for simultaneous use and one time submit errors"); - const char *simultaneous_use_message = "is already in use and is not marked for simultaneous use"; - const char *one_shot_message = "VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT set, but has been submitted"; - ASSERT_NO_FATAL_FAILURE(Init()); - - VkCommandBuffer cmd_bufs[2]; - VkCommandBufferAllocateInfo alloc_info; - alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - alloc_info.pNext = NULL; - alloc_info.commandBufferCount = 2; - alloc_info.commandPool = m_commandPool->handle(); - alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(m_device->device(), &alloc_info, cmd_bufs); - - VkCommandBufferBeginInfo cb_binfo; - cb_binfo.pNext = NULL; - cb_binfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - cb_binfo.pInheritanceInfo = VK_NULL_HANDLE; - cb_binfo.flags = 0; - vkBeginCommandBuffer(cmd_bufs[0], &cb_binfo); - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - vkCmdSetViewport(cmd_bufs[0], 0, 1, &viewport); - vkEndCommandBuffer(cmd_bufs[0]); - VkCommandBuffer duplicates[2] = {cmd_bufs[0], cmd_bufs[0]}; - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 2; - submit_info.pCommandBuffers = duplicates; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, simultaneous_use_message); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - vkQueueWaitIdle(m_device->m_queue); - - // Set one time use and now look for one time submit - duplicates[0] = duplicates[1] = cmd_bufs[1]; - cb_binfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT | VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - vkBeginCommandBuffer(cmd_bufs[1], &cb_binfo); - vkCmdSetViewport(cmd_bufs[1], 0, 1, &viewport); - vkEndCommandBuffer(cmd_bufs[1]); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, one_shot_message); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - vkQueueWaitIdle(m_device->m_queue); -} - -TEST_F(VkLayerTest, StageMaskGsTsEnabled) { - TEST_DESCRIPTION( - "Attempt to use a stageMask w/ geometry shader and tesselation shader bits enabled when those features are disabled on the " - "device."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - std::vector<const char *> device_extension_names; - auto features = m_device->phy().features(); - // Make sure gs & ts are disabled - features.geometryShader = false; - features.tessellationShader = false; - // The sacrificial device object - VkDeviceObj test_device(0, gpu(), device_extension_names, &features); - - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = test_device.graphics_queue_node_index_; - - VkCommandPool command_pool; - vkCreateCommandPool(test_device.handle(), &pool_create_info, nullptr, &command_pool); - - VkCommandBufferAllocateInfo cmd = {}; - cmd.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - cmd.pNext = NULL; - cmd.commandPool = command_pool; - cmd.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - cmd.commandBufferCount = 1; - - VkCommandBuffer cmd_buffer; - VkResult err = vkAllocateCommandBuffers(test_device.handle(), &cmd, &cmd_buffer); - ASSERT_VK_SUCCESS(err); - - VkEvent event; - VkEventCreateInfo evci = {}; - evci.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - VkResult result = vkCreateEvent(test_device.handle(), &evci, NULL, &event); - ASSERT_VK_SUCCESS(result); - - VkCommandBufferBeginInfo cbbi = {}; - cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(cmd_buffer, &cbbi); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetEvent-stageMask-01150"); - vkCmdSetEvent(cmd_buffer, event, VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetEvent-stageMask-01151"); - vkCmdSetEvent(cmd_buffer, event, VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT); - m_errorMonitor->VerifyFound(); - - vkDestroyEvent(test_device.handle(), event, NULL); - vkDestroyCommandPool(test_device.handle(), command_pool, NULL); -} - -TEST_F(VkLayerTest, EventInUseDestroyedSignaled) { - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - m_commandBuffer->begin(); - - VkEvent event; - VkEventCreateInfo event_create_info = {}; - event_create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - vkCreateEvent(m_device->device(), &event_create_info, nullptr, &event); - vkCmdSetEvent(m_commandBuffer->handle(), event, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - - m_commandBuffer->end(); - vkDestroyEvent(m_device->device(), event, nullptr); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "that is invalid because bound"); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, InUseDestroyedSignaled) { - TEST_DESCRIPTION( - "Use vkCmdExecuteCommands with invalid state in primary and secondary command buffers. Delete objects that are in use. " - "Call VkQueueSubmit with an event that has been deleted."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - m_errorMonitor->ExpectSuccess(); - - VkSemaphoreCreateInfo semaphore_create_info = {}; - semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - VkSemaphore semaphore; - ASSERT_VK_SUCCESS(vkCreateSemaphore(m_device->device(), &semaphore_create_info, nullptr, &semaphore)); - VkFenceCreateInfo fence_create_info = {}; - fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - VkFence fence; - ASSERT_VK_SUCCESS(vkCreateFence(m_device->device(), &fence_create_info, nullptr, &fence)); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - VkBufferTest buffer_test(m_device, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); - - VkDescriptorBufferInfo buffer_info = {}; - buffer_info.buffer = buffer_test.GetBuffer(); - buffer_info.offset = 0; - buffer_info.range = 1024; - - VkWriteDescriptorSet write_descriptor_set = {}; - write_descriptor_set.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write_descriptor_set.dstSet = ds.set_; - write_descriptor_set.descriptorCount = 1; - write_descriptor_set.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - write_descriptor_set.pBufferInfo = &buffer_info; - - vkUpdateDescriptorSets(m_device->device(), 1, &write_descriptor_set, 0, nullptr); - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - - pipe.CreateVKPipeline(pipeline_layout.handle(), m_renderPass); - - VkEvent event; - VkEventCreateInfo event_create_info = {}; - event_create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - vkCreateEvent(m_device->device(), &event_create_info, nullptr, &event); - - m_commandBuffer->begin(); - - vkCmdSetEvent(m_commandBuffer->handle(), event, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, &ds.set_, 0, - NULL); - - m_commandBuffer->end(); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &semaphore; - vkQueueSubmit(m_device->m_queue, 1, &submit_info, fence); - m_errorMonitor->Reset(); // resume logmsg processing - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkDestroyEvent-event-01145"); - vkDestroyEvent(m_device->device(), event, nullptr); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkDestroySemaphore-semaphore-01137"); - vkDestroySemaphore(m_device->device(), semaphore, nullptr); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Fence 0x"); - vkDestroyFence(m_device->device(), fence, nullptr); - 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); -} - -TEST_F(VkLayerTest, QueryPoolInUseDestroyedSignaled) { - TEST_DESCRIPTION("Delete in-use query pool."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkQueryPool query_pool; - VkQueryPoolCreateInfo query_pool_ci{}; - query_pool_ci.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; - query_pool_ci.queryType = VK_QUERY_TYPE_TIMESTAMP; - query_pool_ci.queryCount = 1; - vkCreateQueryPool(m_device->device(), &query_pool_ci, nullptr, &query_pool); - m_commandBuffer->begin(); - // Reset query pool to create binding with cmd buffer - vkCmdResetQueryPool(m_commandBuffer->handle(), query_pool, 0, 1); - - m_commandBuffer->end(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkGetQueryPoolResults-queryType-00818"); - uint32_t data_space[16]; - m_errorMonitor->SetUnexpectedError("Cannot get query results on queryPool"); - vkGetQueryPoolResults(m_device->handle(), query_pool, 0, 1, sizeof(data_space), &data_space, sizeof(uint32_t), - VK_QUERY_RESULT_PARTIAL_BIT); - m_errorMonitor->VerifyFound(); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - // Submit cmd buffer and then destroy query pool while in-flight - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkDestroyQueryPool-queryPool-00793"); - vkDestroyQueryPool(m_device->handle(), query_pool, NULL); - m_errorMonitor->VerifyFound(); - - 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 QueryPool obj"); - vkDestroyQueryPool(m_device->handle(), query_pool, NULL); -} - -TEST_F(VkLayerTest, PipelineInUseDestroyedSignaled) { - TEST_DESCRIPTION("Delete in-use pipeline."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const VkPipelineLayoutObj pipeline_layout(m_device); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkDestroyPipeline-pipeline-00765"); - // Create PSO to be used for draw-time errors below - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - // Store pipeline handle so we can actually delete it before test finishes - VkPipeline delete_this_pipeline; - { // Scope pipeline so it will be auto-deleted - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - delete_this_pipeline = pipe.handle(); - - m_commandBuffer->begin(); - // Bind pipeline to cmd buffer - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - - m_commandBuffer->end(); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - // Submit cmd buffer and then pipeline destroyed while in-flight - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - } // Pipeline deletion triggered here - 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); -} - -TEST_F(VkLayerTest, CreateImageViewBreaksParameterCompatibilityRequirements) { - TEST_DESCRIPTION( - "Attempts to create an Image View with a view type that does not match the image type it is being created from."); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkPhysicalDeviceMemoryProperties memProps; - vkGetPhysicalDeviceMemoryProperties(m_device->phy().handle(), &memProps); - - // Test mismatch detection for image of type VK_IMAGE_TYPE_1D - VkImageCreateInfo imgInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - nullptr, - VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, - VK_IMAGE_TYPE_1D, - VK_FORMAT_R8G8B8A8_UNORM, - {1, 1, 1}, - 1, - 1, - VK_SAMPLE_COUNT_1_BIT, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_SHARING_MODE_EXCLUSIVE, - 0, - nullptr, - VK_IMAGE_LAYOUT_UNDEFINED}; - VkImageObj image1D(m_device); - image1D.init(&imgInfo); - ASSERT_TRUE(image1D.initialized()); - - // Initialize VkImageViewCreateInfo with mismatched viewType - VkImageView imageView; - VkImageViewCreateInfo ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.image = image1D.handle(); - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.format = VK_FORMAT_R8G8B8A8_UNORM; - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - ivci.subresourceRange.levelCount = 1; - ivci.subresourceRange.baseArrayLayer = 0; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - // Test for error message - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkCreateImageView(): pCreateInfo->viewType VK_IMAGE_VIEW_TYPE_2D is not compatible with image"); - vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyFound(); - - // Test mismatch detection for image of type VK_IMAGE_TYPE_2D - imgInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - nullptr, - VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, - VK_IMAGE_TYPE_2D, - VK_FORMAT_R8G8B8A8_UNORM, - {1, 1, 1}, - 1, - 6, - VK_SAMPLE_COUNT_1_BIT, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_SHARING_MODE_EXCLUSIVE, - 0, - nullptr, - VK_IMAGE_LAYOUT_UNDEFINED}; - VkImageObj image2D(m_device); - image2D.init(&imgInfo); - ASSERT_TRUE(image2D.initialized()); - - // Initialize VkImageViewCreateInfo with mismatched viewType - ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.image = image2D.handle(); - ivci.viewType = VK_IMAGE_VIEW_TYPE_3D; - ivci.format = VK_FORMAT_R8G8B8A8_UNORM; - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - ivci.subresourceRange.levelCount = 1; - ivci.subresourceRange.baseArrayLayer = 0; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - // Test for error message - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkCreateImageView(): pCreateInfo->viewType VK_IMAGE_VIEW_TYPE_3D is not compatible with image"); - vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyFound(); - - // Change VkImageViewCreateInfo to different mismatched viewType - ivci.viewType = VK_IMAGE_VIEW_TYPE_CUBE; - ivci.subresourceRange.layerCount = 6; - - // Test for error message - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-image-01003"); - vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyFound(); - - // Test mismatch detection for image of type VK_IMAGE_TYPE_3D - imgInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - nullptr, - VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, - VK_IMAGE_TYPE_3D, - VK_FORMAT_R8G8B8A8_UNORM, - {1, 1, 1}, - 1, - 1, - VK_SAMPLE_COUNT_1_BIT, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_SHARING_MODE_EXCLUSIVE, - 0, - nullptr, - VK_IMAGE_LAYOUT_UNDEFINED}; - VkImageObj image3D(m_device); - image3D.init(&imgInfo); - ASSERT_TRUE(image3D.initialized()); - - // Initialize VkImageViewCreateInfo with mismatched viewType - ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.image = image3D.handle(); - ivci.viewType = VK_IMAGE_VIEW_TYPE_1D; - ivci.format = VK_FORMAT_R8G8B8A8_UNORM; - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - ivci.subresourceRange.levelCount = 1; - ivci.subresourceRange.baseArrayLayer = 0; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - // Test for error message - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkCreateImageView(): pCreateInfo->viewType VK_IMAGE_VIEW_TYPE_1D is not compatible with image"); - vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyFound(); - - // Change VkImageViewCreateInfo to different mismatched viewType - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - - // Test for error message - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME)) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-image-01005"); - } else { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-subResourceRange-01021"); - } - - vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyFound(); - - // Check if the device can make the image required for this test case. - VkImageFormatProperties formProps = {{0, 0, 0}, 0, 0, 0, 0}; - VkResult res = vkGetPhysicalDeviceImageFormatProperties( - m_device->phy().handle(), VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TYPE_3D, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR | VK_IMAGE_CREATE_SPARSE_BINDING_BIT, - &formProps); - - // If not, skip this part of the test. - if (res || !m_device->phy().features().sparseBinding || - !DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME)) { - printf("%s %s is not supported.\n", kSkipPrefix, VK_KHR_MAINTENANCE1_EXTENSION_NAME); - return; - } - - // Initialize VkImageCreateInfo with VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR and VK_IMAGE_CREATE_SPARSE_BINDING_BIT which - // are incompatible create flags. - imgInfo = { - VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - nullptr, - VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR | VK_IMAGE_CREATE_SPARSE_BINDING_BIT, - VK_IMAGE_TYPE_3D, - VK_FORMAT_R8G8B8A8_UNORM, - {1, 1, 1}, - 1, - 1, - VK_SAMPLE_COUNT_1_BIT, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_SHARING_MODE_EXCLUSIVE, - 0, - nullptr, - VK_IMAGE_LAYOUT_UNDEFINED}; - VkImage imageSparse; - - // Creating a sparse image means we should not bind memory to it. - res = vkCreateImage(m_device->device(), &imgInfo, NULL, &imageSparse); - ASSERT_FALSE(res); - - // Initialize VkImageViewCreateInfo to create a view that will attempt to utilize VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR. - ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.image = imageSparse; - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.format = VK_FORMAT_R8G8B8A8_UNORM; - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - ivci.subresourceRange.levelCount = 1; - ivci.subresourceRange.baseArrayLayer = 0; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - // Test for error message - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - " when the VK_IMAGE_CREATE_SPARSE_BINDING_BIT, VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT, or " - "VK_IMAGE_CREATE_SPARSE_ALIASED_BIT flags are enabled."); - vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyFound(); - - // Clean up - vkDestroyImage(m_device->device(), imageSparse, nullptr); -} - -TEST_F(VkLayerTest, CreateImageViewFormatFeatureMismatch) { - TEST_DESCRIPTION("Create view with a format that does not have the same features as the image format."); - - if (!EnableDeviceProfileLayer()) { - printf("%s Failed to enable device profile layer.\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - ASSERT_NO_FATAL_FAILURE(InitState()); - - PFN_vkSetPhysicalDeviceFormatPropertiesEXT fpvkSetPhysicalDeviceFormatPropertiesEXT = nullptr; - PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT = nullptr; - - // Load required functions - if (!LoadDeviceProfileLayer(fpvkSetPhysicalDeviceFormatPropertiesEXT, fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT)) { - printf("%s Failed to device profile layer.\n", kSkipPrefix); - return; - } - - // List of features to be tested - VkFormatFeatureFlagBits features[] = {VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT, VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT, - VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT}; - uint32_t feature_count = 4; - // List of usage cases for each feature test - VkImageUsageFlags usages[] = {VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT}; - // List of errors that will be thrown in order of tests run - std::string optimal_error_codes[] = { - "VUID-VkImageViewCreateInfo-usage-02274", - "VUID-VkImageViewCreateInfo-usage-02275", - "VUID-VkImageViewCreateInfo-usage-02276", - "VUID-VkImageViewCreateInfo-usage-02277", - }; - - VkFormatProperties formatProps; - - // First three tests - uint32_t i = 0; - for (i = 0; i < (feature_count - 1); i++) { - // Modify formats to have mismatched features - - // Format for image - fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT(gpu(), VK_FORMAT_R32G32B32A32_UINT, &formatProps); - formatProps.optimalTilingFeatures |= features[i]; - fpvkSetPhysicalDeviceFormatPropertiesEXT(gpu(), VK_FORMAT_R32G32B32A32_UINT, formatProps); - - memset(&formatProps, 0, sizeof(formatProps)); - - // Format for view - fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT(gpu(), VK_FORMAT_R32G32B32A32_SINT, &formatProps); - formatProps.optimalTilingFeatures = features[(i + 1) % feature_count]; - fpvkSetPhysicalDeviceFormatPropertiesEXT(gpu(), VK_FORMAT_R32G32B32A32_SINT, formatProps); - - // Create image with modified format - VkImageCreateInfo imgInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - nullptr, - VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, - VK_IMAGE_TYPE_2D, - VK_FORMAT_R32G32B32A32_UINT, - {1, 1, 1}, - 1, - 1, - VK_SAMPLE_COUNT_1_BIT, - VK_IMAGE_TILING_OPTIMAL, - usages[i], - VK_SHARING_MODE_EXCLUSIVE, - 0, - nullptr, - VK_IMAGE_LAYOUT_UNDEFINED}; - VkImageObj image(m_device); - image.init(&imgInfo); - ASSERT_TRUE(image.initialized()); - - VkImageView imageView; - - // Initialize VkImageViewCreateInfo with modified format - VkImageViewCreateInfo ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.image = image.handle(); - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.format = VK_FORMAT_R32G32B32A32_SINT; - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - ivci.subresourceRange.levelCount = 1; - ivci.subresourceRange.baseArrayLayer = 0; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - // Test for error message - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, optimal_error_codes[i]); - VkResult res = vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyFound(); - - if (!res) { - vkDestroyImageView(m_device->device(), imageView, nullptr); - } - } - - // Test for VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT. Needs special formats - - // Only run this test if format supported - if (!ImageFormatIsSupported(gpu(), VK_FORMAT_D24_UNORM_S8_UINT, VK_IMAGE_TILING_OPTIMAL)) { - printf("%s VK_FORMAT_D24_UNORM_S8_UINT format not supported - skipped.\n", kSkipPrefix); - return; - } - // Modify formats to have mismatched features - - // Format for image - fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT(gpu(), VK_FORMAT_D24_UNORM_S8_UINT, &formatProps); - formatProps.optimalTilingFeatures |= features[i]; - fpvkSetPhysicalDeviceFormatPropertiesEXT(gpu(), VK_FORMAT_D24_UNORM_S8_UINT, formatProps); - - memset(&formatProps, 0, sizeof(formatProps)); - - // Format for view - fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT(gpu(), VK_FORMAT_D32_SFLOAT_S8_UINT, &formatProps); - formatProps.optimalTilingFeatures = features[(i + 1) % feature_count]; - fpvkSetPhysicalDeviceFormatPropertiesEXT(gpu(), VK_FORMAT_D32_SFLOAT_S8_UINT, formatProps); - - // Create image with modified format - VkImageCreateInfo imgInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - nullptr, - VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, - VK_IMAGE_TYPE_2D, - VK_FORMAT_D24_UNORM_S8_UINT, - {1, 1, 1}, - 1, - 1, - VK_SAMPLE_COUNT_1_BIT, - VK_IMAGE_TILING_OPTIMAL, - usages[i], - VK_SHARING_MODE_EXCLUSIVE, - 0, - nullptr, - VK_IMAGE_LAYOUT_UNDEFINED}; - VkImageObj image(m_device); - image.init(&imgInfo); - ASSERT_TRUE(image.initialized()); - - VkImageView imageView; - - // Initialize VkImageViewCreateInfo with modified format - VkImageViewCreateInfo ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.image = image.handle(); - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.format = VK_FORMAT_D32_SFLOAT_S8_UINT; - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - ivci.subresourceRange.levelCount = 1; - ivci.subresourceRange.baseArrayLayer = 0; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; - - // Test for error message - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, optimal_error_codes[i]); - VkResult res = vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyFound(); - - if (!res) { - vkDestroyImageView(m_device->device(), imageView, nullptr); - } -} - -TEST_F(VkLayerTest, InvalidImageViewUsageCreateInfo) { - TEST_DESCRIPTION("Usage modification via a chained VkImageViewUsageCreateInfo struct"); - - if (!EnableDeviceProfileLayer()) { - printf("%s Test requires DeviceProfileLayer, unavailable - skipped.\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (!DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE2_EXTENSION_NAME)) { - printf("%s Test requires API >= 1.1 or KHR_MAINTENANCE2 extension, unavailable - skipped.\n", kSkipPrefix); - return; - } - m_device_extension_names.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME); - ASSERT_NO_FATAL_FAILURE(InitState()); - - PFN_vkSetPhysicalDeviceFormatPropertiesEXT fpvkSetPhysicalDeviceFormatPropertiesEXT = nullptr; - PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT = nullptr; - - // Load required functions - if (!LoadDeviceProfileLayer(fpvkSetPhysicalDeviceFormatPropertiesEXT, fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT)) { - printf("%s Required extensions are not avaiable.\n", kSkipPrefix); - return; - } - - VkFormatProperties formatProps; - - // Ensure image format claims support for sampled and storage, excludes color attachment - memset(&formatProps, 0, sizeof(formatProps)); - fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT(gpu(), VK_FORMAT_R32G32B32A32_UINT, &formatProps); - formatProps.optimalTilingFeatures |= (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT); - formatProps.optimalTilingFeatures = formatProps.optimalTilingFeatures & ~VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; - fpvkSetPhysicalDeviceFormatPropertiesEXT(gpu(), VK_FORMAT_R32G32B32A32_UINT, formatProps); - - // Create image with sampled and storage usages - VkImageCreateInfo imgInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - nullptr, - VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, - VK_IMAGE_TYPE_2D, - VK_FORMAT_R32G32B32A32_UINT, - {1, 1, 1}, - 1, - 1, - VK_SAMPLE_COUNT_1_BIT, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, - VK_SHARING_MODE_EXCLUSIVE, - 0, - nullptr, - VK_IMAGE_LAYOUT_UNDEFINED}; - VkImageObj image(m_device); - image.init(&imgInfo); - ASSERT_TRUE(image.initialized()); - - // Force the imageview format to exclude storage feature, include color attachment - memset(&formatProps, 0, sizeof(formatProps)); - fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT(gpu(), VK_FORMAT_R32G32B32A32_SINT, &formatProps); - formatProps.optimalTilingFeatures |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; - formatProps.optimalTilingFeatures = (formatProps.optimalTilingFeatures & ~VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT); - fpvkSetPhysicalDeviceFormatPropertiesEXT(gpu(), VK_FORMAT_R32G32B32A32_SINT, formatProps); - - VkImageViewCreateInfo ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.image = image.handle(); - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.format = VK_FORMAT_R32G32B32A32_SINT; - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - ivci.subresourceRange.levelCount = 1; - ivci.subresourceRange.baseArrayLayer = 0; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - // ImageView creation should fail because view format doesn't support all the underlying image's usages - VkImageView imageView; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-usage-02275"); - VkResult res = vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyFound(); - - // Add a chained VkImageViewUsageCreateInfo to override original image usage bits, removing storage - VkImageViewUsageCreateInfo usage_ci = {VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, nullptr, VK_IMAGE_USAGE_SAMPLED_BIT}; - // Link the VkImageViewUsageCreateInfo struct into the view's create info pNext chain - ivci.pNext = &usage_ci; - - // ImageView should now succeed without error - m_errorMonitor->ExpectSuccess(); - res = vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyNotFound(); - if (VK_SUCCESS == res) { - vkDestroyImageView(m_device->device(), imageView, nullptr); - } - - // Try a zero usage field - usage_ci.usage = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkCreateImageView: Chained VkImageViewUsageCreateInfo usage field must not be 0"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VkImageViewUsageCreateInfo: value of usage must not be 0"); - res = vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == res) { - vkDestroyImageView(m_device->device(), imageView, nullptr); - } - - // Try an illegal bit in usage field - usage_ci.usage = 0x10000000 | VK_IMAGE_USAGE_SAMPLED_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewUsageCreateInfo-usage-parameter"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "UNASSIGNED-GeneralParameterError-UnrecognizedValue"); - res = vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == res) { - vkDestroyImageView(m_device->device(), imageView, nullptr); - } -} - -TEST_F(VkLayerTest, ImageViewInUseDestroyedSignaled) { - TEST_DESCRIPTION("Delete in-use imageView."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}, - }); - - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - VkSampler sampler; - - VkResult err; - err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler); - ASSERT_VK_SUCCESS(err); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - - VkImageObj image(m_device); - image.Init(128, 128, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - VkImageView view; - VkImageViewCreateInfo ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.image = image.handle(); - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.format = VK_FORMAT_R8G8B8A8_UNORM; - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - ivci.subresourceRange.levelCount = 1; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - err = vkCreateImageView(m_device->device(), &ivci, NULL, &view); - ASSERT_VK_SUCCESS(err); - - VkDescriptorImageInfo image_info{}; - image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - image_info.imageView = view; - image_info.sampler = sampler; - - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_write.pImageInfo = &image_info; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - // Create PSO to use the sampler - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(set=0, binding=0) uniform sampler2D s;\n" - "layout(location=0) out vec4 x;\n" - "void main(){\n" - " x = texture(s, vec2(1));\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkDestroyImageView-imageView-01026"); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - // Bind pipeline to cmd buffer - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, &ds.set_, 0, - nullptr); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - - m_commandBuffer->Draw(1, 0, 0, 0); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - // Submit cmd buffer then destroy sampler - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - // Submit cmd buffer and then destroy imageView while in-flight - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - - vkDestroyImageView(m_device->device(), view, nullptr); - 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 ImageView obj"); - vkDestroyImageView(m_device->device(), view, NULL); - vkDestroySampler(m_device->device(), sampler, nullptr); -} - -TEST_F(VkLayerTest, BufferViewInUseDestroyedSignaled) { - TEST_DESCRIPTION("Delete in-use bufferView."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}, - }); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - - VkBuffer buffer; - uint32_t queue_family_index = 0; - VkBufferCreateInfo buffer_create_info = {}; - buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_create_info.size = 1024; - buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; - buffer_create_info.queueFamilyIndexCount = 1; - buffer_create_info.pQueueFamilyIndices = &queue_family_index; - - VkResult err = vkCreateBuffer(m_device->device(), &buffer_create_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - VkMemoryRequirements memory_reqs; - VkDeviceMemory buffer_memory; - - VkMemoryAllocateInfo memory_info = {}; - memory_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_info.allocationSize = 0; - memory_info.memoryTypeIndex = 0; - - vkGetBufferMemoryRequirements(m_device->device(), buffer, &memory_reqs); - memory_info.allocationSize = memory_reqs.size; - bool pass = m_device->phy().set_memory_type(memory_reqs.memoryTypeBits, &memory_info, 0); - ASSERT_TRUE(pass); - - err = vkAllocateMemory(m_device->device(), &memory_info, NULL, &buffer_memory); - ASSERT_VK_SUCCESS(err); - err = vkBindBufferMemory(m_device->device(), buffer, buffer_memory, 0); - ASSERT_VK_SUCCESS(err); - - VkBufferView view; - VkBufferViewCreateInfo bvci = {}; - bvci.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; - bvci.buffer = buffer; - bvci.format = VK_FORMAT_R32_SFLOAT; - bvci.range = VK_WHOLE_SIZE; - - err = vkCreateBufferView(m_device->device(), &bvci, NULL, &view); - ASSERT_VK_SUCCESS(err); - - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - descriptor_write.pTexelBufferView = &view; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(set=0, binding=0, r32f) uniform readonly imageBuffer s;\n" - "layout(location=0) out vec4 x;\n" - "void main(){\n" - " x = imageLoad(s, 0);\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkDestroyBufferView-bufferView-00936"); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - // Bind pipeline to cmd buffer - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, &ds.set_, 0, - nullptr); - m_commandBuffer->Draw(1, 0, 0, 0); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - // Submit cmd buffer and then destroy bufferView while in-flight - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - - vkDestroyBufferView(m_device->device(), view, nullptr); - 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 BufferView obj"); - vkDestroyBufferView(m_device->device(), view, NULL); - vkDestroyBuffer(m_device->device(), buffer, NULL); - vkFreeMemory(m_device->device(), buffer_memory, NULL); -} - -TEST_F(VkLayerTest, SamplerInUseDestroyedSignaled) { - TEST_DESCRIPTION("Delete in-use sampler."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}, - }); - - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - VkSampler sampler; - - VkResult err; - err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler); - ASSERT_VK_SUCCESS(err); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - - VkImageObj image(m_device); - image.Init(128, 128, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - VkImageView view; - VkImageViewCreateInfo ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.image = image.handle(); - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.format = VK_FORMAT_R8G8B8A8_UNORM; - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - ivci.subresourceRange.levelCount = 1; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - err = vkCreateImageView(m_device->device(), &ivci, NULL, &view); - ASSERT_VK_SUCCESS(err); - - VkDescriptorImageInfo image_info{}; - image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - image_info.imageView = view; - image_info.sampler = sampler; - - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_write.pImageInfo = &image_info; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - // Create PSO to use the sampler - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(set=0, binding=0) uniform sampler2D s;\n" - "layout(location=0) out vec4 x;\n" - "void main(){\n" - " x = texture(s, vec2(1));\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkDestroySampler-sampler-01082"); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - // Bind pipeline to cmd buffer - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, &ds.set_, 0, - nullptr); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - - m_commandBuffer->Draw(1, 0, 0, 0); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - // Submit cmd buffer then destroy sampler - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - // Submit cmd buffer and then destroy sampler while in-flight - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - - vkDestroySampler(m_device->device(), sampler, nullptr); // Destroyed too soon - m_errorMonitor->VerifyFound(); - 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); -} - -TEST_F(VkLayerTest, UpdateDestroyDescriptorSetLayout) { - TEST_DESCRIPTION("Attempt updates to descriptor sets with destroyed descriptor set layouts"); - // TODO: Update to match the descriptor set layout specific VUIDs/VALIDATION_ERROR_* when present - const auto kWriteDestroyedLayout = "VUID-VkWriteDescriptorSet-dstSet-00320"; - const auto kCopyDstDestroyedLayout = "VUID-VkCopyDescriptorSet-dstSet-parameter"; - const auto kCopySrcDestroyedLayout = "VUID-VkCopyDescriptorSet-srcSet-parameter"; - - ASSERT_NO_FATAL_FAILURE(Init()); - - // Set up the descriptor (resource) and write/copy operations to use. - float data[16] = {}; - VkConstantBufferObj buffer(m_device, sizeof(data), data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); - ASSERT_TRUE(buffer.initialized()); - - VkDescriptorBufferInfo info = {}; - info.buffer = buffer.handle(); - info.range = VK_WHOLE_SIZE; - - VkWriteDescriptorSet write_descriptor = {}; - write_descriptor.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write_descriptor.dstSet = VK_NULL_HANDLE; // must update this - write_descriptor.dstBinding = 0; - write_descriptor.descriptorCount = 1; - write_descriptor.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - write_descriptor.pBufferInfo = &info; - - VkCopyDescriptorSet copy_descriptor = {}; - copy_descriptor.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; - copy_descriptor.srcSet = VK_NULL_HANDLE; // must update - copy_descriptor.srcBinding = 0; - copy_descriptor.dstSet = VK_NULL_HANDLE; // must update - copy_descriptor.dstBinding = 0; - copy_descriptor.descriptorCount = 1; - - // Create valid and invalid source and destination descriptor sets - std::vector<VkDescriptorSetLayoutBinding> one_uniform_buffer = { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }; - OneOffDescriptorSet good_dst(m_device, one_uniform_buffer); - ASSERT_TRUE(good_dst.Initialized()); - - OneOffDescriptorSet bad_dst(m_device, one_uniform_buffer); - // Must assert before invalidating it below - ASSERT_TRUE(bad_dst.Initialized()); - bad_dst.layout_ = VkDescriptorSetLayoutObj(); - - OneOffDescriptorSet good_src(m_device, one_uniform_buffer); - ASSERT_TRUE(good_src.Initialized()); - - // Put valid data in the good and bad sources, simultaneously doing a positive test on write and copy operations - m_errorMonitor->ExpectSuccess(); - write_descriptor.dstSet = good_src.set_; - vkUpdateDescriptorSets(m_device->device(), 1, &write_descriptor, 0, NULL); - m_errorMonitor->VerifyNotFound(); - - OneOffDescriptorSet bad_src(m_device, one_uniform_buffer); - ASSERT_TRUE(bad_src.Initialized()); - - // to complete our positive testing use copy, where above we used write. - copy_descriptor.srcSet = good_src.set_; - copy_descriptor.dstSet = bad_src.set_; - vkUpdateDescriptorSets(m_device->device(), 0, nullptr, 1, ©_descriptor); - bad_src.layout_ = VkDescriptorSetLayoutObj(); - m_errorMonitor->VerifyNotFound(); - - // Trigger the three invalid use errors - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, kWriteDestroyedLayout); - write_descriptor.dstSet = bad_dst.set_; - vkUpdateDescriptorSets(m_device->device(), 1, &write_descriptor, 0, NULL); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, kCopyDstDestroyedLayout); - copy_descriptor.dstSet = bad_dst.set_; - vkUpdateDescriptorSets(m_device->device(), 0, nullptr, 1, ©_descriptor); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, kCopySrcDestroyedLayout); - copy_descriptor.srcSet = bad_src.set_; - copy_descriptor.dstSet = good_dst.set_; - vkUpdateDescriptorSets(m_device->device(), 0, nullptr, 1, ©_descriptor); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, QueueForwardProgressFenceWait) { - TEST_DESCRIPTION( - "Call VkQueueSubmit with a semaphore that is already signaled but not waited on by the queue. Wait on a fence that has not " - "yet been submitted to a queue."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const char *queue_forward_progress_message = " that was previously signaled by queue 0x"; - const char *invalid_fence_wait_message = " which has not been submitted on a Queue or during acquire next image."; - - VkCommandBufferObj cb1(m_device, m_commandPool); - cb1.begin(); - cb1.end(); - - VkSemaphoreCreateInfo semaphore_create_info = {}; - semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - VkSemaphore semaphore; - ASSERT_VK_SUCCESS(vkCreateSemaphore(m_device->device(), &semaphore_create_info, nullptr, &semaphore)); - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &cb1.handle(); - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &semaphore; - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - - m_commandBuffer->begin(); - m_commandBuffer->end(); - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, queue_forward_progress_message); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - - VkFenceCreateInfo fence_create_info = {}; - fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - VkFence fence; - ASSERT_VK_SUCCESS(vkCreateFence(m_device->device(), &fence_create_info, nullptr, &fence)); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, invalid_fence_wait_message); - vkWaitForFences(m_device->device(), 1, &fence, VK_TRUE, UINT64_MAX); - m_errorMonitor->VerifyFound(); - - vkDeviceWaitIdle(m_device->device()); - vkDestroyFence(m_device->device(), fence, nullptr); - vkDestroySemaphore(m_device->device(), semaphore, nullptr); -} - -TEST_F(VkLayerTest, FramebufferIncompatible) { - TEST_DESCRIPTION( - "Bind a secondary command buffer with a framebuffer that does not match the framebuffer for the active renderpass."); - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // A renderpass with one color attachment. - VkAttachmentDescription attachment = {0, - VK_FORMAT_B8G8R8A8_UNORM, - VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_STORE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - - VkAttachmentReference att_ref = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - - VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &att_ref, nullptr, nullptr, 0, nullptr}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &attachment, 1, &subpass, 0, nullptr}; - - VkRenderPass rp; - VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - - // A compatible framebuffer. - VkImageObj image(m_device); - image.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - VkImageViewCreateInfo ivci = { - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - nullptr, - 0, - image.handle(), - VK_IMAGE_VIEW_TYPE_2D, - VK_FORMAT_B8G8R8A8_UNORM, - {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, - VK_COMPONENT_SWIZZLE_IDENTITY}, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}, - }; - VkImageView view; - err = vkCreateImageView(m_device->device(), &ivci, nullptr, &view); - ASSERT_VK_SUCCESS(err); - - VkFramebufferCreateInfo fci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 1, &view, 32, 32, 1}; - VkFramebuffer fb; - err = vkCreateFramebuffer(m_device->device(), &fci, nullptr, &fb); - ASSERT_VK_SUCCESS(err); - - VkCommandBufferAllocateInfo cbai = {}; - cbai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - cbai.commandPool = m_commandPool->handle(); - cbai.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY; - cbai.commandBufferCount = 1; - - VkCommandBuffer sec_cb; - err = vkAllocateCommandBuffers(m_device->device(), &cbai, &sec_cb); - ASSERT_VK_SUCCESS(err); - VkCommandBufferBeginInfo cbbi = {}; - VkCommandBufferInheritanceInfo cbii = {}; - cbii.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; - cbii.renderPass = renderPass(); - cbii.framebuffer = fb; - cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - cbbi.pNext = NULL; - cbbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; - cbbi.pInheritanceInfo = &cbii; - vkBeginCommandBuffer(sec_cb, &cbbi); - vkEndCommandBuffer(sec_cb); - - VkCommandBufferBeginInfo cbbi2 = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, 0, nullptr}; - vkBeginCommandBuffer(m_commandBuffer->handle(), &cbbi2); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - " that is not the same as the primary command buffer's current active framebuffer "); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &sec_cb); - m_errorMonitor->VerifyFound(); - // Cleanup - - vkCmdEndRenderPass(m_commandBuffer->handle()); - vkEndCommandBuffer(m_commandBuffer->handle()); - - vkDestroyImageView(m_device->device(), view, NULL); - vkDestroyRenderPass(m_device->device(), rp, NULL); - vkDestroyFramebuffer(m_device->device(), fb, NULL); -} - -TEST_F(VkLayerTest, RenderPassMissingAttachment) { - TEST_DESCRIPTION("Begin render pass with missing framebuffer attachment"); - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Create a renderPass with a single color attachment - VkAttachmentReference attach = {}; - attach.layout = VK_IMAGE_LAYOUT_GENERAL; - VkSubpassDescription subpass = {}; - subpass.pColorAttachments = &attach; - VkRenderPassCreateInfo rpci = {}; - rpci.subpassCount = 1; - rpci.pSubpasses = &subpass; - rpci.attachmentCount = 1; - VkAttachmentDescription attach_desc = {}; - attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM; - attach_desc.samples = VK_SAMPLE_COUNT_1_BIT; - attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL; - rpci.pAttachments = &attach_desc; - rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - VkRenderPass rp; - VkResult err = vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - ASSERT_VK_SUCCESS(err); - - auto createView = lvl_init_struct<VkImageViewCreateInfo>(); - createView.image = m_renderTargets[0]->handle(); - createView.viewType = VK_IMAGE_VIEW_TYPE_2D; - createView.format = VK_FORMAT_B8G8R8A8_UNORM; - createView.components.r = VK_COMPONENT_SWIZZLE_R; - createView.components.g = VK_COMPONENT_SWIZZLE_G; - createView.components.b = VK_COMPONENT_SWIZZLE_B; - createView.components.a = VK_COMPONENT_SWIZZLE_A; - createView.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - createView.flags = 0; - - VkImageView iv; - vkCreateImageView(m_device->handle(), &createView, nullptr, &iv); - - auto fb_info = lvl_init_struct<VkFramebufferCreateInfo>(); - fb_info.renderPass = rp; - fb_info.attachmentCount = 1; - fb_info.pAttachments = &iv; - fb_info.width = 100; - fb_info.height = 100; - fb_info.layers = 1; - - // Create the framebuffer then destory the view it uses. - VkFramebuffer fb; - err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb); - vkDestroyImageView(device(), iv, NULL); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkRenderPassBeginInfo-framebuffer-parameter"); - - auto rpbi = lvl_init_struct<VkRenderPassBeginInfo>(); - rpbi.renderPass = rp; - rpbi.framebuffer = fb; - rpbi.renderArea = {{0, 0}, {32, 32}}; - - m_commandBuffer->begin(); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE); - // Don't call vkCmdEndRenderPass; as the begin has been "skipped" based on the error condition - m_errorMonitor->VerifyFound(); - m_commandBuffer->end(); - - vkDestroyFramebuffer(m_device->device(), fb, NULL); - vkDestroyRenderPass(m_device->device(), rp, NULL); -} - -TEST_F(VkLayerTest, ColorBlendInvalidLogicOp) { - TEST_DESCRIPTION("Attempt to use invalid VkPipelineColorBlendStateCreateInfo::logicOp value."); - - ASSERT_NO_FATAL_FAILURE(Init()); // enables all supported features - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - if (!m_device->phy().features().logicOp) { - printf("%s Device does not support logicOp feature; skipped.\n", kSkipPrefix); - return; - } - - const auto set_shading_enable = [](CreatePipelineHelper &helper) { - helper.cb_ci_.logicOpEnable = VK_TRUE; - helper.cb_ci_.logicOp = static_cast<VkLogicOp>(VK_LOGIC_OP_END_RANGE + 1); // invalid logicOp to be tested - }; - CreatePipelineHelper::OneshotTest(*this, set_shading_enable, VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineColorBlendStateCreateInfo-logicOpEnable-00607"); -} - -TEST_F(VkLayerTest, ColorBlendUnsupportedLogicOp) { - TEST_DESCRIPTION("Attempt enabling VkPipelineColorBlendStateCreateInfo::logicOpEnable when logicOp feature is disabled."); - - VkPhysicalDeviceFeatures features{}; - ASSERT_NO_FATAL_FAILURE(Init(&features)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const auto set_shading_enable = [](CreatePipelineHelper &helper) { helper.cb_ci_.logicOpEnable = VK_TRUE; }; - CreatePipelineHelper::OneshotTest(*this, set_shading_enable, VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineColorBlendStateCreateInfo-logicOpEnable-00606"); -} - -TEST_F(VkLayerTest, ColorBlendUnsupportedDualSourceBlend) { - TEST_DESCRIPTION("Attempt to use dual-source blending when dualSrcBlend feature is disabled."); - - VkPhysicalDeviceFeatures features{}; - ASSERT_NO_FATAL_FAILURE(Init(&features)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const auto set_dsb_src_color_enable = [](CreatePipelineHelper &helper) { - helper.cb_attachments_.blendEnable = VK_TRUE; - helper.cb_attachments_.srcColorBlendFactor = VK_BLEND_FACTOR_SRC1_COLOR; // bad! - helper.cb_attachments_.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; - helper.cb_attachments_.colorBlendOp = VK_BLEND_OP_ADD; - helper.cb_attachments_.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - helper.cb_attachments_.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - helper.cb_attachments_.alphaBlendOp = VK_BLEND_OP_ADD; - }; - CreatePipelineHelper::OneshotTest(*this, set_dsb_src_color_enable, VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineColorBlendAttachmentState-srcColorBlendFactor-00608"); - - const auto set_dsb_dst_color_enable = [](CreatePipelineHelper &helper) { - helper.cb_attachments_.blendEnable = VK_TRUE; - helper.cb_attachments_.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR; - helper.cb_attachments_.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR; // bad - helper.cb_attachments_.colorBlendOp = VK_BLEND_OP_ADD; - helper.cb_attachments_.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - helper.cb_attachments_.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - helper.cb_attachments_.alphaBlendOp = VK_BLEND_OP_ADD; - }; - CreatePipelineHelper::OneshotTest(*this, set_dsb_dst_color_enable, VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineColorBlendAttachmentState-dstColorBlendFactor-00609"); - - const auto set_dsb_src_alpha_enable = [](CreatePipelineHelper &helper) { - helper.cb_attachments_.blendEnable = VK_TRUE; - helper.cb_attachments_.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR; - helper.cb_attachments_.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; - helper.cb_attachments_.colorBlendOp = VK_BLEND_OP_ADD; - helper.cb_attachments_.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC1_ALPHA; // bad - helper.cb_attachments_.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - helper.cb_attachments_.alphaBlendOp = VK_BLEND_OP_ADD; - }; - CreatePipelineHelper::OneshotTest(*this, set_dsb_src_alpha_enable, VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineColorBlendAttachmentState-srcAlphaBlendFactor-00610"); - - const auto set_dsb_dst_alpha_enable = [](CreatePipelineHelper &helper) { - helper.cb_attachments_.blendEnable = VK_TRUE; - helper.cb_attachments_.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR; - helper.cb_attachments_.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; - helper.cb_attachments_.colorBlendOp = VK_BLEND_OP_ADD; - helper.cb_attachments_.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - helper.cb_attachments_.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA; // bad! - helper.cb_attachments_.alphaBlendOp = VK_BLEND_OP_ADD; - }; - CreatePipelineHelper::OneshotTest(*this, set_dsb_dst_alpha_enable, VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineColorBlendAttachmentState-dstAlphaBlendFactor-00611"); -} - -#if GTEST_IS_THREADSAFE -struct thread_data_struct { - VkCommandBuffer commandBuffer; - VkDevice device; - VkEvent event; - bool bailout; -}; - -extern "C" void *AddToCommandBuffer(void *arg) { - struct thread_data_struct *data = (struct thread_data_struct *)arg; - - for (int i = 0; i < 80000; i++) { - vkCmdSetEvent(data->commandBuffer, data->event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); - if (data->bailout) { - break; - } - } - return NULL; -} - -TEST_F(VkLayerTest, ThreadCommandBufferCollision) { - test_platform_thread thread; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "THREADING ERROR"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Calls AllocateCommandBuffers - VkCommandBufferObj commandBuffer(m_device, m_commandPool); - - commandBuffer.begin(); - - VkEventCreateInfo event_info; - VkEvent event; - VkResult err; - - memset(&event_info, 0, sizeof(event_info)); - event_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - - err = vkCreateEvent(device(), &event_info, NULL, &event); - ASSERT_VK_SUCCESS(err); - - err = vkResetEvent(device(), event); - ASSERT_VK_SUCCESS(err); - - struct thread_data_struct data; - data.commandBuffer = commandBuffer.handle(); - data.event = event; - data.bailout = false; - m_errorMonitor->SetBailout(&data.bailout); - - // First do some correct operations using multiple threads. - // Add many entries to command buffer from another thread. - test_platform_thread_create(&thread, AddToCommandBuffer, (void *)&data); - // Make non-conflicting calls from this thread at the same time. - for (int i = 0; i < 80000; i++) { - uint32_t count; - vkEnumeratePhysicalDevices(instance(), &count, NULL); - } - test_platform_thread_join(thread, NULL); - - // Then do some incorrect operations using multiple threads. - // Add many entries to command buffer from another thread. - test_platform_thread_create(&thread, AddToCommandBuffer, (void *)&data); - // Add many entries to command buffer from this thread at the same time. - AddToCommandBuffer(&data); - - test_platform_thread_join(thread, NULL); - commandBuffer.end(); - - m_errorMonitor->SetBailout(NULL); - - m_errorMonitor->VerifyFound(); - - vkDestroyEvent(device(), event, NULL); -} -#endif // GTEST_IS_THREADSAFE - -TEST_F(VkLayerTest, InvalidSPIRVCodeSize) { - TEST_DESCRIPTION("Test that errors are produced for a spirv modules with invalid code sizes"); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Invalid SPIR-V header"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkShaderModule module; - VkShaderModuleCreateInfo moduleCreateInfo; - struct icd_spv_header spv; - - spv.magic = ICD_SPV_MAGIC; - spv.version = ICD_SPV_VERSION; - spv.gen_magic = 0; - - moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - moduleCreateInfo.pNext = NULL; - moduleCreateInfo.pCode = (const uint32_t *)&spv; - moduleCreateInfo.codeSize = 4; - moduleCreateInfo.flags = 0; - vkCreateShaderModule(m_device->device(), &moduleCreateInfo, NULL, &module); - - m_errorMonitor->VerifyFound(); - - char const *vsSource = - "#version 450\n" - "\n" - "layout(location=0) out float x;\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - " x = 0;\n" - "}\n"; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkShaderModuleCreateInfo-pCode-01376"); - std::vector<unsigned int> shader; - VkShaderModuleCreateInfo module_create_info; - VkShaderModule shader_module; - module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - module_create_info.pNext = NULL; - this->GLSLtoSPV(VK_SHADER_STAGE_VERTEX_BIT, vsSource, shader); - module_create_info.pCode = shader.data(); - // Introduce failure by making codeSize a non-multiple of 4 - module_create_info.codeSize = shader.size() * sizeof(unsigned int) - 1; - module_create_info.flags = 0; - vkCreateShaderModule(m_device->handle(), &module_create_info, NULL, &shader_module); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, InvalidSPIRVMagic) { - TEST_DESCRIPTION("Test that an error is produced for a spirv module with a bad magic number"); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Invalid SPIR-V magic number"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkShaderModule module; - VkShaderModuleCreateInfo moduleCreateInfo; - struct icd_spv_header spv; - - spv.magic = (uint32_t)~ICD_SPV_MAGIC; - spv.version = ICD_SPV_VERSION; - spv.gen_magic = 0; - - moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - moduleCreateInfo.pNext = NULL; - moduleCreateInfo.pCode = (const uint32_t *)&spv; - moduleCreateInfo.codeSize = sizeof(spv) + 16; - moduleCreateInfo.flags = 0; - vkCreateShaderModule(m_device->device(), &moduleCreateInfo, NULL, &module); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineVertexOutputNotConsumed) { - TEST_DESCRIPTION("Test that a warning is produced for a vertex output that is not consumed by the fragment stage"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, "not consumed by fragment shader"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "\n" - "layout(location=0) out float x;\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - " x = 0;\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkPositiveLayerTest, CreatePipelineComplexTypes) { - TEST_DESCRIPTION("Smoke test for complex types across VS/FS boundary"); - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - if (!m_device->phy().features().tessellationShader) { - printf("%s Device does not support tessellation shaders; skipped.\n", kSkipPrefix); - return; - } - - m_errorMonitor->ExpectSuccess(); - - char const *vsSource = - "#version 450\n" - "void main() {}"; - char const *tcsSource = - "#version 450\n" - "layout(vertices=3) out;\n" - "struct S { int x; };\n" - "layout(location=2) patch out B { S s; } b;\n" - "void main() {\n" - " gl_TessLevelOuter[0] = gl_TessLevelOuter[1] = gl_TessLevelOuter[2] = 1;\n" - " gl_TessLevelInner[0] = 1;\n" - " b.s.x = 1;\n" - "}\n"; - - char const *tesSource = - "#version 450\n" - "layout(triangles, equal_spacing, cw) in;\n" - "struct S { int x; };\n" - "layout(location=2) patch in B { S s; } b;\n" - "void main() { gl_Position = vec4(b.s.x); }\n"; - - char const *fsSource = - "#version 450\n" - "layout(location=0) out vec4 c;\n" - "void main() { c = vec4(1); }\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj tcs(m_device, tcsSource, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, this); - VkShaderObj tes(m_device, tesSource, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineInputAssemblyStateCreateInfo iasci{VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, nullptr, 0, - VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, VK_FALSE}; - - VkPipelineTessellationStateCreateInfo tsci{VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, nullptr, 0, 3}; - - VkPipelineObj pipe(m_device); - - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&tcs); - pipe.AddShader(&tes); - pipe.AddShader(&fs); - pipe.SetInputAssembly(&iasci); - pipe.SetTessellation(&tsci); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkLayerTest, CreatePipelineCheckShaderBadSpecialization) { - TEST_DESCRIPTION("Challenge core_validation with shader validation issues related to vkCreateGraphicsPipelines."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const char *bad_specialization_message = - "Specialization entry 0 (for constant id 0) references memory outside provided specialization data "; - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - - char const *fsSource = - "#version 450\n" - "\n" - "layout (constant_id = 0) const float r = 0.0f;\n" - "layout(location = 0) out vec4 uFragColor;\n" - "void main(){\n" - " uFragColor = vec4(r,1,0,1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - const VkPipelineLayoutObj pipeline_layout(m_device); - - VkPipelineViewportStateCreateInfo vp_state_create_info = {}; - vp_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - vp_state_create_info.viewportCount = 1; - VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; - vp_state_create_info.pViewports = &viewport; - vp_state_create_info.scissorCount = 1; - - VkDynamicState scissor_state = VK_DYNAMIC_STATE_SCISSOR; - - VkPipelineDynamicStateCreateInfo pipeline_dynamic_state_create_info = {}; - pipeline_dynamic_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - pipeline_dynamic_state_create_info.dynamicStateCount = 1; - pipeline_dynamic_state_create_info.pDynamicStates = &scissor_state; - - VkPipelineShaderStageCreateInfo shader_stage_create_info[2] = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; - - VkPipelineVertexInputStateCreateInfo vertex_input_create_info = {}; - vertex_input_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - - VkPipelineInputAssemblyStateCreateInfo input_assembly_create_info = {}; - input_assembly_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - input_assembly_create_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; - - VkPipelineRasterizationStateCreateInfo rasterization_state_create_info = {}; - rasterization_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterization_state_create_info.pNext = nullptr; - rasterization_state_create_info.lineWidth = 1.0f; - rasterization_state_create_info.rasterizerDiscardEnable = true; - - VkPipelineColorBlendAttachmentState color_blend_attachment_state = {}; - color_blend_attachment_state.blendEnable = VK_FALSE; - color_blend_attachment_state.colorWriteMask = 0xf; - - VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = {}; - color_blend_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - color_blend_state_create_info.attachmentCount = 1; - color_blend_state_create_info.pAttachments = &color_blend_attachment_state; - - VkGraphicsPipelineCreateInfo graphicspipe_create_info = {}; - graphicspipe_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - graphicspipe_create_info.stageCount = 2; - graphicspipe_create_info.pStages = shader_stage_create_info; - graphicspipe_create_info.pVertexInputState = &vertex_input_create_info; - graphicspipe_create_info.pInputAssemblyState = &input_assembly_create_info; - graphicspipe_create_info.pViewportState = &vp_state_create_info; - graphicspipe_create_info.pRasterizationState = &rasterization_state_create_info; - graphicspipe_create_info.pColorBlendState = &color_blend_state_create_info; - graphicspipe_create_info.pDynamicState = &pipeline_dynamic_state_create_info; - graphicspipe_create_info.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; - graphicspipe_create_info.layout = pipeline_layout.handle(); - graphicspipe_create_info.renderPass = renderPass(); - - VkPipelineCacheCreateInfo pipeline_cache_create_info = {}; - pipeline_cache_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - - VkPipelineCache pipelineCache; - ASSERT_VK_SUCCESS(vkCreatePipelineCache(m_device->device(), &pipeline_cache_create_info, nullptr, &pipelineCache)); - - // This structure maps constant ids to data locations. - const VkSpecializationMapEntry entry = - // id, offset, size - {0, 4, sizeof(uint32_t)}; // Challenge core validation by using a bogus offset. - - uint32_t data = 1; - - // Set up the info describing spec map and data - const VkSpecializationInfo specialization_info = { - 1, - &entry, - 1 * sizeof(float), - &data, - }; - shader_stage_create_info[0].pSpecializationInfo = &specialization_info; - - VkPipeline pipeline; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, bad_specialization_message); - vkCreateGraphicsPipelines(m_device->device(), pipelineCache, 1, &graphicspipe_create_info, nullptr, &pipeline); - m_errorMonitor->VerifyFound(); - - vkDestroyPipelineCache(m_device->device(), pipelineCache, nullptr); -} - -TEST_F(VkLayerTest, CreatePipelineCheckShaderDescriptorTypeMismatch) { - TEST_DESCRIPTION("Challenge core_validation with shader validation issues related to vkCreateGraphicsPipelines."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const char *descriptor_type_mismatch_message = "Type mismatch on descriptor slot 0.0 "; - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - char const *vsSource = - "#version 450\n" - "\n" - "layout (std140, set = 0, binding = 0) uniform buf {\n" - " mat4 mvp;\n" - "} ubuf;\n" - "void main(){\n" - " gl_Position = ubuf.mvp * vec4(1);\n" - "}\n"; - - char const *fsSource = - "#version 450\n" - "\n" - "layout(location = 0) out vec4 uFragColor;\n" - "void main(){\n" - " uFragColor = vec4(0,1,0,1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, descriptor_type_mismatch_message); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineCheckShaderDescriptorNotAccessible) { - TEST_DESCRIPTION( - "Create a pipeline in which a descriptor used by a shader stage does not include that stage in its stageFlags."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const char *descriptor_not_accessible_message = "Shader uses descriptor slot 0.0 "; - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT /*!*/, nullptr}, - }); - - char const *vsSource = - "#version 450\n" - "\n" - "layout (std140, set = 0, binding = 0) uniform buf {\n" - " mat4 mvp;\n" - "} ubuf;\n" - "void main(){\n" - " gl_Position = ubuf.mvp * vec4(1);\n" - "}\n"; - - char const *fsSource = - "#version 450\n" - "\n" - "layout(location = 0) out vec4 uFragColor;\n" - "void main(){\n" - " uFragColor = vec4(0,1,0,1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, descriptor_not_accessible_message); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineCheckShaderPushConstantNotAccessible) { - TEST_DESCRIPTION( - "Create a graphics pipeline in which a push constant range containing a push constant block member is not accessible from " - "the current shader stage."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const char *push_constant_not_accessible_message = - "Push constant range covering variable starting at offset 0 not accessible from stage VK_SHADER_STAGE_VERTEX_BIT"; - - char const *vsSource = - "#version 450\n" - "\n" - "layout(push_constant, std430) uniform foo { float x; } consts;\n" - "void main(){\n" - " gl_Position = vec4(consts.x);\n" - "}\n"; - - char const *fsSource = - "#version 450\n" - "\n" - "layout(location = 0) out vec4 uFragColor;\n" - "void main(){\n" - " uFragColor = vec4(0,1,0,1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - // Set up a push constant range - VkPushConstantRange push_constant_range = {}; - // Set to the wrong stage to challenge core_validation - push_constant_range.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - push_constant_range.size = 4; - - const VkPipelineLayoutObj pipeline_layout(m_device, {}, {push_constant_range}); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, push_constant_not_accessible_message); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineCheckShaderNotEnabled) { - TEST_DESCRIPTION( - "Create a graphics pipeline in which a capability declared by the shader requires a feature not enabled on the device."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const char *feature_not_enabled_message = - "Shader requires VkPhysicalDeviceFeatures::shaderFloat64 but is not enabled on the device"; - - // Some awkward steps are required to test with custom device features. - std::vector<const char *> device_extension_names; - auto features = m_device->phy().features(); - // Disable support for 64 bit floats - features.shaderFloat64 = false; - // The sacrificial device object - VkDeviceObj test_device(0, gpu(), device_extension_names, &features); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " dvec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n" - " color = vec4(green);\n" - "}\n"; - - VkShaderObj vs(&test_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(&test_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkRenderpassObj render_pass(&test_device); - - VkPipelineObj pipe(&test_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - const VkPipelineLayoutObj pipeline_layout(&test_device); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, feature_not_enabled_message); - pipe.CreateVKPipeline(pipeline_layout.handle(), render_pass.handle()); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreateShaderModuleCheckBadCapability) { - TEST_DESCRIPTION("Create a shader in which a capability declared by the shader is not supported."); - // Note that this failure message comes from spirv-tools, specifically the validator. - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const std::string spv_source = R"( - OpCapability ImageRect - OpEntryPoint Vertex %main "main" - %main = OpFunction %void None %3 - OpReturn - OpFunctionEnd - )"; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Capability ImageRect is not allowed by Vulkan"); - - std::vector<unsigned int> spv; - VkShaderModuleCreateInfo module_create_info; - VkShaderModule shader_module; - module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - module_create_info.pNext = NULL; - ASMtoSPV(SPV_ENV_VULKAN_1_0, 0, spv_source.data(), spv); - module_create_info.pCode = spv.data(); - module_create_info.codeSize = spv.size() * sizeof(unsigned int); - module_create_info.flags = 0; - - VkResult err = vkCreateShaderModule(m_device->handle(), &module_create_info, NULL, &shader_module); - m_errorMonitor->VerifyFound(); - if (err == VK_SUCCESS) { - vkDestroyShaderModule(m_device->handle(), shader_module, NULL); - } -} - -TEST_F(VkPositiveLayerTest, ShaderRelaxedBlockLayout) { - // This is a positive test, no errors expected - // Verifies the ability to relax block layout rules with a shader that requires them to be relaxed - TEST_DESCRIPTION("Create a shader that requires relaxed block layout."); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - // The Relaxed Block Layout extension was promoted to core in 1.1. - // Go ahead and check for it and turn it on in case a 1.0 device has it. - if (!DeviceExtensionSupported(gpu(), nullptr, VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME)) { - printf("%s Extension %s not supported, skipping this pass. \n", kSkipPrefix, VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME); - return; - } - m_device_extension_names.push_back(VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME); - ASSERT_NO_FATAL_FAILURE(InitState()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Vertex shader requiring relaxed layout. - // Without relaxed layout, we would expect a message like: - // "Structure id 2 decorated as Block for variable in Uniform storage class - // must follow standard uniform buffer layout rules: member 1 at offset 4 is not aligned to 16" - - const std::string spv_source = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 4 - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %S = OpTypeStruct %float %v3float -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::vector<unsigned int> spv; - VkShaderModuleCreateInfo module_create_info; - VkShaderModule shader_module; - module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - module_create_info.pNext = NULL; - ASMtoSPV(SPV_ENV_VULKAN_1_0, 0, spv_source.data(), spv); - module_create_info.pCode = spv.data(); - module_create_info.codeSize = spv.size() * sizeof(unsigned int); - module_create_info.flags = 0; - - m_errorMonitor->ExpectSuccess(); - VkResult err = vkCreateShaderModule(m_device->handle(), &module_create_info, NULL, &shader_module); - m_errorMonitor->VerifyNotFound(); - if (err == VK_SUCCESS) { - vkDestroyShaderModule(m_device->handle(), shader_module, NULL); - } -} - -TEST_F(VkPositiveLayerTest, ShaderScalarBlockLayout) { - // This is a positive test, no errors expected - // Verifies the ability to scalar block layout rules with a shader that requires them to be relaxed - TEST_DESCRIPTION("Create a shader that requires scalar block layout."); - // Enable req'd extensions - if (!InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - printf("%s Extension %s not supported, skipping this pass. \n", kSkipPrefix, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - return; - } - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - // Check for the Scalar Block Layout extension and turn it on if it's available - if (!DeviceExtensionSupported(gpu(), nullptr, VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME)) { - printf("%s Extension %s not supported, skipping this pass. \n", kSkipPrefix, VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME); - return; - } - m_device_extension_names.push_back(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME); - - PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2 = - (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR"); - - auto scalar_block_features = lvl_init_struct<VkPhysicalDeviceScalarBlockLayoutFeaturesEXT>(NULL); - scalar_block_features.scalarBlockLayout = VK_TRUE; - auto query_features2 = lvl_init_struct<VkPhysicalDeviceFeatures2>(&scalar_block_features); - vkGetPhysicalDeviceFeatures2(gpu(), &query_features2); - - auto set_features2 = lvl_init_struct<VkPhysicalDeviceFeatures2>(&scalar_block_features); - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &set_features2)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Vertex shader requiring scalar layout. - // Without scalar layout, we would expect a message like: - // "Structure id 2 decorated as Block for variable in Uniform storage class - // must follow standard uniform buffer layout rules: member 1 at offset 4 is not aligned to 16" - - const std::string spv_source = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" - OpSource GLSL 450 - OpMemberDecorate %S 0 Offset 0 - OpMemberDecorate %S 1 Offset 4 - OpMemberDecorate %S 2 Offset 8 - OpDecorate %S Block - OpDecorate %B DescriptorSet 0 - OpDecorate %B Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %S = OpTypeStruct %float %float %v3float -%_ptr_Uniform_S = OpTypePointer Uniform %S - %B = OpVariable %_ptr_Uniform_S Uniform - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd - )"; - - std::vector<unsigned int> spv; - VkShaderModuleCreateInfo module_create_info; - VkShaderModule shader_module; - module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - module_create_info.pNext = NULL; - ASMtoSPV(SPV_ENV_VULKAN_1_0, 0, spv_source.data(), spv); - module_create_info.pCode = spv.data(); - module_create_info.codeSize = spv.size() * sizeof(unsigned int); - module_create_info.flags = 0; - - m_errorMonitor->ExpectSuccess(); - VkResult err = vkCreateShaderModule(m_device->handle(), &module_create_info, NULL, &shader_module); - m_errorMonitor->VerifyNotFound(); - if (err == VK_SUCCESS) { - vkDestroyShaderModule(m_device->handle(), shader_module, NULL); - } -} - -TEST_F(VkPositiveLayerTest, SpirvGroupDecorations) { - TEST_DESCRIPTION("Test shader validation support for group decorations."); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - ASSERT_NO_FATAL_FAILURE(InitState()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const std::string spv_source = R"( - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID - OpExecutionMode %main LocalSize 1 1 1 - OpSource GLSL 430 - OpName %main "main" - OpName %gl_GlobalInvocationID "gl_GlobalInvocationID" - OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId - OpDecorate %_runtimearr_float ArrayStride 4 - OpDecorate %4 BufferBlock - OpDecorate %5 Offset 0 - %4 = OpDecorationGroup - %5 = OpDecorationGroup - OpGroupDecorate %4 %_struct_6 %_struct_7 %_struct_8 %_struct_9 %_struct_10 %_struct_11 - OpGroupMemberDecorate %5 %_struct_6 0 %_struct_7 0 %_struct_8 0 %_struct_9 0 %_struct_10 0 %_struct_11 0 - OpDecorate %12 DescriptorSet 0 - OpDecorate %13 DescriptorSet 0 - OpDecorate %13 NonWritable - OpDecorate %13 Restrict - %14 = OpDecorationGroup - %12 = OpDecorationGroup - %13 = OpDecorationGroup - OpGroupDecorate %12 %15 - OpGroupDecorate %12 %15 - OpGroupDecorate %12 %15 - OpDecorate %15 DescriptorSet 0 - OpDecorate %15 Binding 5 - OpGroupDecorate %14 %16 - OpDecorate %16 DescriptorSet 0 - OpDecorate %16 Binding 0 - OpGroupDecorate %12 %17 - OpDecorate %17 Binding 1 - OpGroupDecorate %13 %18 %19 - OpDecorate %18 Binding 2 - OpDecorate %19 Binding 3 - OpGroupDecorate %14 %20 - OpGroupDecorate %12 %20 - OpGroupDecorate %13 %20 - OpDecorate %20 Binding 4 - %bool = OpTypeBool - %void = OpTypeVoid - %23 = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %int = OpTypeInt 32 1 - %float = OpTypeFloat 32 - %v3uint = OpTypeVector %uint 3 - %v3float = OpTypeVector %float 3 -%_ptr_Input_v3uint = OpTypePointer Input %v3uint -%_ptr_Uniform_int = OpTypePointer Uniform %int -%_ptr_Uniform_float = OpTypePointer Uniform %float -%_runtimearr_int = OpTypeRuntimeArray %int -%_runtimearr_float = OpTypeRuntimeArray %float -%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input - %int_0 = OpConstant %int 0 - %_struct_6 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6 - %15 = OpVariable %_ptr_Uniform__struct_6 Uniform - %_struct_7 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7 - %16 = OpVariable %_ptr_Uniform__struct_7 Uniform - %_struct_8 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_8 = OpTypePointer Uniform %_struct_8 - %17 = OpVariable %_ptr_Uniform__struct_8 Uniform - %_struct_9 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_9 = OpTypePointer Uniform %_struct_9 - %18 = OpVariable %_ptr_Uniform__struct_9 Uniform - %_struct_10 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_10 = OpTypePointer Uniform %_struct_10 - %19 = OpVariable %_ptr_Uniform__struct_10 Uniform - %_struct_11 = OpTypeStruct %_runtimearr_float -%_ptr_Uniform__struct_11 = OpTypePointer Uniform %_struct_11 - %20 = OpVariable %_ptr_Uniform__struct_11 Uniform - %main = OpFunction %void None %23 - %40 = OpLabel - %41 = OpLoad %v3uint %gl_GlobalInvocationID - %42 = OpCompositeExtract %uint %41 0 - %43 = OpAccessChain %_ptr_Uniform_float %16 %int_0 %42 - %44 = OpAccessChain %_ptr_Uniform_float %17 %int_0 %42 - %45 = OpAccessChain %_ptr_Uniform_float %18 %int_0 %42 - %46 = OpAccessChain %_ptr_Uniform_float %19 %int_0 %42 - %47 = OpAccessChain %_ptr_Uniform_float %20 %int_0 %42 - %48 = OpAccessChain %_ptr_Uniform_float %15 %int_0 %42 - %49 = OpLoad %float %43 - %50 = OpLoad %float %44 - %51 = OpLoad %float %45 - %52 = OpLoad %float %46 - %53 = OpLoad %float %47 - %54 = OpFAdd %float %49 %50 - %55 = OpFAdd %float %54 %51 - %56 = OpFAdd %float %55 %52 - %57 = OpFAdd %float %56 %53 - OpStore %48 %57 - OpReturn - OpFunctionEnd -)"; - - // CreateDescriptorSetLayout - VkDescriptorSetLayoutBinding dslb[6] = {}; - for (auto i = 0; i < 6; i++) { - dslb[i].binding = i; - dslb[i].descriptorCount = 1; - dslb[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - dslb[i].pImmutableSamplers = NULL; - dslb[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_ALL; - } - - VkDescriptorSetLayoutCreateInfo ds_layout_ci = {}; - ds_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - ds_layout_ci.flags = 0; - ds_layout_ci.bindingCount = 6; - ds_layout_ci.pBindings = dslb; - - if (m_device->props.limits.maxPerStageDescriptorStorageBuffers < ds_layout_ci.bindingCount) { - printf("%sNeeded storage buffer bindings exceeds this devices limit. Skipping tests.\n", kSkipPrefix); - return; - } - - VkDescriptorSetLayout ds_layout = {}; - vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - - // CreatePipelineLayout - VkPipelineLayoutCreateInfo pipeline_layout_ci = {}; - pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_ci.pNext = NULL; - pipeline_layout_ci.flags = 0; - pipeline_layout_ci.setLayoutCount = 1; - pipeline_layout_ci.pSetLayouts = &ds_layout; - VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; - vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - - // Create DescriptorPool - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - ds_type_count.descriptorCount = 6; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool = VK_NULL_HANDLE; - vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - - // AllocateDescriptorSets - VkDescriptorSetAllocateInfo ds_alloc_info = {}; - ds_alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - ds_alloc_info.descriptorSetCount = 1; - ds_alloc_info.descriptorPool = ds_pool; - ds_alloc_info.pSetLayouts = &ds_layout; - - VkDescriptorSet descriptorSet; - vkAllocateDescriptorSets(m_device->device(), &ds_alloc_info, &descriptorSet); - - // CreateShaderModule - std::vector<unsigned int> spv; - VkShaderModuleCreateInfo module_create_info; - VkShaderModule shader_module; - module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - module_create_info.pNext = NULL; - ASMtoSPV(SPV_ENV_VULKAN_1_0, 0, spv_source.data(), spv); - module_create_info.pCode = spv.data(); - module_create_info.codeSize = spv.size() * sizeof(unsigned int); - module_create_info.flags = 0; - vkCreateShaderModule(m_device->handle(), &module_create_info, NULL, &shader_module); - - // CreateComputePipelines - VkComputePipelineCreateInfo pipeline_info = {}; - pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; - pipeline_info.pNext = nullptr; - pipeline_info.flags = 0; - pipeline_info.layout = pipeline_layout; - pipeline_info.basePipelineHandle = VK_NULL_HANDLE; - pipeline_info.basePipelineIndex = -1; - pipeline_info.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - pipeline_info.stage.pNext = nullptr; - pipeline_info.stage.flags = 0; - pipeline_info.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; - pipeline_info.stage.module = shader_module; - pipeline_info.stage.pName = "main"; - pipeline_info.stage.pSpecializationInfo = nullptr; - VkPipeline cs_pipeline; - - m_errorMonitor->ExpectSuccess(); - vkCreateComputePipelines(device(), VK_NULL_HANDLE, 1, &pipeline_info, nullptr, &cs_pipeline); - m_errorMonitor->VerifyNotFound(); - - vkDestroyPipeline(device(), cs_pipeline, nullptr); - vkDestroyShaderModule(device(), shader_module, nullptr); - vkDestroyDescriptorPool(device(), ds_pool, nullptr); - vkDestroyPipelineLayout(device(), pipeline_layout, nullptr); - vkDestroyDescriptorSetLayout(device(), ds_layout, nullptr); -} - -TEST_F(VkPositiveLayerTest, CreatePipelineCheckShaderCapabilityExtension1of2) { - // This is a positive test, no errors expected - // Verifies the ability to deal with a shader that declares a non-unique SPIRV capability ID - TEST_DESCRIPTION("Create a shader in which uses a non-unique capability ID extension, 1 of 2"); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (!DeviceExtensionSupported(gpu(), nullptr, VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME)) { - printf("%s Extension %s not supported, skipping this pass. \n", kSkipPrefix, - VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME); - return; - } - m_device_extension_names.push_back(VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME); - ASSERT_NO_FATAL_FAILURE(InitState()); - - // These tests require that the device support multiViewport - if (!m_device->phy().features().multiViewport) { - printf("%s Device does not support multiViewport, test skipped.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Vertex shader using viewport array capability - char const *vsSource = - "#version 450\n" - "#extension GL_ARB_shader_viewport_layer_array : enable\n" - "void main() {\n" - " gl_ViewportIndex = 1;\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - - const VkPipelineLayoutObj pipe_layout(m_device, {}); - - m_errorMonitor->ExpectSuccess(); - pipe.CreateVKPipeline(pipe_layout.handle(), renderPass()); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, CreatePipelineCheckShaderCapabilityExtension2of2) { - // This is a positive test, no errors expected - // Verifies the ability to deal with a shader that declares a non-unique SPIRV capability ID - TEST_DESCRIPTION("Create a shader in which uses a non-unique capability ID extension, 2 of 2"); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (!DeviceExtensionSupported(gpu(), nullptr, VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME)) { - printf("%s Extension %s not supported, skipping this pass. \n", kSkipPrefix, VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME); - return; - } - m_device_extension_names.push_back(VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME); - ASSERT_NO_FATAL_FAILURE(InitState()); - - // These tests require that the device support multiViewport - if (!m_device->phy().features().multiViewport) { - printf("%s Device does not support multiViewport, test skipped.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Vertex shader using viewport array capability - char const *vsSource = - "#version 450\n" - "#extension GL_ARB_shader_viewport_layer_array : enable\n" - "void main() {\n" - " gl_ViewportIndex = 1;\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - - const VkPipelineLayoutObj pipe_layout(m_device, {}); - - m_errorMonitor->ExpectSuccess(); - pipe.CreateVKPipeline(pipe_layout.handle(), renderPass()); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkLayerTest, CreatePipelineFragmentInputNotProvided) { - TEST_DESCRIPTION( - "Test that an error is produced for a fragment shader input which is not present in the outputs of the previous stage"); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "not written by vertex shader"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) in float x;\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(x);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineFragmentInputNotProvidedInBlock) { - TEST_DESCRIPTION( - "Test that an error is produced for a fragment shader input within an interace block, which is not present in the outputs " - "of the previous stage."); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "not written by vertex shader"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "in block { layout(location=0) float x; } ins;\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(ins.x);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineVsFsTypeMismatchArraySize) { - TEST_DESCRIPTION("Test that an error is produced for mismatched array sizes across the vertex->fragment shader interface"); - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Type mismatch on location 0.0: 'ptr to output arr[2] of float32' vs 'ptr to input arr[1] of float32'"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "\n" - "layout(location=0) out float x[2];\n" - "void main(){\n" - " x[0] = 0; x[1] = 0;\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) in float x[1];\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(x[0]);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineVsFsTypeMismatch) { - TEST_DESCRIPTION("Test that an error is produced for mismatched types across the vertex->fragment shader interface"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Type mismatch on location 0"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "\n" - "layout(location=0) out int x;\n" - "void main(){\n" - " x = 0;\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) in float x;\n" /* VS writes int */ - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(x);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineVsFsTypeMismatchInBlock) { - TEST_DESCRIPTION( - "Test that an error is produced for mismatched types across the vertex->fragment shader interface, when the variable is " - "contained within an interface block"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Type mismatch on location 0"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "\n" - "out block { layout(location=0) int x; } outs;\n" - "void main(){\n" - " outs.x = 0;\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "in block { layout(location=0) float x; } ins;\n" /* VS writes int */ - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(ins.x);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineVsFsMismatchByLocation) { - TEST_DESCRIPTION( - "Test that an error is produced for location mismatches across the vertex->fragment shader interface; This should manifest " - "as a not-written/not-consumed pair, but flushes out broken walking of the interfaces"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "location 0.0 which is not written by vertex shader"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "\n" - "out block { layout(location=1) float x; } outs;\n" - "void main(){\n" - " outs.x = 0;\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "in block { layout(location=0) float x; } ins;\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(ins.x);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineVsFsMismatchByComponent) { - TEST_DESCRIPTION( - "Test that an error is produced for component mismatches across the vertex->fragment shader interface. It's not enough to " - "have the same set of locations in use; matching is defined in terms of spirv variables."); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "location 0.1 which is not written by vertex shader"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "\n" - "out block { layout(location=0, component=0) float x; } outs;\n" - "void main(){\n" - " outs.x = 0;\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "in block { layout(location=0, component=1) float x; } ins;\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(ins.x);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineVsFsMismatchByPrecision) { - TEST_DESCRIPTION("Test that the RelaxedPrecision decoration is validated to match"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "layout(location=0) out mediump float x;\n" - "void main() { gl_Position = vec4(0); x = 1.0; }\n"; - char const *fsSource = - "#version 450\n" - "layout(location=0) in highp float x;\n" - "layout(location=0) out vec4 color;\n" - "void main() { color = vec4(x); }\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "differ in precision"); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineVsFsMismatchByPrecisionBlock) { - TEST_DESCRIPTION("Test that the RelaxedPrecision decoration is validated to match"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "out block { layout(location=0) mediump float x; };\n" - "void main() { gl_Position = vec4(0); x = 1.0; }\n"; - char const *fsSource = - "#version 450\n" - "in block { layout(location=0) highp float x; };\n" - "layout(location=0) out vec4 color;\n" - "void main() { color = vec4(x); }\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "differ in precision"); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineAttribNotConsumed) { - TEST_DESCRIPTION("Test that a warning is produced for a vertex attribute which is not consumed by the vertex shader"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, "location 0 not consumed by vertex shader"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkVertexInputBindingDescription input_binding; - memset(&input_binding, 0, sizeof(input_binding)); - - VkVertexInputAttributeDescription input_attrib; - memset(&input_attrib, 0, sizeof(input_attrib)); - input_attrib.format = VK_FORMAT_R32_SFLOAT; - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - pipe.AddVertexInputBindings(&input_binding, 1); - pipe.AddVertexInputAttribs(&input_attrib, 1); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineAttribLocationMismatch) { - TEST_DESCRIPTION( - "Test that a warning is produced for a location mismatch on vertex attributes. This flushes out bad behavior in the " - "interface walker"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, "location 0 not consumed by vertex shader"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkVertexInputBindingDescription input_binding; - memset(&input_binding, 0, sizeof(input_binding)); - - VkVertexInputAttributeDescription input_attrib; - memset(&input_attrib, 0, sizeof(input_attrib)); - input_attrib.format = VK_FORMAT_R32_SFLOAT; - - char const *vsSource = - "#version 450\n" - "\n" - "layout(location=1) in float x;\n" - "void main(){\n" - " gl_Position = vec4(x);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - pipe.AddVertexInputBindings(&input_binding, 1); - pipe.AddVertexInputAttribs(&input_attrib, 1); - - VkDescriptorSetObj descriptorSet(m_device); - 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(); -} - -TEST_F(VkLayerTest, CreatePipelineAttribNotProvided) { - TEST_DESCRIPTION("Test that an error is produced for a vertex shader input which is not provided by a vertex attribute"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Vertex shader consumes input at location 0 but not provided"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "\n" - "layout(location=0) in vec4 x;\n" /* not provided */ - "void main(){\n" - " gl_Position = x;\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineAttribTypeMismatch) { - TEST_DESCRIPTION( - "Test that an error is produced for a mismatch between the fundamental type (float/int/uint) of an attribute and the " - "vertex shader input that consumes it"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "location 0 does not match vertex shader input type"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkVertexInputBindingDescription input_binding; - memset(&input_binding, 0, sizeof(input_binding)); - - VkVertexInputAttributeDescription input_attrib; - memset(&input_attrib, 0, sizeof(input_attrib)); - input_attrib.format = VK_FORMAT_R32_SFLOAT; - - char const *vsSource = - "#version 450\n" - "\n" - "layout(location=0) in int x;\n" /* attrib provided float */ - "void main(){\n" - " gl_Position = vec4(x);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - pipe.AddVertexInputBindings(&input_binding, 1); - pipe.AddVertexInputAttribs(&input_attrib, 1); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineDuplicateStage) { - TEST_DESCRIPTION("Test that an error is produced for a pipeline containing multiple shaders for the same stage"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Multiple shaders provided for stage VK_SHADER_STAGE_VERTEX_BIT"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&vs); // intentionally duplicate vertex shader attachment - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineMissingEntrypoint) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "No entrypoint found named `foo`"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "void main(){\n" - " gl_Position = vec4(0);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this, "foo"); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineDepthStencilRequired) { - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "pDepthStencilState is NULL when rasterization is enabled and subpass uses a depth/stencil attachment"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "void main(){ gl_Position = vec4(0); }\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - VkAttachmentDescription attachments[] = { - { - 0, - VK_FORMAT_B8G8R8A8_UNORM, - VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - }, - { - 0, - VK_FORMAT_D16_UNORM, - VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - }, - }; - VkAttachmentReference refs[] = { - {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - {1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}, - }; - VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &refs[0], nullptr, &refs[1], 0, nullptr}; - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 2, attachments, 1, &subpass, 0, nullptr}; - VkRenderPass rp; - VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), rp); - - m_errorMonitor->VerifyFound(); - - vkDestroyRenderPass(m_device->device(), rp, nullptr); -} - -TEST_F(VkLayerTest, CreatePipelineTessPatchDecorationMismatch) { - TEST_DESCRIPTION( - "Test that an error is produced for a variable output from the TCS without the patch decoration, but consumed in the TES " - "with the decoration."); - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "is per-vertex in tessellation control shader stage but per-patch in tessellation evaluation shader stage"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - if (!m_device->phy().features().tessellationShader) { - printf("%s Device does not support tessellation shaders; skipped.\n", kSkipPrefix); - return; - } - - char const *vsSource = - "#version 450\n" - "void main(){}\n"; - char const *tcsSource = - "#version 450\n" - "layout(location=0) out int x[];\n" - "layout(vertices=3) out;\n" - "void main(){\n" - " gl_TessLevelOuter[0] = gl_TessLevelOuter[1] = gl_TessLevelOuter[2] = 1;\n" - " gl_TessLevelInner[0] = 1;\n" - " x[gl_InvocationID] = gl_InvocationID;\n" - "}\n"; - char const *tesSource = - "#version 450\n" - "layout(triangles, equal_spacing, cw) in;\n" - "layout(location=0) patch in int x;\n" - "void main(){\n" - " gl_Position.xyz = gl_TessCoord;\n" - " gl_Position.w = x;\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj tcs(m_device, tcsSource, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, this); - VkShaderObj tes(m_device, tesSource, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineInputAssemblyStateCreateInfo iasci{VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, nullptr, 0, - VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, VK_FALSE}; - - VkPipelineTessellationStateCreateInfo tsci{VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, nullptr, 0, 3}; - - VkPipelineObj pipe(m_device); - pipe.SetInputAssembly(&iasci); - pipe.SetTessellation(&tsci); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&tcs); - pipe.AddShader(&tes); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineTessErrors) { - TEST_DESCRIPTION("Test various errors when creating a graphics pipeline with tessellation stages active."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - if (!m_device->phy().features().tessellationShader) { - printf("%s Device does not support tessellation shaders; skipped.\n", kSkipPrefix); - return; - } - - char const *vsSource = - "#version 450\n" - "void main(){}\n"; - char const *tcsSource = - "#version 450\n" - "layout(vertices=3) out;\n" - "void main(){\n" - " gl_TessLevelOuter[0] = gl_TessLevelOuter[1] = gl_TessLevelOuter[2] = 1;\n" - " gl_TessLevelInner[0] = 1;\n" - "}\n"; - char const *tesSource = - "#version 450\n" - "layout(triangles, equal_spacing, cw) in;\n" - "void main(){\n" - " gl_Position.xyz = gl_TessCoord;\n" - " gl_Position.w = 0;\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj tcs(m_device, tcsSource, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, this); - VkShaderObj tes(m_device, tesSource, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineInputAssemblyStateCreateInfo iasci{VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, nullptr, 0, - VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, VK_FALSE}; - - VkPipelineTessellationStateCreateInfo tsci{VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, nullptr, 0, 3}; - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - { - VkPipelineObj pipe(m_device); - VkPipelineInputAssemblyStateCreateInfo iasci_bad = iasci; - iasci_bad.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; // otherwise we get a failure about invalid topology - pipe.SetInputAssembly(&iasci_bad); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - // Pass a tess control shader without a tess eval shader - pipe.AddShader(&tcs); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkGraphicsPipelineCreateInfo-pStages-00729"); - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); - } - - { - VkPipelineObj pipe(m_device); - VkPipelineInputAssemblyStateCreateInfo iasci_bad = iasci; - iasci_bad.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; // otherwise we get a failure about invalid topology - pipe.SetInputAssembly(&iasci_bad); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - // Pass a tess eval shader without a tess control shader - pipe.AddShader(&tes); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkGraphicsPipelineCreateInfo-pStages-00730"); - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); - } - - { - VkPipelineObj pipe(m_device); - pipe.SetInputAssembly(&iasci); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - // Pass patch topology without tessellation shaders - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkGraphicsPipelineCreateInfo-topology-00737"); - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); - - pipe.AddShader(&tcs); - pipe.AddShader(&tes); - // Pass a NULL pTessellationState (with active tessellation shader stages) - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkGraphicsPipelineCreateInfo-pStages-00731"); - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); - - // Pass an invalid pTessellationState (bad sType) - VkPipelineTessellationStateCreateInfo tsci_bad = tsci; - tsci_bad.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - pipe.SetTessellation(&tsci_bad); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineTessellationStateCreateInfo-sType-sType"); - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); - // Pass out-of-range patchControlPoints - tsci_bad = tsci; - tsci_bad.patchControlPoints = 0; - pipe.SetTessellation(&tsci); - pipe.SetTessellation(&tsci_bad); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineTessellationStateCreateInfo-patchControlPoints-01214"); - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); - tsci_bad.patchControlPoints = m_device->props.limits.maxTessellationPatchSize + 1; - pipe.SetTessellation(&tsci_bad); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineTessellationStateCreateInfo-patchControlPoints-01214"); - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); - pipe.SetTessellation(&tsci); - - // Pass an invalid primitive topology - VkPipelineInputAssemblyStateCreateInfo iasci_bad = iasci; - iasci_bad.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - pipe.SetInputAssembly(&iasci_bad); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkGraphicsPipelineCreateInfo-pStages-00736"); - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); - pipe.SetInputAssembly(&iasci); - } -} - -TEST_F(VkLayerTest, CreatePipelineAttribBindingConflict) { - TEST_DESCRIPTION( - "Test that an error is produced for a vertex attribute setup where multiple bindings provide the same location"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Duplicate vertex input binding descriptions for binding 0"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - /* Two binding descriptions for binding 0 */ - VkVertexInputBindingDescription input_bindings[2]; - memset(input_bindings, 0, sizeof(input_bindings)); - - VkVertexInputAttributeDescription input_attrib; - memset(&input_attrib, 0, sizeof(input_attrib)); - input_attrib.format = VK_FORMAT_R32_SFLOAT; - - char const *vsSource = - "#version 450\n" - "\n" - "layout(location=0) in float x;\n" /* attrib provided float */ - "void main(){\n" - " gl_Position = vec4(x);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - pipe.AddVertexInputBindings(input_bindings, 2); - pipe.AddVertexInputAttribs(&input_attrib, 1); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - m_errorMonitor->SetUnexpectedError("VUID-VkPipelineVertexInputStateCreateInfo-pVertexBindingDescriptions-00616 "); - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineFragmentOutputNotWritten) { - TEST_DESCRIPTION( - "Test that an error is produced for a fragment shader which does not provide an output for one of the pipeline's color " - "attachments"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, "Attachment 0 not written by fragment shader"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "void main(){\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - /* set up CB 0, not written */ - pipe.AddDefaultColorAttachment(); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkPositiveLayerTest, CreatePipelineFragmentOutputNotWrittenButMasked) { - TEST_DESCRIPTION( - "Test that no error is produced when the fragment shader fails to declare an output, but the corresponding attachment's " - "write mask is 0."); - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "void main(){\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - /* set up CB 0, not written, but also masked */ - pipe.AddDefaultColorAttachment(0); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkLayerTest, CreatePipelineFragmentOutputNotConsumed) { - TEST_DESCRIPTION( - "Test that a warning is produced for a fragment shader which provides a spurious output with no matching attachment"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, - "fragment shader writes to output location 1 with no matching attachment"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 x;\n" - "layout(location=1) out vec4 y;\n" /* no matching attachment for this */ - "void main(){\n" - " x = vec4(1);\n" - " y = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - /* set up CB 0, not written */ - pipe.AddDefaultColorAttachment(); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - /* FS writes CB 1, but we don't configure it */ - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineFragmentOutputNotConsumedButAlphaToCoverageEnabled) { - TEST_DESCRIPTION( - "Test that no warning is produced when writing to non-existing color attachment if alpha to coverage is enabled."); - - m_errorMonitor->ExpectSuccess(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT); - - ASSERT_NO_FATAL_FAILURE(Init()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 x;\n" - "void main(){\n" - " x = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkPipelineMultisampleStateCreateInfo ms_state_ci = {}; - ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - ms_state_ci.alphaToCoverageEnable = VK_TRUE; - pipe.SetMSAA(&ms_state_ci); - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget(0u)); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkLayerTest, CreatePipelineFragmentNoOutputLocation0ButAlphaToCoverageEnabled) { - TEST_DESCRIPTION("Test that an error is produced when alpha to coverage is enabled but no output at location 0 is declared."); - - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "fragment shader doesn't declare alpha output at location 0 even though alpha to coverage is enabled."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "void main(){\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkPipelineMultisampleStateCreateInfo ms_state_ci = {}; - ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - ms_state_ci.alphaToCoverageEnable = VK_TRUE; - pipe.SetMSAA(&ms_state_ci); - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget(0u)); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineFragmentNoAlphaLocation0ButAlphaToCoverageEnabled) { - TEST_DESCRIPTION( - "Test that an error is produced when alpha to coverage is enabled but output at location 0 doesn't have alpha channel."); - - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "fragment shader doesn't declare alpha output at location 0 even though alpha to coverage is enabled."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "layout(location=0) out vec3 x;\n" - "\n" - "void main(){\n" - " x = vec3(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkPipelineMultisampleStateCreateInfo ms_state_ci = {}; - ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - ms_state_ci.alphaToCoverageEnable = VK_TRUE; - pipe.SetMSAA(&ms_state_ci); - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget(0u)); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineFragmentOutputTypeMismatch) { - TEST_DESCRIPTION( - "Test that an error is produced for a mismatch between the fundamental type of an fragment shader output variable, and the " - "format of the corresponding attachment"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, "does not match fragment shader output type"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out ivec4 x;\n" /* not UNORM */ - "void main(){\n" - " x = ivec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - /* set up CB 0; type is UNORM by default */ - pipe.AddDefaultColorAttachment(); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineExceedMaxVertexOutputComponents) { - TEST_DESCRIPTION( - "Test that an error is produced when the number of output components from the vertex stage exceeds the device limit"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Vertex shader exceeds " - "VkPhysicalDeviceLimits::maxVertexOutputComponents"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - const uint32_t maxVsOutComp = m_device->props.limits.maxVertexOutputComponents; - std::string vsSourceStr = "#version 450\n\n"; - const uint32_t numVec4 = maxVsOutComp / 4; - uint32_t location = 0; - for (uint32_t i = 0; i < numVec4; i++) { - vsSourceStr += "layout(location=" + std::to_string(location) + ") out vec4 v" + std::to_string(i) + ";\n"; - location += 1; - } - const uint32_t remainder = maxVsOutComp % 4; - if (remainder != 0) { - if (remainder == 1) { - vsSourceStr += "layout(location=" + std::to_string(location) + ") out float" + " vn;\n"; - } else { - vsSourceStr += "layout(location=" + std::to_string(location) + ") out vec" + std::to_string(remainder) + " vn;\n"; - } - location += 1; - } - vsSourceStr += "layout(location=" + std::to_string(location) + - ") out vec4 exceedLimit;\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - - std::string fsSourceStr = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSourceStr.c_str(), VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSourceStr.c_str(), VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - // Set up CB 0; type is UNORM by default - pipe.AddDefaultColorAttachment(); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineExceedMaxTessellationControlInputOutputComponents) { - TEST_DESCRIPTION( - "Test that errors are produced when the number of per-vertex input and/or output components to the tessellation control " - "stage exceeds the device limit"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Tessellation control shader exceeds " - "VkPhysicalDeviceLimits::maxTessellationControlPerVertexInputComponents"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Tessellation control shader exceeds " - "VkPhysicalDeviceLimits::maxTessellationControlPerVertexOutputComponents"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkPhysicalDeviceFeatures feat; - vkGetPhysicalDeviceFeatures(gpu(), &feat); - if (!feat.tessellationShader) { - printf("%s tessellation shader stage(s) unsupported.\n", kSkipPrefix); - return; - } - - std::string vsSourceStr = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - - // Tessellation control stage - std::string tcsSourceStr = - "#version 450\n" - "\n"; - // Input components - const uint32_t maxTescInComp = m_device->props.limits.maxTessellationControlPerVertexInputComponents; - const uint32_t numInVec4 = maxTescInComp / 4; - uint32_t inLocation = 0; - for (uint32_t i = 0; i < numInVec4; i++) { - tcsSourceStr += "layout(location=" + std::to_string(inLocation) + ") in vec4 v" + std::to_string(i) + "In[];\n"; - inLocation += 1; - } - const uint32_t inRemainder = maxTescInComp % 4; - if (inRemainder != 0) { - if (inRemainder == 1) { - tcsSourceStr += "layout(location=" + std::to_string(inLocation) + ") in float" + " vnIn[];\n"; - } else { - tcsSourceStr += - "layout(location=" + std::to_string(inLocation) + ") in vec" + std::to_string(inRemainder) + " vnIn[];\n"; - } - inLocation += 1; - } - tcsSourceStr += "layout(location=" + std::to_string(inLocation) + ") in vec4 exceedLimitIn[];\n\n"; - // Output components - const uint32_t maxTescOutComp = m_device->props.limits.maxTessellationControlPerVertexOutputComponents; - const uint32_t numOutVec4 = maxTescOutComp / 4; - uint32_t outLocation = 0; - for (uint32_t i = 0; i < numOutVec4; i++) { - tcsSourceStr += "layout(location=" + std::to_string(outLocation) + ") out vec4 v" + std::to_string(i) + "Out[3];\n"; - outLocation += 1; - } - const uint32_t outRemainder = maxTescOutComp % 4; - if (outRemainder != 0) { - if (outRemainder == 1) { - tcsSourceStr += "layout(location=" + std::to_string(outLocation) + ") out float" + " vnOut[3];\n"; - } else { - tcsSourceStr += - "layout(location=" + std::to_string(outLocation) + ") out vec" + std::to_string(outRemainder) + " vnOut[3];\n"; - } - outLocation += 1; - } - tcsSourceStr += "layout(location=" + std::to_string(outLocation) + ") out vec4 exceedLimitOut[3];\n"; - tcsSourceStr += "layout(vertices=3) out;\n"; - // Finalize - tcsSourceStr += - "\n" - "void main(){\n" - " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" - "}\n"; - - std::string tesSourceStr = - "#version 450\n" - "\n" - "layout(triangles) in;" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - - std::string fsSourceStr = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;" - "\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSourceStr.c_str(), VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj tcs(m_device, tcsSourceStr.c_str(), VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, this); - VkShaderObj tes(m_device, tesSourceStr.c_str(), VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, this); - VkShaderObj fs(m_device, fsSourceStr.c_str(), VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&tcs); - pipe.AddShader(&tes); - pipe.AddShader(&fs); - - // Set up CB 0; type is UNORM by default - pipe.AddDefaultColorAttachment(); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo = {}; - inputAssemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - inputAssemblyInfo.pNext = NULL; - inputAssemblyInfo.flags = 0; - inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; - inputAssemblyInfo.primitiveRestartEnable = VK_FALSE; - pipe.SetInputAssembly(&inputAssemblyInfo); - - VkPipelineTessellationStateCreateInfo tessInfo = {}; - tessInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; - tessInfo.pNext = NULL; - tessInfo.flags = 0; - tessInfo.patchControlPoints = 3; - pipe.SetTessellation(&tessInfo); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineExceedMaxTessellationEvaluationInputOutputComponents) { - TEST_DESCRIPTION( - "Test that errors are produced when the number of input and/or output components to the tessellation evaluation stage " - "exceeds the device limit"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Tessellation evaluation shader exceeds " - "VkPhysicalDeviceLimits::maxTessellationEvaluationInputComponents"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Tessellation evaluation shader exceeds " - "VkPhysicalDeviceLimits::maxTessellationEvaluationOutputComponents"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkPhysicalDeviceFeatures feat; - vkGetPhysicalDeviceFeatures(gpu(), &feat); - if (!feat.tessellationShader) { - printf("%s tessellation shader stage(s) unsupported.\n", kSkipPrefix); - return; - } - - std::string vsSourceStr = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - - std::string tcsSourceStr = - "#version 450\n" - "\n" - "layout (vertices = 3) out;\n" - "\n" - "void main(){\n" - " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" - "}\n"; - - // Tessellation evaluation stage - std::string tesSourceStr = - "#version 450\n" - "\n" - "layout (triangles) in;\n" - "\n"; - // Input components - const uint32_t maxTeseInComp = m_device->props.limits.maxTessellationEvaluationInputComponents; - const uint32_t numInVec4 = maxTeseInComp / 4; - uint32_t inLocation = 0; - for (uint32_t i = 0; i < numInVec4; i++) { - tesSourceStr += "layout(location=" + std::to_string(inLocation) + ") in vec4 v" + std::to_string(i) + "In[];\n"; - inLocation += 1; - } - const uint32_t inRemainder = maxTeseInComp % 4; - if (inRemainder != 0) { - if (inRemainder == 1) { - tesSourceStr += "layout(location=" + std::to_string(inLocation) + ") in float" + " vnIn[];\n"; - } else { - tesSourceStr += - "layout(location=" + std::to_string(inLocation) + ") in vec" + std::to_string(inRemainder) + " vnIn[];\n"; - } - inLocation += 1; - } - tesSourceStr += "layout(location=" + std::to_string(inLocation) + ") in vec4 exceedLimitIn[];\n\n"; - // Output components - const uint32_t maxTeseOutComp = m_device->props.limits.maxTessellationEvaluationOutputComponents; - const uint32_t numOutVec4 = maxTeseOutComp / 4; - uint32_t outLocation = 0; - for (uint32_t i = 0; i < numOutVec4; i++) { - tesSourceStr += "layout(location=" + std::to_string(outLocation) + ") out vec4 v" + std::to_string(i) + "Out;\n"; - outLocation += 1; - } - const uint32_t outRemainder = maxTeseOutComp % 4; - if (outRemainder != 0) { - if (outRemainder == 1) { - tesSourceStr += "layout(location=" + std::to_string(outLocation) + ") out float" + " vnOut;\n"; - } else { - tesSourceStr += - "layout(location=" + std::to_string(outLocation) + ") out vec" + std::to_string(outRemainder) + " vnOut;\n"; - } - outLocation += 1; - } - tesSourceStr += "layout(location=" + std::to_string(outLocation) + ") out vec4 exceedLimitOut;\n"; - // Finalize - tesSourceStr += - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - - std::string fsSourceStr = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;" - "\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSourceStr.c_str(), VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj tcs(m_device, tcsSourceStr.c_str(), VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, this); - VkShaderObj tes(m_device, tesSourceStr.c_str(), VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, this); - VkShaderObj fs(m_device, fsSourceStr.c_str(), VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&tcs); - pipe.AddShader(&tes); - pipe.AddShader(&fs); - - // Set up CB 0; type is UNORM by default - pipe.AddDefaultColorAttachment(); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo = {}; - inputAssemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - inputAssemblyInfo.pNext = NULL; - inputAssemblyInfo.flags = 0; - inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; - inputAssemblyInfo.primitiveRestartEnable = VK_FALSE; - pipe.SetInputAssembly(&inputAssemblyInfo); - - VkPipelineTessellationStateCreateInfo tessInfo = {}; - tessInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; - tessInfo.pNext = NULL; - tessInfo.flags = 0; - tessInfo.patchControlPoints = 3; - pipe.SetTessellation(&tessInfo); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineExceedMaxGeometryInputOutputComponents) { - TEST_DESCRIPTION( - "Test that errors are produced when the number of input and/or output components to the geometry stage exceeds the device " - "limit"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Geometry shader exceeds " - "VkPhysicalDeviceLimits::maxGeometryInputComponents"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Geometry shader exceeds " - "VkPhysicalDeviceLimits::maxGeometryOutputComponents"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkPhysicalDeviceFeatures feat; - vkGetPhysicalDeviceFeatures(gpu(), &feat); - if (!feat.geometryShader) { - printf("%s geometry shader stage unsupported.\n", kSkipPrefix); - return; - } - - std::string vsSourceStr = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - - std::string gsSourceStr = - "#version 450\n" - "\n" - "layout(triangles) in;\n" - "layout(invocations=1) in;\n"; - // Input components - const uint32_t maxGeomInComp = m_device->props.limits.maxGeometryInputComponents; - const uint32_t numInVec4 = maxGeomInComp / 4; - uint32_t inLocation = 0; - for (uint32_t i = 0; i < numInVec4; i++) { - gsSourceStr += "layout(location=" + std::to_string(inLocation) + ") in vec4 v" + std::to_string(i) + "In[];\n"; - inLocation += 1; - } - const uint32_t inRemainder = maxGeomInComp % 4; - if (inRemainder != 0) { - if (inRemainder == 1) { - gsSourceStr += "layout(location=" + std::to_string(inLocation) + ") in float" + " vnIn[];\n"; - } else { - gsSourceStr += - "layout(location=" + std::to_string(inLocation) + ") in vec" + std::to_string(inRemainder) + " vnIn[];\n"; - } - inLocation += 1; - } - gsSourceStr += "layout(location=" + std::to_string(inLocation) + ") in vec4 exceedLimitIn[];\n\n"; - // Output components - const uint32_t maxGeomOutComp = m_device->props.limits.maxGeometryOutputComponents; - const uint32_t numOutVec4 = maxGeomOutComp / 4; - uint32_t outLocation = 0; - for (uint32_t i = 0; i < numOutVec4; i++) { - gsSourceStr += "layout(location=" + std::to_string(outLocation) + ") out vec4 v" + std::to_string(i) + "Out;\n"; - outLocation += 1; - } - const uint32_t outRemainder = maxGeomOutComp % 4; - if (outRemainder != 0) { - if (outRemainder == 1) { - gsSourceStr += "layout(location=" + std::to_string(outLocation) + ") out float" + " vnOut;\n"; - } else { - gsSourceStr += - "layout(location=" + std::to_string(outLocation) + ") out vec" + std::to_string(outRemainder) + " vnOut;\n"; - } - outLocation += 1; - } - gsSourceStr += "layout(location=" + std::to_string(outLocation) + ") out vec4 exceedLimitOut;\n"; - // Finalize - gsSourceStr += - "layout(triangle_strip, max_vertices=3) out;\n" - "\n" - "void main(){\n" - " exceedLimitOut = vec4(1);\n" - "}\n"; - - std::string fsSourceStr = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;" - "\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSourceStr.c_str(), VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj gs(m_device, gsSourceStr.c_str(), VK_SHADER_STAGE_GEOMETRY_BIT, this); - VkShaderObj fs(m_device, fsSourceStr.c_str(), VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&gs); - pipe.AddShader(&fs); - - // Set up CB 0; type is UNORM by default - pipe.AddDefaultColorAttachment(); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineExceedMaxFragmentInputComponents) { - TEST_DESCRIPTION( - "Test that an error is produced when the number of input components from the fragment stage exceeds the device limit"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Fragment shader exceeds " - "VkPhysicalDeviceLimits::maxFragmentInputComponents"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - std::string vsSourceStr = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - - const uint32_t maxFsInComp = m_device->props.limits.maxFragmentInputComponents; - std::string fsSourceStr = "#version 450\n\n"; - const uint32_t numVec4 = maxFsInComp / 4; - uint32_t location = 0; - for (uint32_t i = 0; i < numVec4; i++) { - fsSourceStr += "layout(location=" + std::to_string(location) + ") in vec4 v" + std::to_string(i) + ";\n"; - location += 1; - } - const uint32_t remainder = maxFsInComp % 4; - if (remainder != 0) { - if (remainder == 1) { - fsSourceStr += "layout(location=" + std::to_string(location) + ") in float" + " vn;\n"; - } else { - fsSourceStr += "layout(location=" + std::to_string(location) + ") in vec" + std::to_string(remainder) + " vn;\n"; - } - location += 1; - } - fsSourceStr += "layout(location=" + std::to_string(location) + - ") in vec4 exceedLimit;\n" - "\n" - "layout(location=0) out vec4 color;" - "\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSourceStr.c_str(), VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSourceStr.c_str(), VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - // Set up CB 0; type is UNORM by default - pipe.AddDefaultColorAttachment(); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineUniformBlockNotProvided) { - TEST_DESCRIPTION( - "Test that an error is produced for a shader consuming a uniform block which has no corresponding binding in the pipeline " - "layout"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "not declared in pipeline layout"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 x;\n" - "layout(set=0) layout(binding=0) uniform foo { int x; int y; } bar;\n" - "void main(){\n" - " x = vec4(bar.y);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - /* set up CB 0; type is UNORM by default */ - pipe.AddDefaultColorAttachment(); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelinePushConstantsNotInLayout) { - TEST_DESCRIPTION( - "Test that an error is produced for a shader consuming push constants which are not provided in the pipeline layout"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "not declared in layout"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - char const *vsSource = - "#version 450\n" - "\n" - "layout(push_constant, std430) uniform foo { float x; } consts;\n" - "void main(){\n" - " gl_Position = vec4(consts.x);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 x;\n" - "void main(){\n" - " x = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - /* set up CB 0; type is UNORM by default */ - pipe.AddDefaultColorAttachment(); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - /* should have generated an error -- no push constant ranges provided! */ - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineInputAttachmentMissing) { - TEST_DESCRIPTION( - "Test that an error is produced for a shader consuming an input attachment which is not included in the subpass " - "description"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "consumes input attachment index 0 but not provided in subpass"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(input_attachment_index=0, set=0, binding=0) uniform subpassInput x;\n" - "layout(location=0) out vec4 color;\n" - "void main() {\n" - " color = subpassLoad(x);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetLayoutBinding dslb = {0, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}; - const VkDescriptorSetLayoutObj dsl(m_device, {dslb}); - - const VkPipelineLayoutObj pl(m_device, {&dsl}); - - // error here. - pipe.CreateVKPipeline(pl.handle(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreatePipelineInputAttachmentTypeMismatch) { - TEST_DESCRIPTION( - "Test that an error is produced for a shader consuming an input attachment with a format having a different fundamental " - "type"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "input attachment 0 format of VK_FORMAT_R8G8B8A8_UINT does not match"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(input_attachment_index=0, set=0, binding=0) uniform subpassInput x;\n" - "layout(location=0) out vec4 color;\n" - "void main() {\n" - " color = subpassLoad(x);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetLayoutBinding dslb = {0, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}; - const VkDescriptorSetLayoutObj dsl(m_device, {dslb}); - - const VkPipelineLayoutObj pl(m_device, {&dsl}); - - VkAttachmentDescription descs[2] = { - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, - VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - {0, VK_FORMAT_R8G8B8A8_UINT, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, - VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL}, - }; - VkAttachmentReference color = { - 0, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - }; - VkAttachmentReference input = { - 1, - VK_IMAGE_LAYOUT_GENERAL, - }; - - VkSubpassDescription sd = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &input, 1, &color, nullptr, nullptr, 0, nullptr}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 2, descs, 1, &sd, 0, nullptr}; - VkRenderPass rp; - VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - - // error here. - pipe.CreateVKPipeline(pl.handle(), rp); - - m_errorMonitor->VerifyFound(); - - vkDestroyRenderPass(m_device->device(), rp, nullptr); -} - -TEST_F(VkLayerTest, CreatePipelineInputAttachmentMissingArray) { - TEST_DESCRIPTION( - "Test that an error is produced for a shader consuming an input attachment which is not included in the subpass " - "description -- array case"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "consumes input attachment index 0 but not provided in subpass"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(input_attachment_index=0, set=0, binding=0) uniform subpassInput xs[1];\n" - "layout(location=0) out vec4 color;\n" - "void main() {\n" - " color = subpassLoad(xs[0]);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetLayoutBinding dslb = {0, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 2, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}; - const VkDescriptorSetLayoutObj dsl(m_device, {dslb}); - - const VkPipelineLayoutObj pl(m_device, {&dsl}); - - // error here. - pipe.CreateVKPipeline(pl.handle(), renderPass()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreateComputePipelineMissingDescriptor) { - TEST_DESCRIPTION( - "Test that an error is produced for a compute pipeline consuming a descriptor which is not provided in the pipeline " - "layout"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Shader uses descriptor slot 0.0"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - char const *csSource = - "#version 450\n" - "\n" - "layout(local_size_x=1) in;\n" - "layout(set=0, binding=0) buffer block { vec4 x; };\n" - "void main(){\n" - " x = vec4(1);\n" - "}\n"; - - VkShaderObj cs(m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT, this); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - VkComputePipelineCreateInfo cpci = {VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - nullptr, - 0, - {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0, - VK_SHADER_STAGE_COMPUTE_BIT, cs.handle(), "main", nullptr}, - descriptorSet.GetPipelineLayout(), - VK_NULL_HANDLE, - -1}; - - VkPipeline pipe; - VkResult err = vkCreateComputePipelines(m_device->device(), VK_NULL_HANDLE, 1, &cpci, nullptr, &pipe); - - m_errorMonitor->VerifyFound(); - - if (err == VK_SUCCESS) { - vkDestroyPipeline(m_device->device(), pipe, nullptr); - } -} - -TEST_F(VkLayerTest, CreateComputePipelineDescriptorTypeMismatch) { - TEST_DESCRIPTION("Test that an error is produced for a pipeline consuming a descriptor-backed resource of a mismatched type"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "but descriptor of type VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}; - const VkDescriptorSetLayoutObj dsl(m_device, {binding}); - - const VkPipelineLayoutObj pl(m_device, {&dsl}); - - char const *csSource = - "#version 450\n" - "\n" - "layout(local_size_x=1) in;\n" - "layout(set=0, binding=0) buffer block { vec4 x; };\n" - "void main() {\n" - " x.x = 1.0f;\n" - "}\n"; - VkShaderObj cs(m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT, this); - - VkComputePipelineCreateInfo cpci = {VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - nullptr, - 0, - {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0, - VK_SHADER_STAGE_COMPUTE_BIT, cs.handle(), "main", nullptr}, - pl.handle(), - VK_NULL_HANDLE, - -1}; - - VkPipeline pipe; - VkResult err = vkCreateComputePipelines(m_device->device(), VK_NULL_HANDLE, 1, &cpci, nullptr, &pipe); - - m_errorMonitor->VerifyFound(); - - if (err == VK_SUCCESS) { - vkDestroyPipeline(m_device->device(), pipe, nullptr); - } -} - -TEST_F(VkLayerTest, DrawTimeImageViewTypeMismatchWithPipeline) { - TEST_DESCRIPTION( - "Test that an error is produced when an image view type does not match the dimensionality declared in the shader"); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "requires an image view of type VK_IMAGE_VIEW_TYPE_3D"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main() { gl_Position = vec4(0); }\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(set=0, binding=0) uniform sampler3D s;\n" - "layout(location=0) out vec4 color;\n" - "void main() {\n" - " color = texture(s, vec3(0));\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - - VkTextureObj texture(m_device, nullptr); - VkSamplerObj sampler(m_device); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendSamplerTexture(&sampler, &texture); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - VkResult err = pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - m_commandBuffer->BindDescriptorSet(descriptorSet); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - - // error produced here. - vkCmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); - - m_errorMonitor->VerifyFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, DrawTimeImageMultisampleMismatchWithPipeline) { - TEST_DESCRIPTION( - "Test that an error is produced when a multisampled images are consumed via singlesample images types in the shader, or " - "vice versa."); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "requires bound image to have multiple samples"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main() { gl_Position = vec4(0); }\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(set=0, binding=0) uniform sampler2DMS s;\n" - "layout(location=0) out vec4 color;\n" - "void main() {\n" - " color = texelFetch(s, ivec2(0), 0);\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - - VkTextureObj texture(m_device, nullptr); // THIS LINE CAUSES CRASH ON MALI - VkSamplerObj sampler(m_device); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendSamplerTexture(&sampler, &texture); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - VkResult err = pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - m_commandBuffer->BindDescriptorSet(descriptorSet); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - - // error produced here. - vkCmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); - - m_errorMonitor->VerifyFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, DrawTimeImageComponentTypeMismatchWithPipeline) { - TEST_DESCRIPTION( - "Test that an error is produced when the component type of an imageview disagrees with the type in the shader."); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "SINT component type, but bound descriptor"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main() { gl_Position = vec4(0); }\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(set=0, binding=0) uniform isampler2D s;\n" - "layout(location=0) out vec4 color;\n" - "void main() {\n" - " color = texelFetch(s, ivec2(0), 0);\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - - VkTextureObj texture(m_device, nullptr); // UNORM texture by default, incompatible with isampler2D - VkSamplerObj sampler(m_device); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendSamplerTexture(&sampler, &texture); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - VkResult err = pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - m_commandBuffer->BindDescriptorSet(descriptorSet); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - - // error produced here. - vkCmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); - - m_errorMonitor->VerifyFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, AttachmentDescriptionUndefinedFormat) { - TEST_DESCRIPTION("Create a render pass with an attachment description format set to VK_FORMAT_UNDEFINED"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, "format is VK_FORMAT_UNDEFINED"); - - VkAttachmentReference color_attach = {}; - color_attach.layout = VK_IMAGE_LAYOUT_GENERAL; - color_attach.attachment = 0; - VkSubpassDescription subpass = {}; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &color_attach; - - VkRenderPassCreateInfo rpci = {}; - rpci.subpassCount = 1; - rpci.pSubpasses = &subpass; - rpci.attachmentCount = 1; - VkAttachmentDescription attach_desc = {}; - attach_desc.format = VK_FORMAT_UNDEFINED; - attach_desc.samples = VK_SAMPLE_COUNT_1_BIT; - attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL; - rpci.pAttachments = &attach_desc; - rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - VkRenderPass rp; - VkResult result = vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp); - - m_errorMonitor->VerifyFound(); - - if (result == VK_SUCCESS) { - vkDestroyRenderPass(m_device->device(), rp, NULL); - } -} - -TEST_F(VkLayerTest, CreateImageViewNoMemoryBoundToImage) { - VkResult err; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - " used with no memory bound. Memory should be bound by calling vkBindImageMemory()."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // Create an image and try to create a view with no memory backing the image - VkImage image; - - const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; - const int32_t tex_width = 32; - const int32_t tex_height = 32; - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = tex_format; - image_create_info.extent.width = tex_width; - image_create_info.extent.height = tex_height; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - image_create_info.flags = 0; - - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - ASSERT_VK_SUCCESS(err); - - VkImageViewCreateInfo image_view_create_info = {}; - image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - image_view_create_info.image = image; - image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - image_view_create_info.format = tex_format; - image_view_create_info.subresourceRange.layerCount = 1; - image_view_create_info.subresourceRange.baseMipLevel = 0; - image_view_create_info.subresourceRange.levelCount = 1; - image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - VkImageView view; - err = vkCreateImageView(m_device->device(), &image_view_create_info, NULL, &view); - - m_errorMonitor->VerifyFound(); - vkDestroyImage(m_device->device(), image, NULL); - // If last error is success, it still created the view, so delete it. - if (err == VK_SUCCESS) { - vkDestroyImageView(m_device->device(), view, NULL); - } -} - -TEST_F(VkLayerTest, InvalidImageViewAspect) { - TEST_DESCRIPTION("Create an image and try to create a view with an invalid aspectMask"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageSubresource-aspectMask-parameter"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; - VkImageObj image(m_device); - image.Init(32, 32, 1, tex_format, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_LINEAR, 0); - ASSERT_TRUE(image.initialized()); - - VkImageViewCreateInfo image_view_create_info = {}; - image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - image_view_create_info.image = image.handle(); - image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - image_view_create_info.format = tex_format; - image_view_create_info.subresourceRange.baseMipLevel = 0; - image_view_create_info.subresourceRange.levelCount = 1; - image_view_create_info.subresourceRange.layerCount = 1; - // Cause an error by setting an invalid image aspect - image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT; - - VkImageView view; - vkCreateImageView(m_device->device(), &image_view_create_info, NULL, &view); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, ExerciseGetImageSubresourceLayout) { - TEST_DESCRIPTION("Test vkGetImageSubresourceLayout() valid usages"); - - ASSERT_NO_FATAL_FAILURE(Init()); - VkSubresourceLayout subres_layout = {}; - - // VU 00732: image must have been created with tiling equal to VK_IMAGE_TILING_LINEAR - { - const VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL; // ERROR: violates VU 00732 - VkImageObj img(m_device); - img.InitNoLayout(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, tiling); - ASSERT_TRUE(img.initialized()); - - VkImageSubresource subres = {}; - subres.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subres.mipLevel = 0; - subres.arrayLayer = 0; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkGetImageSubresourceLayout-image-00996"); - vkGetImageSubresourceLayout(m_device->device(), img.image(), &subres, &subres_layout); - m_errorMonitor->VerifyFound(); - } - - // VU 00733: The aspectMask member of pSubresource must only have a single bit set - { - VkImageObj img(m_device); - img.InitNoLayout(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_SRC_BIT); - ASSERT_TRUE(img.initialized()); - - VkImageSubresource subres = {}; - subres.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_METADATA_BIT; // ERROR: triggers VU 00733 - subres.mipLevel = 0; - subres.arrayLayer = 0; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkGetImageSubresourceLayout-aspectMask-00997"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageSubresource-aspectMask-parameter"); - vkGetImageSubresourceLayout(m_device->device(), img.image(), &subres, &subres_layout); - m_errorMonitor->VerifyFound(); - } - - // 00739 mipLevel must be less than the mipLevels specified in VkImageCreateInfo when the image was created - { - VkImageObj img(m_device); - img.InitNoLayout(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_SRC_BIT); - ASSERT_TRUE(img.initialized()); - - VkImageSubresource subres = {}; - subres.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subres.mipLevel = 1; // ERROR: triggers VU 00739 - subres.arrayLayer = 0; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkGetImageSubresourceLayout-mipLevel-01716"); - vkGetImageSubresourceLayout(m_device->device(), img.image(), &subres, &subres_layout); - m_errorMonitor->VerifyFound(); - } - - // 00740 arrayLayer must be less than the arrayLayers specified in VkImageCreateInfo when the image was created - { - VkImageObj img(m_device); - img.InitNoLayout(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_SRC_BIT); - ASSERT_TRUE(img.initialized()); - - VkImageSubresource subres = {}; - subres.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subres.mipLevel = 0; - subres.arrayLayer = 1; // ERROR: triggers VU 00740 - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkGetImageSubresourceLayout-arrayLayer-01717"); - vkGetImageSubresourceLayout(m_device->device(), img.image(), &subres, &subres_layout); - m_errorMonitor->VerifyFound(); - } -} - -TEST_F(VkLayerTest, CopyImageLayerCountMismatch) { - TEST_DESCRIPTION( - "Try to copy between images with the source subresource having a different layerCount than the destination subresource"); - ASSERT_NO_FATAL_FAILURE(Init()); - - // Create two images to copy between - VkImageObj src_image_obj(m_device); - VkImageObj dst_image_obj(m_device); - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM; - image_create_info.extent.width = 32; - image_create_info.extent.height = 32; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 4; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - image_create_info.flags = 0; - - src_image_obj.init(&image_create_info); - ASSERT_TRUE(src_image_obj.initialized()); - - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; - dst_image_obj.init(&image_create_info); - ASSERT_TRUE(dst_image_obj.initialized()); - - m_commandBuffer->begin(); - VkImageCopy copyRegion; - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.srcSubresource.mipLevel = 0; - copyRegion.srcSubresource.baseArrayLayer = 0; - copyRegion.srcSubresource.layerCount = 1; - copyRegion.srcOffset.x = 0; - copyRegion.srcOffset.y = 0; - copyRegion.srcOffset.z = 0; - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.dstSubresource.mipLevel = 0; - copyRegion.dstSubresource.baseArrayLayer = 0; - // Introduce failure by forcing the dst layerCount to differ from src - copyRegion.dstSubresource.layerCount = 3; - copyRegion.dstOffset.x = 0; - copyRegion.dstOffset.y = 0; - copyRegion.dstOffset.z = 0; - copyRegion.extent.width = 1; - copyRegion.extent.height = 1; - copyRegion.extent.depth = 1; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-extent-00140"); - m_commandBuffer->CopyImage(src_image_obj.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image_obj.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©Region); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, ImageLayerUnsupportedFormat) { - TEST_DESCRIPTION("Creating images with unsupported formats "); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Create image with unsupported format - Expect FORMAT_UNSUPPORTED - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_UNDEFINED; - image_create_info.extent.width = 32; - image_create_info.extent.height = 32; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-format-00943"); - - VkImage image; - vkCreateImage(m_device->handle(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreateImageViewFormatMismatchUnrelated) { - TEST_DESCRIPTION("Create an image with a color format, then try to create a depth view of it"); - - if (!EnableDeviceProfileLayer()) { - printf("%s Failed to enable device profile layer.\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - ASSERT_NO_FATAL_FAILURE(InitState()); - - // Load required functions - PFN_vkSetPhysicalDeviceFormatPropertiesEXT fpvkSetPhysicalDeviceFormatPropertiesEXT = - (PFN_vkSetPhysicalDeviceFormatPropertiesEXT)vkGetInstanceProcAddr(instance(), "vkSetPhysicalDeviceFormatPropertiesEXT"); - PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT = - (PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT)vkGetInstanceProcAddr(instance(), - "vkGetOriginalPhysicalDeviceFormatPropertiesEXT"); - - if (!(fpvkSetPhysicalDeviceFormatPropertiesEXT) || !(fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT)) { - printf("%s Can't find device_profile_api functions; skipped.\n", kSkipPrefix); - return; - } - - auto depth_format = FindSupportedDepthStencilFormat(gpu()); - if (!depth_format) { - printf("%s Couldn't find depth stencil image format.\n", kSkipPrefix); - return; - } - - VkFormatProperties formatProps; - - fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT(gpu(), depth_format, &formatProps); - formatProps.optimalTilingFeatures |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; - fpvkSetPhysicalDeviceFormatPropertiesEXT(gpu(), depth_format, formatProps); - - VkImageObj image(m_device); - image.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - VkImageView imgView; - VkImageViewCreateInfo imgViewInfo = {}; - imgViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - imgViewInfo.image = image.handle(); - imgViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - imgViewInfo.format = depth_format; - imgViewInfo.subresourceRange.layerCount = 1; - imgViewInfo.subresourceRange.baseMipLevel = 0; - imgViewInfo.subresourceRange.levelCount = 1; - imgViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - // Can't use depth format for view into color image - Expect INVALID_FORMAT - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Formats MUST be IDENTICAL unless VK_IMAGE_CREATE_MUTABLE_FORMAT BIT was set on image creation."); - vkCreateImageView(m_device->handle(), &imgViewInfo, NULL, &imgView); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreateImageViewNoMutableFormatBit) { - TEST_DESCRIPTION("Create an image view with a different format, when the image does not have MUTABLE_FORMAT bit"); - - if (!EnableDeviceProfileLayer()) { - printf("%s Couldn't enable device profile layer.\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - ASSERT_NO_FATAL_FAILURE(InitState()); - - PFN_vkSetPhysicalDeviceFormatPropertiesEXT fpvkSetPhysicalDeviceFormatPropertiesEXT = nullptr; - PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT = nullptr; - - // Load required functions - if (!LoadDeviceProfileLayer(fpvkSetPhysicalDeviceFormatPropertiesEXT, fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT)) { - printf("%s Required extensions are not present.\n", kSkipPrefix); - return; - } - - VkImageObj image(m_device); - image.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - VkFormatProperties formatProps; - - fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT(gpu(), VK_FORMAT_B8G8R8A8_UINT, &formatProps); - formatProps.optimalTilingFeatures |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; - fpvkSetPhysicalDeviceFormatPropertiesEXT(gpu(), VK_FORMAT_B8G8R8A8_UINT, formatProps); - - VkImageView imgView; - VkImageViewCreateInfo imgViewInfo = {}; - imgViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - imgViewInfo.image = image.handle(); - imgViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - imgViewInfo.format = VK_FORMAT_B8G8R8A8_UINT; - imgViewInfo.subresourceRange.layerCount = 1; - imgViewInfo.subresourceRange.baseMipLevel = 0; - imgViewInfo.subresourceRange.levelCount = 1; - imgViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - // Same compatibility class but no MUTABLE_FORMAT bit - Expect - // VIEW_CREATE_ERROR - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-image-01019"); - vkCreateImageView(m_device->handle(), &imgViewInfo, NULL, &imgView); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreateImageViewDifferentClass) { - TEST_DESCRIPTION("Passing bad parameters to CreateImageView"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - if (!(m_device->format_properties(VK_FORMAT_R8_UINT).optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) { - printf("%s Device does not support R8_UINT as color attachment; skipped", kSkipPrefix); - return; - } - - VkImageCreateInfo mutImgInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - nullptr, - VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, - VK_IMAGE_TYPE_2D, - VK_FORMAT_R8_UINT, - {128, 128, 1}, - 1, - 1, - VK_SAMPLE_COUNT_1_BIT, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_SHARING_MODE_EXCLUSIVE, - 0, - nullptr, - VK_IMAGE_LAYOUT_UNDEFINED}; - VkImageObj mutImage(m_device); - mutImage.init(&mutImgInfo); - ASSERT_TRUE(mutImage.initialized()); - - VkImageView imgView; - VkImageViewCreateInfo imgViewInfo = {}; - imgViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - imgViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - imgViewInfo.format = VK_FORMAT_B8G8R8A8_UNORM; - imgViewInfo.subresourceRange.layerCount = 1; - imgViewInfo.subresourceRange.baseMipLevel = 0; - imgViewInfo.subresourceRange.levelCount = 1; - imgViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imgViewInfo.image = mutImage.handle(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-image-01018"); - vkCreateImageView(m_device->handle(), &imgViewInfo, NULL, &imgView); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, MultiplaneIncompatibleViewFormat) { - TEST_DESCRIPTION("Postive/negative tests of multiplane imageview format compatibility"); - - // Enable KHR multiplane req'd extensions - bool mp_extensions = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, - VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION); - if (mp_extensions) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - if (mp_extensions) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - } else { - printf("%s test requires KHR multiplane extensions, not available. Skipping.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkImageCreateInfo ci = {}; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; - ci.imageType = VK_IMAGE_TYPE_2D; - ci.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; - ci.tiling = VK_IMAGE_TILING_OPTIMAL; - ci.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - ci.extent = {128, 128, 1}; - ci.mipLevels = 1; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - // Verify format - VkFormatFeatureFlags features = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; - bool supported = ImageFormatAndFeaturesSupported(instance(), gpu(), ci, features); - if (!supported) { - printf("%s Multiplane image format not supported. Skipping test.\n", kSkipPrefix); - return; - } - - VkImageObj image_obj(m_device); - image_obj.init(&ci); - ASSERT_TRUE(image_obj.initialized()); - - VkImageViewCreateInfo ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.image = image_obj.image(); - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.format = VK_FORMAT_R8_SNORM; // Compat is VK_FORMAT_R8_UNORM - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - ivci.subresourceRange.levelCount = 1; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT; - - // Incompatible format error - VkImageView imageView = VK_NULL_HANDLE; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-image-01586"); - vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyFound(); - vkDestroyImageView(m_device->device(), imageView, NULL); // VK_NULL_HANDLE allowed - imageView = VK_NULL_HANDLE; - - // Correct format succeeds - ivci.format = VK_FORMAT_R8_UNORM; - m_errorMonitor->ExpectSuccess(); - vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyNotFound(); - vkDestroyImageView(m_device->device(), imageView, NULL); // VK_NULL_HANDLE allowed - imageView = VK_NULL_HANDLE; - - // Try a multiplane imageview - ivci.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - m_errorMonitor->ExpectSuccess(); - vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyNotFound(); - vkDestroyImageView(m_device->device(), imageView, NULL); // VK_NULL_HANDLE allowed -} - -TEST_F(VkLayerTest, CreateImageViewInvalidSubresourceRange) { - TEST_DESCRIPTION("Passing bad image subrange to CreateImageView"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkImageObj image(m_device); - image.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(image.create_info().arrayLayers == 1); - ASSERT_TRUE(image.initialized()); - - VkImageView img_view; - VkImageViewCreateInfo img_view_info_template = {}; - img_view_info_template.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - img_view_info_template.image = image.handle(); - img_view_info_template.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; - img_view_info_template.format = image.format(); - // subresourceRange to be filled later for the purposes of this test - img_view_info_template.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - img_view_info_template.subresourceRange.baseMipLevel = 0; - img_view_info_template.subresourceRange.levelCount = 0; - img_view_info_template.subresourceRange.baseArrayLayer = 0; - img_view_info_template.subresourceRange.layerCount = 0; - - // Try baseMipLevel >= image.mipLevels with VK_REMAINING_MIP_LEVELS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-subresourceRange-01478"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 1, VK_REMAINING_MIP_LEVELS, 0, 1}; - VkImageViewCreateInfo img_view_info = img_view_info_template; - img_view_info.subresourceRange = range; - vkCreateImageView(m_device->handle(), &img_view_info, nullptr, &img_view); - m_errorMonitor->VerifyFound(); - } - - // Try baseMipLevel >= image.mipLevels without VK_REMAINING_MIP_LEVELS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-subresourceRange-01478"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-subresourceRange-01718"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 0, 1}; - VkImageViewCreateInfo img_view_info = img_view_info_template; - img_view_info.subresourceRange = range; - vkCreateImageView(m_device->handle(), &img_view_info, nullptr, &img_view); - m_errorMonitor->VerifyFound(); - } - - // Try levelCount = 0 - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-subresourceRange-01718"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 0, 1}; - VkImageViewCreateInfo img_view_info = img_view_info_template; - img_view_info.subresourceRange = range; - vkCreateImageView(m_device->handle(), &img_view_info, nullptr, &img_view); - m_errorMonitor->VerifyFound(); - } - - // Try baseMipLevel + levelCount > image.mipLevels - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-subresourceRange-01718"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 2, 0, 1}; - VkImageViewCreateInfo img_view_info = img_view_info_template; - img_view_info.subresourceRange = range; - vkCreateImageView(m_device->handle(), &img_view_info, nullptr, &img_view); - m_errorMonitor->VerifyFound(); - } - - // These tests rely on having the Maintenance1 extension not being enabled, and are invalid on all but version 1.0 - if (m_device->props.apiVersion < VK_API_VERSION_1_1) { - // Try baseArrayLayer >= image.arrayLayers with VK_REMAINING_ARRAY_LAYERS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageViewCreateInfo-subresourceRange-01480"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 1, VK_REMAINING_ARRAY_LAYERS}; - VkImageViewCreateInfo img_view_info = img_view_info_template; - img_view_info.subresourceRange = range; - vkCreateImageView(m_device->handle(), &img_view_info, nullptr, &img_view); - m_errorMonitor->VerifyFound(); - } - - // Try baseArrayLayer >= image.arrayLayers without VK_REMAINING_ARRAY_LAYERS - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageViewCreateInfo-subresourceRange-01480"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageViewCreateInfo-subresourceRange-01719"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 1, 1}; - VkImageViewCreateInfo img_view_info = img_view_info_template; - img_view_info.subresourceRange = range; - vkCreateImageView(m_device->handle(), &img_view_info, nullptr, &img_view); - m_errorMonitor->VerifyFound(); - } - - // Try layerCount = 0 - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageViewCreateInfo-subresourceRange-01719"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 0}; - VkImageViewCreateInfo img_view_info = img_view_info_template; - img_view_info.subresourceRange = range; - vkCreateImageView(m_device->handle(), &img_view_info, nullptr, &img_view); - m_errorMonitor->VerifyFound(); - } - - // Try baseArrayLayer + layerCount > image.arrayLayers - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageViewCreateInfo-subresourceRange-01719"); - const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 2}; - VkImageViewCreateInfo img_view_info = img_view_info_template; - img_view_info.subresourceRange = range; - vkCreateImageView(m_device->handle(), &img_view_info, nullptr, &img_view); - m_errorMonitor->VerifyFound(); - } - } -} - -TEST_F(VkLayerTest, CompressedImageMipCopyTests) { - TEST_DESCRIPTION("Image/Buffer copies for higher mip levels"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkPhysicalDeviceFeatures device_features = {}; - ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features)); - VkFormat compressed_format = VK_FORMAT_UNDEFINED; - if (device_features.textureCompressionBC) { - compressed_format = VK_FORMAT_BC3_SRGB_BLOCK; - } else if (device_features.textureCompressionETC2) { - compressed_format = VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; - } else if (device_features.textureCompressionASTC_LDR) { - compressed_format = VK_FORMAT_ASTC_4x4_UNORM_BLOCK; - } else { - printf("%s No compressed formats supported - CompressedImageMipCopyTests skipped.\n", kSkipPrefix); - return; - } - - VkImageCreateInfo ci; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_2D; - ci.format = compressed_format; - ci.extent = {32, 32, 1}; - ci.mipLevels = 6; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.tiling = VK_IMAGE_TILING_OPTIMAL; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.queueFamilyIndexCount = 0; - ci.pQueueFamilyIndices = NULL; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkImageObj image(m_device); - image.init(&ci); - ASSERT_TRUE(image.initialized()); - - VkImageObj odd_image(m_device); - ci.extent = {31, 32, 1}; // Mips are [31,32] [15,16] [7,8] [3,4], [1,2] [1,1] - odd_image.init(&ci); - ASSERT_TRUE(odd_image.initialized()); - - // Allocate buffers - VkMemoryPropertyFlags reqs = 0; - VkBufferObj buffer_1024, buffer_64, buffer_16, buffer_8; - buffer_1024.init_as_src_and_dst(*m_device, 1024, reqs); - buffer_64.init_as_src_and_dst(*m_device, 64, reqs); - buffer_16.init_as_src_and_dst(*m_device, 16, reqs); - buffer_8.init_as_src_and_dst(*m_device, 8, reqs); - - VkBufferImageCopy region = {}; - region.bufferRowLength = 0; - region.bufferImageHeight = 0; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.layerCount = 1; - region.imageOffset = {0, 0, 0}; - region.bufferOffset = 0; - - // start recording - m_commandBuffer->begin(); - - // Mip level copies that work - 5 levels - m_errorMonitor->ExpectSuccess(); - - // Mip 0 should fit in 1k buffer - 1k texels @ 1b each - region.imageExtent = {32, 32, 1}; - region.imageSubresource.mipLevel = 0; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_1024.handle(), 1, ®ion); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_1024.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - - // Mip 2 should fit in 64b buffer - 64 texels @ 1b each - region.imageExtent = {8, 8, 1}; - region.imageSubresource.mipLevel = 2; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_64.handle(), 1, ®ion); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_64.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - - // Mip 3 should fit in 16b buffer - 16 texels @ 1b each - region.imageExtent = {4, 4, 1}; - region.imageSubresource.mipLevel = 3; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, ®ion); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_16.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - - // Mip 4&5 should fit in 16b buffer with no complaint - 4 & 1 texels @ 1b each - region.imageExtent = {2, 2, 1}; - region.imageSubresource.mipLevel = 4; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, ®ion); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_16.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - - region.imageExtent = {1, 1, 1}; - region.imageSubresource.mipLevel = 5; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, ®ion); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_16.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - m_errorMonitor->VerifyNotFound(); - - // Buffer must accommodate a full compressed block, regardless of texel count - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImageToBuffer-pRegions-00183"); - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_8.handle(), 1, ®ion); - m_errorMonitor->VerifyFound(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyBufferToImage-pRegions-00171"); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_8.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - m_errorMonitor->VerifyFound(); - - // Copy width < compressed block size, but not the full mip width - region.imageExtent = {1, 2, 1}; - region.imageSubresource.mipLevel = 4; - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkBufferImageCopy-imageExtent-00207"); // width not a multiple of compressed block width - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImageToBuffer-imageOffset-01794"); // image transfer granularity - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, ®ion); - m_errorMonitor->VerifyFound(); - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkBufferImageCopy-imageExtent-00207"); // width not a multiple of compressed block width - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyBufferToImage-imageOffset-01793"); // image transfer granularity - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_16.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - m_errorMonitor->VerifyFound(); - - // Copy height < compressed block size but not the full mip height - region.imageExtent = {2, 1, 1}; - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkBufferImageCopy-imageExtent-00208"); // height not a multiple of compressed block width - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImageToBuffer-imageOffset-01794"); // image transfer granularity - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, ®ion); - m_errorMonitor->VerifyFound(); - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkBufferImageCopy-imageExtent-00208"); // height not a multiple of compressed block width - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyBufferToImage-imageOffset-01793"); // image transfer granularity - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_16.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - m_errorMonitor->VerifyFound(); - - // Offsets must be multiple of compressed block size - region.imageOffset = {1, 1, 0}; - region.imageExtent = {1, 1, 1}; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkBufferImageCopy-imageOffset-00205"); // imageOffset not a multiple of block size - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImageToBuffer-imageOffset-01794"); // image transfer granularity - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, ®ion); - m_errorMonitor->VerifyFound(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkBufferImageCopy-imageOffset-00205"); // imageOffset not a multiple of block size - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyBufferToImage-imageOffset-01793"); // image transfer granularity - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_16.handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - m_errorMonitor->VerifyFound(); - - // Offset + extent width = mip width - should succeed - region.imageOffset = {4, 4, 0}; - region.imageExtent = {3, 4, 1}; - region.imageSubresource.mipLevel = 2; - m_errorMonitor->ExpectSuccess(); - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), odd_image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, ®ion); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_16.handle(), odd_image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - m_errorMonitor->VerifyNotFound(); - - // Offset + extent width > mip width, but still within the final compressed block - should succeed - region.imageExtent = {4, 4, 1}; - m_errorMonitor->ExpectSuccess(); - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), odd_image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, ®ion); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_16.handle(), odd_image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - m_errorMonitor->VerifyNotFound(); - - // Offset + extent width < mip width and not a multiple of block width - should fail - region.imageExtent = {3, 3, 1}; - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkBufferImageCopy-imageExtent-00208"); // offset+extent not a multiple of block width - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImageToBuffer-imageOffset-01794"); // image transfer granularity - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), odd_image.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16.handle(), 1, ®ion); - m_errorMonitor->VerifyFound(); - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkBufferImageCopy-imageExtent-00208"); // offset+extent not a multiple of block width - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyBufferToImage-imageOffset-01793"); // image transfer granularity - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_16.handle(), odd_image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, ImageBufferCopyTests) { - TEST_DESCRIPTION("Image to buffer and buffer to image tests"); - ASSERT_NO_FATAL_FAILURE(Init()); - - // Bail if any dimension of transfer granularity is 0. - auto index = m_device->graphics_queue_node_index_; - auto queue_family_properties = m_device->phy().queue_properties(); - if ((queue_family_properties[index].minImageTransferGranularity.depth == 0) || - (queue_family_properties[index].minImageTransferGranularity.width == 0) || - (queue_family_properties[index].minImageTransferGranularity.height == 0)) { - printf("%s Subresource copies are disallowed when xfer granularity (x|y|z) is 0. Skipped.\n", kSkipPrefix); - return; - } - - VkImageObj image_64k(m_device); // 128^2 texels, 64k - VkImageObj image_16k(m_device); // 64^2 texels, 16k - VkImageObj image_16k_depth(m_device); // 64^2 texels, depth, 16k - VkImageObj ds_image_4D_1S(m_device); // 256^2 texels, 512kb (256k depth, 64k stencil, 192k pack) - VkImageObj ds_image_3D_1S(m_device); // 256^2 texels, 256kb (192k depth, 64k stencil) - VkImageObj ds_image_2D(m_device); // 256^2 texels, 128k (128k depth) - VkImageObj ds_image_1S(m_device); // 256^2 texels, 64k (64k stencil) - - image_64k.Init(128, 128, 1, VK_FORMAT_R8G8B8A8_UINT, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - image_16k.Init(64, 64, 1, VK_FORMAT_R8G8B8A8_UINT, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image_64k.initialized()); - ASSERT_TRUE(image_16k.initialized()); - - // Verify all needed Depth/Stencil formats are supported - bool missing_ds_support = false; - VkFormatProperties props = {0, 0, 0}; - vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), VK_FORMAT_D32_SFLOAT_S8_UINT, &props); - missing_ds_support |= (props.bufferFeatures == 0 && props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0); - missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0; - missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0; - vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), VK_FORMAT_D24_UNORM_S8_UINT, &props); - missing_ds_support |= (props.bufferFeatures == 0 && props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0); - missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0; - missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0; - vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), VK_FORMAT_D16_UNORM, &props); - missing_ds_support |= (props.bufferFeatures == 0 && props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0); - missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0; - missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0; - vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), VK_FORMAT_S8_UINT, &props); - missing_ds_support |= (props.bufferFeatures == 0 && props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0); - missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0; - missing_ds_support |= (props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0; - - if (!missing_ds_support) { - image_16k_depth.Init(64, 64, 1, VK_FORMAT_D24_UNORM_S8_UINT, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image_16k_depth.initialized()); - - ds_image_4D_1S.Init( - 256, 256, 1, VK_FORMAT_D32_SFLOAT_S8_UINT, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(ds_image_4D_1S.initialized()); - - ds_image_3D_1S.Init( - 256, 256, 1, VK_FORMAT_D24_UNORM_S8_UINT, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(ds_image_3D_1S.initialized()); - - ds_image_2D.Init( - 256, 256, 1, VK_FORMAT_D16_UNORM, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(ds_image_2D.initialized()); - - ds_image_1S.Init( - 256, 256, 1, VK_FORMAT_S8_UINT, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(ds_image_1S.initialized()); - } - - // Allocate buffers - VkBufferObj buffer_256k, buffer_128k, buffer_64k, buffer_16k; - VkMemoryPropertyFlags reqs = 0; - buffer_256k.init_as_src_and_dst(*m_device, 262144, reqs); // 256k - buffer_128k.init_as_src_and_dst(*m_device, 131072, reqs); // 128k - buffer_64k.init_as_src_and_dst(*m_device, 65536, reqs); // 64k - buffer_16k.init_as_src_and_dst(*m_device, 16384, reqs); // 16k - - VkBufferImageCopy region = {}; - region.bufferRowLength = 0; - region.bufferImageHeight = 0; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.layerCount = 1; - region.imageOffset = {0, 0, 0}; - region.imageExtent = {64, 64, 1}; - region.bufferOffset = 0; - - // attempt copies before putting command buffer in recording state - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyBufferToImage-commandBuffer-recording"); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_64k.handle(), image_64k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImageToBuffer-commandBuffer-recording"); - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_64k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_64k.handle(), 1, ®ion); - m_errorMonitor->VerifyFound(); - - // start recording - m_commandBuffer->begin(); - - // successful copies - m_errorMonitor->ExpectSuccess(); - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, ®ion); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_16k.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - region.imageOffset.x = 16; // 16k copy, offset requires larger image - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_64k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, ®ion); - region.imageExtent.height = 78; // > 16k copy requires larger buffer & image - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_64k.handle(), image_64k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - region.imageOffset.x = 0; - region.imageExtent.height = 64; - region.bufferOffset = 256; // 16k copy with buffer offset, requires larger buffer - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_64k.handle(), 1, ®ion); - m_errorMonitor->VerifyNotFound(); - - // image/buffer too small (extent too large) on copy to image - region.imageExtent = {65, 64, 1}; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyBufferToImage-pRegions-00171"); // buffer too small - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_16k.handle(), image_64k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyBufferToImage-pRegions-00172"); // image too small - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_64k.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - m_errorMonitor->VerifyFound(); - - // image/buffer too small (offset) on copy to image - region.imageExtent = {64, 64, 1}; - region.imageOffset = {0, 4, 0}; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyBufferToImage-pRegions-00171"); // buffer too small - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_16k.handle(), image_64k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyBufferToImage-pRegions-00172"); // image too small - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_64k.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - m_errorMonitor->VerifyFound(); - - // image/buffer too small on copy to buffer - region.imageExtent = {64, 64, 1}; - region.imageOffset = {0, 0, 0}; - region.bufferOffset = 4; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImageToBuffer-pRegions-00183"); // buffer too small - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_64k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, ®ion); - m_errorMonitor->VerifyFound(); - - region.imageExtent = {64, 65, 1}; - region.bufferOffset = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImageToBuffer-pRegions-00182"); // image too small - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_64k.handle(), 1, ®ion); - m_errorMonitor->VerifyFound(); - - // buffer size OK but rowlength causes loose packing - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImageToBuffer-pRegions-00183"); - region.imageExtent = {64, 64, 1}; - region.bufferRowLength = 68; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, ®ion); - m_errorMonitor->VerifyFound(); - - // An extent with zero area should produce a warning, but no error - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_ERROR_BIT_EXT, "} has zero area"); - region.imageExtent.width = 0; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, ®ion); - m_errorMonitor->VerifyFound(); - - // aspect bits - region.imageExtent = {64, 64, 1}; - region.bufferRowLength = 0; - region.bufferImageHeight = 0; - if (!missing_ds_support) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkBufferImageCopy-aspectMask-00212"); // more than 1 aspect bit set - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_16k_depth.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, - ®ion); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkBufferImageCopy-aspectMask-00211"); // different mis-matched aspect - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_16k_depth.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, - ®ion); - m_errorMonitor->VerifyFound(); - } - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkBufferImageCopy-aspectMask-00211"); // mis-matched aspect - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, ®ion); - m_errorMonitor->VerifyFound(); - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - // Out-of-range mip levels should fail - region.imageSubresource.mipLevel = image_16k.create_info().mipLevels + 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImageToBuffer-imageSubresource-01703"); - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImageToBuffer-pRegions-00182"); // unavoidable "region exceeds image bounds" for non-existent mip - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, ®ion); - m_errorMonitor->VerifyFound(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyBufferToImage-imageSubresource-01701"); - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyBufferToImage-pRegions-00172"); // unavoidable "region exceeds image bounds" for non-existent mip - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_16k.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - m_errorMonitor->VerifyFound(); - region.imageSubresource.mipLevel = 0; - - // Out-of-range array layers should fail - region.imageSubresource.baseArrayLayer = image_16k.create_info().arrayLayers; - region.imageSubresource.layerCount = 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImageToBuffer-imageSubresource-01704"); - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), 1, ®ion); - m_errorMonitor->VerifyFound(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyBufferToImage-imageSubresource-01702"); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_16k.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - m_errorMonitor->VerifyFound(); - region.imageSubresource.baseArrayLayer = 0; - - // Layout mismatch should fail - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImageToBuffer-srcImageLayout-00189"); - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_16k.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer_16k.handle(), - 1, ®ion); - m_errorMonitor->VerifyFound(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyBufferToImage-dstImageLayout-00180"); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer_16k.handle(), image_16k.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, ®ion); - m_errorMonitor->VerifyFound(); - - // Test Depth/Stencil copies - if (missing_ds_support) { - printf("%s Depth / Stencil formats unsupported - skipping D/S tests.\n", kSkipPrefix); - } else { - VkBufferImageCopy ds_region = {}; - ds_region.bufferOffset = 0; - ds_region.bufferRowLength = 0; - ds_region.bufferImageHeight = 0; - ds_region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - ds_region.imageSubresource.mipLevel = 0; - ds_region.imageSubresource.baseArrayLayer = 0; - ds_region.imageSubresource.layerCount = 1; - ds_region.imageOffset = {0, 0, 0}; - ds_region.imageExtent = {256, 256, 1}; - - // Depth copies that should succeed - m_errorMonitor->ExpectSuccess(); // Extract 4b depth per texel, pack into 256k buffer - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), ds_image_4D_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - buffer_256k.handle(), 1, &ds_region); - m_errorMonitor->VerifyNotFound(); - - m_errorMonitor->ExpectSuccess(); // Extract 3b depth per texel, pack (loose) into 256k buffer - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), ds_image_3D_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - buffer_256k.handle(), 1, &ds_region); - m_errorMonitor->VerifyNotFound(); - - m_errorMonitor->ExpectSuccess(); // Copy 2b depth per texel, into 128k buffer - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), ds_image_2D.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - buffer_128k.handle(), 1, &ds_region); - m_errorMonitor->VerifyNotFound(); - - // Depth copies that should fail - ds_region.bufferOffset = 4; - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImageToBuffer-pRegions-00183"); // Extract 4b depth per texel, pack into 256k buffer - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), ds_image_4D_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - buffer_256k.handle(), 1, &ds_region); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImageToBuffer-pRegions-00183"); // Extract 3b depth per texel, pack (loose) into 256k buffer - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), ds_image_3D_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - buffer_256k.handle(), 1, &ds_region); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImageToBuffer-pRegions-00183"); // Copy 2b depth per texel, into 128k buffer - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), ds_image_2D.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - buffer_128k.handle(), 1, &ds_region); - m_errorMonitor->VerifyFound(); - - // Stencil copies that should succeed - ds_region.bufferOffset = 0; - ds_region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; - m_errorMonitor->ExpectSuccess(); // Extract 1b stencil per texel, pack into 64k buffer - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), ds_image_4D_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - buffer_64k.handle(), 1, &ds_region); - m_errorMonitor->VerifyNotFound(); - - m_errorMonitor->ExpectSuccess(); // Extract 1b stencil per texel, pack into 64k buffer - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), ds_image_3D_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - buffer_64k.handle(), 1, &ds_region); - m_errorMonitor->VerifyNotFound(); - - m_errorMonitor->ExpectSuccess(); // Copy 1b depth per texel, into 64k buffer - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), ds_image_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - buffer_64k.handle(), 1, &ds_region); - m_errorMonitor->VerifyNotFound(); - - // Stencil copies that should fail - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImageToBuffer-pRegions-00183"); // Extract 1b stencil per texel, pack into 64k buffer - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), ds_image_4D_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - buffer_16k.handle(), 1, &ds_region); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImageToBuffer-pRegions-00183"); // Extract 1b stencil per texel, pack into 64k buffer - ds_region.bufferRowLength = 260; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), ds_image_3D_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - buffer_64k.handle(), 1, &ds_region); - m_errorMonitor->VerifyFound(); - - ds_region.bufferRowLength = 0; - ds_region.bufferOffset = 4; - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImageToBuffer-pRegions-00183"); // Copy 1b depth per texel, into 64k buffer - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), ds_image_1S.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - buffer_64k.handle(), 1, &ds_region); - m_errorMonitor->VerifyFound(); - } - - // Test compressed formats, if supported - VkPhysicalDeviceFeatures device_features = {}; - ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features)); - if (!(device_features.textureCompressionBC || device_features.textureCompressionETC2 || - device_features.textureCompressionASTC_LDR)) { - printf("%s No compressed formats supported - block compression tests skipped.\n", kSkipPrefix); - } else { - VkImageObj image_16k_4x4comp(m_device); // 128^2 texels as 32^2 compressed (4x4) blocks, 16k - VkImageObj image_NPOT_4x4comp(m_device); // 130^2 texels as 33^2 compressed (4x4) blocks - if (device_features.textureCompressionBC) { - image_16k_4x4comp.Init(128, 128, 1, VK_FORMAT_BC3_SRGB_BLOCK, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_OPTIMAL, - 0); - image_NPOT_4x4comp.Init(130, 130, 1, VK_FORMAT_BC3_SRGB_BLOCK, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_OPTIMAL, - 0); - } else if (device_features.textureCompressionETC2) { - image_16k_4x4comp.Init(128, 128, 1, VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - image_NPOT_4x4comp.Init(130, 130, 1, VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - } else { - image_16k_4x4comp.Init(128, 128, 1, VK_FORMAT_ASTC_4x4_UNORM_BLOCK, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - image_NPOT_4x4comp.Init(130, 130, 1, VK_FORMAT_ASTC_4x4_UNORM_BLOCK, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - } - ASSERT_TRUE(image_16k_4x4comp.initialized()); - - // Just fits - m_errorMonitor->ExpectSuccess(); - region.imageExtent = {128, 128, 1}; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_16k_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), - 1, ®ion); - m_errorMonitor->VerifyNotFound(); - - // with offset, too big for buffer - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImageToBuffer-pRegions-00183"); - region.bufferOffset = 16; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_16k_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), - 1, ®ion); - m_errorMonitor->VerifyFound(); - region.bufferOffset = 0; - - // extents that are not a multiple of compressed block size - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkBufferImageCopy-imageExtent-00207"); // extent width not a multiple of block size - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImageToBuffer-imageOffset-01794"); // image transfer granularity - region.imageExtent.width = 66; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_NPOT_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), - 1, ®ion); - m_errorMonitor->VerifyFound(); - region.imageExtent.width = 128; - - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkBufferImageCopy-imageExtent-00208"); // extent height not a multiple of block size - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImageToBuffer-imageOffset-01794"); // image transfer granularity - region.imageExtent.height = 2; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_NPOT_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), - 1, ®ion); - m_errorMonitor->VerifyFound(); - region.imageExtent.height = 128; - - // TODO: All available compressed formats are 2D, with block depth of 1. Unable to provoke VU_01277. - - // non-multiple extents are allowed if at the far edge of a non-block-multiple image - these should pass - m_errorMonitor->ExpectSuccess(); - region.imageExtent.width = 66; - region.imageOffset.x = 64; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_NPOT_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), - 1, ®ion); - region.imageExtent.width = 16; - region.imageOffset.x = 0; - region.imageExtent.height = 2; - region.imageOffset.y = 128; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_NPOT_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), - 1, ®ion); - m_errorMonitor->VerifyNotFound(); - region.imageOffset = {0, 0, 0}; - - // buffer offset must be a multiple of texel block size (16) - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferImageCopy-bufferOffset-00206"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferImageCopy-bufferOffset-00193"); - region.imageExtent = {64, 64, 1}; - region.bufferOffset = 24; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_16k_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_16k.handle(), - 1, ®ion); - m_errorMonitor->VerifyFound(); - - // rowlength not a multiple of block width (4) - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferImageCopy-bufferRowLength-00203"); - region.bufferOffset = 0; - region.bufferRowLength = 130; - region.bufferImageHeight = 0; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_16k_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_64k.handle(), - 1, ®ion); - m_errorMonitor->VerifyFound(); - - // imageheight not a multiple of block height (4) - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferImageCopy-bufferImageHeight-00204"); - region.bufferRowLength = 0; - region.bufferImageHeight = 130; - vkCmdCopyImageToBuffer(m_commandBuffer->handle(), image_16k_4x4comp.handle(), VK_IMAGE_LAYOUT_GENERAL, buffer_64k.handle(), - 1, ®ion); - m_errorMonitor->VerifyFound(); - } -} - -TEST_F(VkLayerTest, MiscImageLayerTests) { - TEST_DESCRIPTION("Image-related tests that don't belong elsewhere"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // TODO: Ideally we should check if a format is supported, before using it. - VkImageObj image(m_device); - image.Init(128, 128, 1, VK_FORMAT_R16G16B16A16_UINT, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL, 0); // 64bpp - ASSERT_TRUE(image.initialized()); - VkBufferObj buffer; - VkMemoryPropertyFlags reqs = 0; - buffer.init_as_src(*m_device, 128 * 128 * 8, reqs); - VkBufferImageCopy region = {}; - region.bufferRowLength = 128; - region.bufferImageHeight = 128; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - // layerCount can't be 0 - Expect MISMATCHED_IMAGE_ASPECT - region.imageSubresource.layerCount = 1; - region.imageExtent.height = 4; - region.imageExtent.width = 4; - region.imageExtent.depth = 1; - - VkImageObj image2(m_device); - image2.Init(128, 128, 1, VK_FORMAT_R8G8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL, 0); // 16bpp - ASSERT_TRUE(image2.initialized()); - VkBufferObj buffer2; - VkMemoryPropertyFlags reqs2 = 0; - buffer2.init_as_src(*m_device, 128 * 128 * 2, reqs2); - VkBufferImageCopy region2 = {}; - region2.bufferRowLength = 128; - region2.bufferImageHeight = 128; - region2.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - // layerCount can't be 0 - Expect MISMATCHED_IMAGE_ASPECT - region2.imageSubresource.layerCount = 1; - region2.imageExtent.height = 4; - region2.imageExtent.width = 4; - region2.imageExtent.depth = 1; - m_commandBuffer->begin(); - - // Image must have offset.z of 0 and extent.depth of 1 - // Introduce failure by setting imageExtent.depth to 0 - region.imageExtent.depth = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferImageCopy-srcImage-00201"); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, - ®ion); - m_errorMonitor->VerifyFound(); - - region.imageExtent.depth = 1; - - // Image must have offset.z of 0 and extent.depth of 1 - // Introduce failure by setting imageOffset.z to 4 - // Note: Also (unavoidably) triggers 'region exceeds image' #1228 - region.imageOffset.z = 4; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferImageCopy-srcImage-00201"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyBufferToImage-pRegions-00172"); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, - ®ion); - m_errorMonitor->VerifyFound(); - - region.imageOffset.z = 0; - // BufferOffset must be a multiple of the calling command's VkImage parameter's texel size - // Introduce failure by setting bufferOffset to 1 and 1/2 texels - region.bufferOffset = 4; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferImageCopy-bufferOffset-00193"); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, - ®ion); - m_errorMonitor->VerifyFound(); - - // BufferOffset must be a multiple of 4 - // Introduce failure by setting bufferOffset to a value not divisible by 4 - region2.bufferOffset = 6; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferImageCopy-bufferOffset-00194"); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer2.handle(), image2.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, - ®ion2); - m_errorMonitor->VerifyFound(); - - // BufferRowLength must be 0, or greater than or equal to the width member of imageExtent - region.bufferOffset = 0; - region.imageExtent.height = 128; - region.imageExtent.width = 128; - // Introduce failure by setting bufferRowLength > 0 but less than width - region.bufferRowLength = 64; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferImageCopy-bufferRowLength-00195"); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, - ®ion); - m_errorMonitor->VerifyFound(); - - // BufferImageHeight must be 0, or greater than or equal to the height member of imageExtent - region.bufferRowLength = 128; - // Introduce failure by setting bufferRowHeight > 0 but less than height - region.bufferImageHeight = 64; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferImageCopy-bufferImageHeight-00196"); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, - ®ion); - m_errorMonitor->VerifyFound(); - - region.bufferImageHeight = 128; - VkImageObj intImage1(m_device); - intImage1.Init(128, 128, 1, VK_FORMAT_R8_UNORM, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - intImage1.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL); - VkImageObj intImage2(m_device); - intImage2.Init(128, 128, 1, VK_FORMAT_R8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - intImage2.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL); - VkImageBlit blitRegion = {}; - blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blitRegion.srcSubresource.baseArrayLayer = 0; - blitRegion.srcSubresource.layerCount = 1; - blitRegion.srcSubresource.mipLevel = 0; - blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blitRegion.dstSubresource.baseArrayLayer = 0; - blitRegion.dstSubresource.layerCount = 1; - blitRegion.dstSubresource.mipLevel = 0; - blitRegion.srcOffsets[0] = {128, 0, 0}; - blitRegion.srcOffsets[1] = {128, 128, 1}; - blitRegion.dstOffsets[0] = {0, 128, 0}; - blitRegion.dstOffsets[1] = {128, 128, 1}; - - // Look for NULL-blit warning - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, - "vkCmdBlitImage(): pRegions[0].srcOffsets specify a zero-volume area."); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, - "vkCmdBlitImage(): pRegions[0].dstOffsets specify a zero-volume area."); - vkCmdBlitImage(m_commandBuffer->handle(), intImage1.handle(), intImage1.Layout(), intImage2.handle(), intImage2.Layout(), 1, - &blitRegion, VK_FILTER_LINEAR); - m_errorMonitor->VerifyFound(); -} - -VkResult GPDIFPHelper(VkPhysicalDevice dev, const VkImageCreateInfo *ci, VkImageFormatProperties *limits = nullptr) { - VkImageFormatProperties tmp_limits; - limits = limits ? limits : &tmp_limits; - return vkGetPhysicalDeviceImageFormatProperties(dev, ci->format, ci->imageType, ci->tiling, ci->usage, ci->flags, limits); -} - -TEST_F(VkLayerTest, CreateImageMiscErrors) { - TEST_DESCRIPTION("Misc leftover valid usage errors in VkImageCreateInfo struct"); - - VkPhysicalDeviceFeatures features{}; - ASSERT_NO_FATAL_FAILURE(Init(&features)); - - VkImage null_image; // throwaway target for all the vkCreateImage - - VkImageCreateInfo tmp_img_ci = {}; - tmp_img_ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - tmp_img_ci.flags = 0; // assumably any is supported - tmp_img_ci.imageType = VK_IMAGE_TYPE_2D; // any is supported - tmp_img_ci.format = VK_FORMAT_R8G8B8A8_UNORM; // has mandatory support for all usages - tmp_img_ci.extent = {64, 64, 1}; // limit is 256 for 3D, or 4096 - tmp_img_ci.mipLevels = 1; // any is supported - tmp_img_ci.arrayLayers = 1; // limit is 256 - tmp_img_ci.samples = VK_SAMPLE_COUNT_1_BIT; // needs to be 1 if TILING_LINEAR - // if VK_IMAGE_TILING_LINEAR imageType must be 2D, usage must be TRANSFER, and levels layers samplers all 1 - tmp_img_ci.tiling = VK_IMAGE_TILING_OPTIMAL; - tmp_img_ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; // depends on format - tmp_img_ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - const VkImageCreateInfo safe_image_ci = tmp_img_ci; - - ASSERT_VK_SUCCESS(GPDIFPHelper(gpu(), &safe_image_ci)); - - { - VkImageCreateInfo image_ci = safe_image_ci; - image_ci.sharingMode = VK_SHARING_MODE_CONCURRENT; - image_ci.queueFamilyIndexCount = 2; - image_ci.pQueueFamilyIndices = nullptr; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-sharingMode-00941"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } - - { - VkImageCreateInfo image_ci = safe_image_ci; - image_ci.sharingMode = VK_SHARING_MODE_CONCURRENT; - image_ci.queueFamilyIndexCount = 1; - const uint32_t queue_family = 0; - image_ci.pQueueFamilyIndices = &queue_family; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-sharingMode-00942"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } - - { - VkImageCreateInfo image_ci = safe_image_ci; - image_ci.format = VK_FORMAT_UNDEFINED; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-format-00943"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } - - { - VkImageCreateInfo image_ci = safe_image_ci; - image_ci.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - image_ci.arrayLayers = 6; - image_ci.imageType = VK_IMAGE_TYPE_1D; - image_ci.extent = {64, 1, 1}; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-flags-00949"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - - image_ci = safe_image_ci; - image_ci.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - image_ci.imageType = VK_IMAGE_TYPE_3D; - image_ci.extent = {4, 4, 4}; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-flags-00949"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } - - { - VkImageCreateInfo image_ci = safe_image_ci; - image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; // always has 4 samples support - image_ci.samples = VK_SAMPLE_COUNT_4_BIT; - image_ci.imageType = VK_IMAGE_TYPE_3D; - image_ci.extent = {4, 4, 4}; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-samples-02257"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - - image_ci = safe_image_ci; - image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; // always has 4 samples support - image_ci.samples = VK_SAMPLE_COUNT_4_BIT; - image_ci.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - image_ci.arrayLayers = 6; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-samples-02257"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - - image_ci = safe_image_ci; - image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; // always has 4 samples support - image_ci.samples = VK_SAMPLE_COUNT_4_BIT; - image_ci.tiling = VK_IMAGE_TILING_LINEAR; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-samples-02257"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - - image_ci = safe_image_ci; - image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; // always has 4 samples support - image_ci.samples = VK_SAMPLE_COUNT_4_BIT; - image_ci.mipLevels = 2; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-samples-02257"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } - - { - VkImageCreateInfo image_ci = safe_image_ci; - image_ci.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - image_ci.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-usage-00963"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - - image_ci.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-usage-00966"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - - image_ci.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT; - image_ci.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-usage-00963"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-usage-00966"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } - - { - VkImageCreateInfo image_ci = safe_image_ci; - image_ci.flags = VK_IMAGE_CREATE_SPARSE_BINDING_BIT; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-flags-00969"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } - - // InitialLayout not VK_IMAGE_LAYOUT_UNDEFINED or VK_IMAGE_LAYOUT_PREDEFINED - { - VkImageCreateInfo image_ci = safe_image_ci; - image_ci.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-initialLayout-00993"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } -} - -TEST_F(VkLayerTest, CreateImageMinLimitsViolation) { - TEST_DESCRIPTION("Create invalid image with invalid parameters violation minimum limit, such as being zero."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkImage null_image; // throwaway target for all the vkCreateImage - - VkImageCreateInfo tmp_img_ci = {}; - tmp_img_ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - tmp_img_ci.flags = 0; // assumably any is supported - tmp_img_ci.imageType = VK_IMAGE_TYPE_2D; // any is supported - tmp_img_ci.format = VK_FORMAT_R8G8B8A8_UNORM; // has mandatory support for all usages - tmp_img_ci.extent = {1, 1, 1}; // limit is 256 for 3D, or 4096 - tmp_img_ci.mipLevels = 1; // any is supported - tmp_img_ci.arrayLayers = 1; // limit is 256 - tmp_img_ci.samples = VK_SAMPLE_COUNT_1_BIT; // needs to be 1 if TILING_LINEAR - // if VK_IMAGE_TILING_LINEAR imageType must be 2D, usage must be TRANSFER, and levels layers samplers all 1 - tmp_img_ci.tiling = VK_IMAGE_TILING_OPTIMAL; - tmp_img_ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; // depends on format - tmp_img_ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - const VkImageCreateInfo safe_image_ci = tmp_img_ci; - - enum Dimension { kWidth = 0x1, kHeight = 0x2, kDepth = 0x4 }; - - for (underlying_type<Dimension>::type bad_dimensions = 0x1; bad_dimensions < 0x8; ++bad_dimensions) { - VkExtent3D extent = {1, 1, 1}; - - if (bad_dimensions & kWidth) { - extent.width = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-extent-00944"); - } - - if (bad_dimensions & kHeight) { - extent.height = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-extent-00945"); - } - - if (bad_dimensions & kDepth) { - extent.depth = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-extent-00946"); - } - - VkImageCreateInfo bad_image_ci = safe_image_ci; - bad_image_ci.imageType = VK_IMAGE_TYPE_3D; // has to be 3D otherwise it might trigger the non-1 error instead - bad_image_ci.extent = extent; - - vkCreateImage(m_device->device(), &bad_image_ci, NULL, &null_image); - - m_errorMonitor->VerifyFound(); - } - - { - VkImageCreateInfo bad_image_ci = safe_image_ci; - bad_image_ci.mipLevels = 0; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-mipLevels-00947"); - vkCreateImage(m_device->device(), &bad_image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } - - { - VkImageCreateInfo bad_image_ci = safe_image_ci; - bad_image_ci.arrayLayers = 0; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-arrayLayers-00948"); - vkCreateImage(m_device->device(), &bad_image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } - - { - VkImageCreateInfo bad_image_ci = safe_image_ci; - bad_image_ci.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - bad_image_ci.arrayLayers = 5; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-imageType-00954"); - vkCreateImage(m_device->device(), &bad_image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - - bad_image_ci.arrayLayers = 6; - bad_image_ci.extent = {64, 63, 1}; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-imageType-00954"); - vkCreateImage(m_device->device(), &bad_image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } - - { - VkImageCreateInfo bad_image_ci = safe_image_ci; - bad_image_ci.imageType = VK_IMAGE_TYPE_1D; - bad_image_ci.extent = {64, 2, 1}; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-imageType-00956"); - vkCreateImage(m_device->device(), &bad_image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - - bad_image_ci.imageType = VK_IMAGE_TYPE_1D; - bad_image_ci.extent = {64, 1, 2}; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-imageType-00956"); - vkCreateImage(m_device->device(), &bad_image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - - bad_image_ci.imageType = VK_IMAGE_TYPE_2D; - bad_image_ci.extent = {64, 64, 2}; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-imageType-00957"); - vkCreateImage(m_device->device(), &bad_image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - - bad_image_ci.imageType = VK_IMAGE_TYPE_2D; - bad_image_ci.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - bad_image_ci.arrayLayers = 6; - bad_image_ci.extent = {64, 64, 2}; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-imageType-00957"); - vkCreateImage(m_device->device(), &bad_image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } - - { - VkImageCreateInfo bad_image_ci = safe_image_ci; - bad_image_ci.imageType = VK_IMAGE_TYPE_3D; - bad_image_ci.arrayLayers = 2; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-imageType-00961"); - vkCreateImage(m_device->device(), &bad_image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } -} - -VkFormat FindFormatLinearWithoutMips(VkPhysicalDevice gpu, VkImageCreateInfo image_ci) { - image_ci.tiling = VK_IMAGE_TILING_LINEAR; - - const VkFormat first_vk_format = static_cast<VkFormat>(1); - const VkFormat last_vk_format = static_cast<VkFormat>(130); // avoid compressed/feature protected, otherwise 184 - - for (VkFormat format = first_vk_format; format <= last_vk_format; format = static_cast<VkFormat>(format + 1)) { - image_ci.format = format; - - // WORKAROUND for dev_sim and mock_icd not containing valid format limits yet - VkFormatProperties format_props; - vkGetPhysicalDeviceFormatProperties(gpu, format, &format_props); - const VkFormatFeatureFlags core_filter = 0x1FFF; - const auto features = (image_ci.tiling == VK_IMAGE_TILING_LINEAR) ? format_props.linearTilingFeatures & core_filter - : format_props.optimalTilingFeatures & core_filter; - if (!(features & core_filter)) continue; - - VkImageFormatProperties img_limits; - if (VK_SUCCESS == GPDIFPHelper(gpu, &image_ci, &img_limits) && img_limits.maxMipLevels == 1) return format; - } - - return VK_FORMAT_UNDEFINED; -} - -bool FindFormatWithoutSamples(VkPhysicalDevice gpu, VkImageCreateInfo &image_ci) { - const VkFormat first_vk_format = static_cast<VkFormat>(1); - const VkFormat last_vk_format = static_cast<VkFormat>(130); // avoid compressed/feature protected, otherwise 184 - - for (VkFormat format = first_vk_format; format <= last_vk_format; format = static_cast<VkFormat>(format + 1)) { - image_ci.format = format; - - // WORKAROUND for dev_sim and mock_icd not containing valid format limits yet - VkFormatProperties format_props; - vkGetPhysicalDeviceFormatProperties(gpu, format, &format_props); - const VkFormatFeatureFlags core_filter = 0x1FFF; - const auto features = (image_ci.tiling == VK_IMAGE_TILING_LINEAR) ? format_props.linearTilingFeatures & core_filter - : format_props.optimalTilingFeatures & core_filter; - if (!(features & core_filter)) continue; - - for (VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_64_BIT; samples > 0; - samples = static_cast<VkSampleCountFlagBits>(samples >> 1)) { - image_ci.samples = samples; - VkImageFormatProperties img_limits; - if (VK_SUCCESS == GPDIFPHelper(gpu, &image_ci, &img_limits) && !(img_limits.sampleCounts & samples)) return true; - } - } - - return false; -} - -TEST_F(VkLayerTest, CreateImageMaxLimitsViolation) { - TEST_DESCRIPTION("Create invalid image with invalid parameters exceeding physical device limits."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkImage null_image; // throwaway target for all the vkCreateImage - - VkImageCreateInfo tmp_img_ci = {}; - tmp_img_ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - tmp_img_ci.flags = 0; // assumably any is supported - tmp_img_ci.imageType = VK_IMAGE_TYPE_2D; // any is supported - tmp_img_ci.format = VK_FORMAT_R8G8B8A8_UNORM; // has mandatory support for all usages - tmp_img_ci.extent = {1, 1, 1}; // limit is 256 for 3D, or 4096 - tmp_img_ci.mipLevels = 1; // any is supported - tmp_img_ci.arrayLayers = 1; // limit is 256 - tmp_img_ci.samples = VK_SAMPLE_COUNT_1_BIT; // needs to be 1 if TILING_LINEAR - // if VK_IMAGE_TILING_LINEAR imageType must be 2D, usage must be TRANSFER, and levels layers samplers all 1 - tmp_img_ci.tiling = VK_IMAGE_TILING_OPTIMAL; - tmp_img_ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; // depends on format - tmp_img_ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - const VkImageCreateInfo safe_image_ci = tmp_img_ci; - - ASSERT_VK_SUCCESS(GPDIFPHelper(gpu(), &safe_image_ci)); - - const VkPhysicalDeviceLimits &dev_limits = m_device->props.limits; - - { - VkImageCreateInfo image_ci = safe_image_ci; - image_ci.extent = {8, 8, 1}; - image_ci.mipLevels = 4 + 1; // 4 = log2(8) + 1 - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-mipLevels-00958"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - - image_ci.extent = {8, 15, 1}; - image_ci.mipLevels = 4 + 1; // 4 = floor(log2(15)) + 1 - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-mipLevels-00958"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } - - { - VkImageCreateInfo image_ci = safe_image_ci; - image_ci.tiling = VK_IMAGE_TILING_LINEAR; - image_ci.extent = {64, 64, 1}; - image_ci.format = FindFormatLinearWithoutMips(gpu(), image_ci); - image_ci.mipLevels = 2; - - if (image_ci.format != VK_FORMAT_UNDEFINED) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-mipLevels-02255"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } else { - printf("%s Cannot find a format to test maxMipLevels limit; skipping part of test.\n", kSkipPrefix); - } - } - - { - VkImageCreateInfo image_ci = safe_image_ci; - - VkImageFormatProperties img_limits; - ASSERT_VK_SUCCESS(GPDIFPHelper(gpu(), &image_ci, &img_limits)); - - if (img_limits.maxArrayLayers != UINT32_MAX) { - image_ci.arrayLayers = img_limits.maxArrayLayers + 1; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-arrayLayers-02256"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } else { - printf("%s VkImageFormatProperties::maxArrayLayers is already UINT32_MAX; skipping part of test.\n", kSkipPrefix); - } - } - - { - VkImageCreateInfo image_ci = safe_image_ci; - bool found = FindFormatWithoutSamples(gpu(), image_ci); - - if (found) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-samples-02258"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } else { - printf("%s Could not find a format with some unsupported samples; skipping part of test.\n", kSkipPrefix); - } - } - - { - VkImageCreateInfo image_ci = safe_image_ci; - image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; // (any attachment bit) - - VkImageFormatProperties img_limits; - ASSERT_VK_SUCCESS(GPDIFPHelper(gpu(), &image_ci, &img_limits)); - - if (dev_limits.maxFramebufferWidth != UINT32_MAX) { - image_ci.extent = {dev_limits.maxFramebufferWidth + 1, 64, 1}; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-usage-00964"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } else { - printf("%s VkPhysicalDeviceLimits::maxFramebufferWidth is already UINT32_MAX; skipping part of test.\n", kSkipPrefix); - } - - if (dev_limits.maxFramebufferHeight != UINT32_MAX) { - image_ci.usage = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; // try different one too - image_ci.extent = {64, dev_limits.maxFramebufferHeight + 1, 1}; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-usage-00965"); - vkCreateImage(m_device->handle(), &image_ci, NULL, &null_image); - m_errorMonitor->VerifyFound(); - } else { - printf("%s VkPhysicalDeviceLimits::maxFramebufferHeight is already UINT32_MAX; skipping part of test.\n", kSkipPrefix); - } - } -} - -bool FindUnsupportedImage(VkPhysicalDevice gpu, VkImageCreateInfo &image_ci) { - const VkFormat first_vk_format = static_cast<VkFormat>(1); - const VkFormat last_vk_format = static_cast<VkFormat>(130); // avoid compressed/feature protected, otherwise 184 - - const std::vector<VkImageTiling> tilings = {VK_IMAGE_TILING_LINEAR, VK_IMAGE_TILING_OPTIMAL}; - for (const auto tiling : tilings) { - image_ci.tiling = tiling; - - for (VkFormat format = first_vk_format; format <= last_vk_format; format = static_cast<VkFormat>(format + 1)) { - image_ci.format = format; - - VkFormatProperties format_props; - vkGetPhysicalDeviceFormatProperties(gpu, format, &format_props); - - const VkFormatFeatureFlags core_filter = 0x1FFF; - const auto features = (tiling == VK_IMAGE_TILING_LINEAR) ? format_props.linearTilingFeatures & core_filter - : format_props.optimalTilingFeatures & core_filter; - if (!(features & core_filter)) continue; // We wand supported by features, but not by ImageFormatProperties - - // get as many usage flags as possible - image_ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - if (features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) image_ci.usage |= VK_IMAGE_USAGE_SAMPLED_BIT; - if (features & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) image_ci.usage |= VK_IMAGE_USAGE_STORAGE_BIT; - if (features & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) image_ci.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - if (features & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) - image_ci.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - - VkImageFormatProperties img_limits; - if (VK_ERROR_FORMAT_NOT_SUPPORTED == GPDIFPHelper(gpu, &image_ci, &img_limits)) { - return true; - } - } - } - - return false; -} - -VkFormat FindFormatWithoutFeatures(VkPhysicalDevice gpu, VkImageTiling tiling, - VkFormatFeatureFlags undesired_features = UINT32_MAX) { - const VkFormat first_vk_format = static_cast<VkFormat>(1); - const VkFormat last_vk_format = static_cast<VkFormat>(130); // avoid compressed/feature protected, otherwise 184 - - for (VkFormat format = first_vk_format; format <= last_vk_format; format = static_cast<VkFormat>(format + 1)) { - VkFormatProperties format_props; - vkGetPhysicalDeviceFormatProperties(gpu, format, &format_props); - - const VkFormatFeatureFlags core_filter = 0x1FFF; - const auto features = (tiling == VK_IMAGE_TILING_LINEAR) ? format_props.linearTilingFeatures & core_filter - : format_props.optimalTilingFeatures & core_filter; - - const auto valid_features = features & core_filter; - if (undesired_features == UINT32_MAX) { - if (!valid_features) return format; - } else { - if (valid_features && !(valid_features & undesired_features)) return format; - } - } - - return VK_FORMAT_UNDEFINED; -} - -TEST_F(VkLayerTest, CopyImageTypeExtentMismatch) { - // Image copy tests where format type and extents don't match - ASSERT_NO_FATAL_FAILURE(Init()); - - VkImageCreateInfo ci; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_1D; - ci.format = VK_FORMAT_R8G8B8A8_UNORM; - ci.extent = {32, 1, 1}; - ci.mipLevels = 1; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.tiling = VK_IMAGE_TILING_OPTIMAL; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.queueFamilyIndexCount = 0; - ci.pQueueFamilyIndices = NULL; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - // Create 1D image - VkImageObj image_1D(m_device); - image_1D.init(&ci); - ASSERT_TRUE(image_1D.initialized()); - - // 2D image - ci.imageType = VK_IMAGE_TYPE_2D; - ci.extent = {32, 32, 1}; - VkImageObj image_2D(m_device); - image_2D.init(&ci); - ASSERT_TRUE(image_2D.initialized()); - - // 3D image - ci.imageType = VK_IMAGE_TYPE_3D; - ci.extent = {32, 32, 8}; - VkImageObj image_3D(m_device); - image_3D.init(&ci); - ASSERT_TRUE(image_3D.initialized()); - - // 2D image array - ci.imageType = VK_IMAGE_TYPE_2D; - ci.extent = {32, 32, 1}; - ci.arrayLayers = 8; - VkImageObj image_2D_array(m_device); - image_2D_array.init(&ci); - ASSERT_TRUE(image_2D_array.initialized()); - - m_commandBuffer->begin(); - - VkImageCopy copy_region; - copy_region.extent = {32, 1, 1}; - copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.srcSubresource.mipLevel = 0; - copy_region.dstSubresource.mipLevel = 0; - copy_region.srcSubresource.baseArrayLayer = 0; - copy_region.dstSubresource.baseArrayLayer = 0; - copy_region.srcSubresource.layerCount = 1; - copy_region.dstSubresource.layerCount = 1; - copy_region.srcOffset = {0, 0, 0}; - copy_region.dstOffset = {0, 0, 0}; - - // Sanity check - m_errorMonitor->ExpectSuccess(); - m_commandBuffer->CopyImage(image_1D.image(), VK_IMAGE_LAYOUT_GENERAL, image_2D.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyNotFound(); - - // 1D texture w/ offset.y > 0. Source = VU 09c00124, dest = 09c00130 - copy_region.srcOffset.y = 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcImage-00146"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcOffset-00145"); // also y-dim overrun - m_commandBuffer->CopyImage(image_1D.image(), VK_IMAGE_LAYOUT_GENERAL, image_2D.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - copy_region.srcOffset.y = 0; - copy_region.dstOffset.y = 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-dstImage-00152"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-dstOffset-00151"); // also y-dim overrun - m_commandBuffer->CopyImage(image_2D.image(), VK_IMAGE_LAYOUT_GENERAL, image_1D.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - copy_region.dstOffset.y = 0; - - // 1D texture w/ extent.height > 1. Source = VU 09c00124, dest = 09c00130 - copy_region.extent.height = 2; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcImage-00146"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcOffset-00145"); // also y-dim overrun - m_commandBuffer->CopyImage(image_1D.image(), VK_IMAGE_LAYOUT_GENERAL, image_2D.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-dstImage-00152"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-dstOffset-00151"); // also y-dim overrun - m_commandBuffer->CopyImage(image_2D.image(), VK_IMAGE_LAYOUT_GENERAL, image_1D.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - copy_region.extent.height = 1; - - // 1D texture w/ offset.z > 0. Source = VU 09c00df2, dest = 09c00df4 - copy_region.srcOffset.z = 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcImage-01785"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcOffset-00147"); // also z-dim overrun - m_commandBuffer->CopyImage(image_1D.image(), VK_IMAGE_LAYOUT_GENERAL, image_2D.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - copy_region.srcOffset.z = 0; - copy_region.dstOffset.z = 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-dstImage-01786"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-dstOffset-00153"); // also z-dim overrun - m_commandBuffer->CopyImage(image_2D.image(), VK_IMAGE_LAYOUT_GENERAL, image_1D.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - copy_region.dstOffset.z = 0; - - // 1D texture w/ extent.depth > 1. Source = VU 09c00df2, dest = 09c00df4 - copy_region.extent.depth = 2; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcImage-01785"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageCopy-srcOffset-00147"); // also z-dim overrun (src) - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageCopy-dstOffset-00153"); // also z-dim overrun (dst) - m_commandBuffer->CopyImage(image_1D.image(), VK_IMAGE_LAYOUT_GENERAL, image_2D.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-dstImage-01786"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageCopy-srcOffset-00147"); // also z-dim overrun (src) - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageCopy-dstOffset-00153"); // also z-dim overrun (dst) - m_commandBuffer->CopyImage(image_2D.image(), VK_IMAGE_LAYOUT_GENERAL, image_1D.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - copy_region.extent.depth = 1; - - // 2D texture w/ offset.z > 0. Source = VU 09c00df6, dest = 09c00df8 - copy_region.extent = {16, 16, 1}; - copy_region.srcOffset.z = 4; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcImage-01787"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageCopy-srcOffset-00147"); // also z-dim overrun (src) - m_commandBuffer->CopyImage(image_2D.image(), VK_IMAGE_LAYOUT_GENERAL, image_3D.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - copy_region.srcOffset.z = 0; - copy_region.dstOffset.z = 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-dstImage-01788"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImageCopy-dstOffset-00153"); // also z-dim overrun (dst) - m_commandBuffer->CopyImage(image_3D.image(), VK_IMAGE_LAYOUT_GENERAL, image_2D.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - copy_region.dstOffset.z = 0; - - // 3D texture accessing an array layer other than 0. VU 09c0011a - copy_region.extent = {4, 4, 1}; - copy_region.srcSubresource.baseArrayLayer = 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcImage-00141"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImage-srcSubresource-01698"); // also 'too many layers' - m_commandBuffer->CopyImage(image_3D.image(), VK_IMAGE_LAYOUT_GENERAL, image_2D.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, CopyImageTypeExtentMismatchMaintenance1) { - // Image copy tests where format type and extents don't match and the Maintenance1 extension is enabled - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - } else { - printf("%s Maintenance1 extension cannot be enabled, test skipped.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkFormat image_format = VK_FORMAT_R8G8B8A8_UNORM; - VkFormatProperties format_props; - // TODO: Remove this check if or when devsim handles extensions. - // The chosen format has mandatory support the transfer src and dst format features when Maitenance1 is enabled. However, our - // use of devsim and the mock ICD violate this guarantee. - vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), image_format, &format_props); - if (!(format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT)) { - printf("%s Maintenance1 extension is not supported.\n", kSkipPrefix); - return; - } - - VkImageCreateInfo ci; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_1D; - ci.format = image_format; - ci.extent = {32, 1, 1}; - ci.mipLevels = 1; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.tiling = VK_IMAGE_TILING_OPTIMAL; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.queueFamilyIndexCount = 0; - ci.pQueueFamilyIndices = NULL; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - // Create 1D image - VkImageObj image_1D(m_device); - image_1D.init(&ci); - ASSERT_TRUE(image_1D.initialized()); - - // 2D image - ci.imageType = VK_IMAGE_TYPE_2D; - ci.extent = {32, 32, 1}; - VkImageObj image_2D(m_device); - image_2D.init(&ci); - ASSERT_TRUE(image_2D.initialized()); - - // 3D image - ci.imageType = VK_IMAGE_TYPE_3D; - ci.extent = {32, 32, 8}; - VkImageObj image_3D(m_device); - image_3D.init(&ci); - ASSERT_TRUE(image_3D.initialized()); - - // 2D image array - ci.imageType = VK_IMAGE_TYPE_2D; - ci.extent = {32, 32, 1}; - ci.arrayLayers = 8; - VkImageObj image_2D_array(m_device); - image_2D_array.init(&ci); - ASSERT_TRUE(image_2D_array.initialized()); - - m_commandBuffer->begin(); - - VkImageCopy copy_region; - copy_region.extent = {32, 1, 1}; - copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.srcSubresource.mipLevel = 0; - copy_region.dstSubresource.mipLevel = 0; - copy_region.srcSubresource.baseArrayLayer = 0; - copy_region.dstSubresource.baseArrayLayer = 0; - copy_region.srcSubresource.layerCount = 1; - copy_region.dstSubresource.layerCount = 1; - copy_region.srcOffset = {0, 0, 0}; - copy_region.dstOffset = {0, 0, 0}; - - // Copy from layer not present - copy_region.srcSubresource.baseArrayLayer = 4; - copy_region.srcSubresource.layerCount = 6; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImage-srcSubresource-01698"); - m_commandBuffer->CopyImage(image_2D_array.image(), VK_IMAGE_LAYOUT_GENERAL, image_3D.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - copy_region.srcSubresource.baseArrayLayer = 0; - copy_region.srcSubresource.layerCount = 1; - - // Copy to layer not present - copy_region.dstSubresource.baseArrayLayer = 1; - copy_region.dstSubresource.layerCount = 8; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImage-dstSubresource-01699"); - m_commandBuffer->CopyImage(image_3D.image(), VK_IMAGE_LAYOUT_GENERAL, image_2D_array.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - copy_region.dstSubresource.layerCount = 1; - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, CopyImageCompressedBlockAlignment) { - // Image copy tests on compressed images with block alignment errors - SetTargetApiVersion(VK_API_VERSION_1_1); - ASSERT_NO_FATAL_FAILURE(Init()); - - // Select a compressed format and verify support - VkPhysicalDeviceFeatures device_features = {}; - ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features)); - VkFormat compressed_format = VK_FORMAT_UNDEFINED; - if (device_features.textureCompressionBC) { - compressed_format = VK_FORMAT_BC3_SRGB_BLOCK; - } else if (device_features.textureCompressionETC2) { - compressed_format = VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; - } else if (device_features.textureCompressionASTC_LDR) { - compressed_format = VK_FORMAT_ASTC_4x4_UNORM_BLOCK; - } - - VkImageCreateInfo ci; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_2D; - ci.format = compressed_format; - ci.extent = {64, 64, 1}; - ci.mipLevels = 1; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.tiling = VK_IMAGE_TILING_OPTIMAL; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.queueFamilyIndexCount = 0; - ci.pQueueFamilyIndices = NULL; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkImageFormatProperties img_prop = {}; - if (VK_SUCCESS != vkGetPhysicalDeviceImageFormatProperties(m_device->phy().handle(), ci.format, ci.imageType, ci.tiling, - ci.usage, ci.flags, &img_prop)) { - printf("%s No compressed formats supported - CopyImageCompressedBlockAlignment skipped.\n", kSkipPrefix); - return; - } - - // Create images - VkImageObj image_1(m_device); - image_1.init(&ci); - ASSERT_TRUE(image_1.initialized()); - - ci.extent = {62, 62, 1}; // slightly smaller and not divisible by block size - VkImageObj image_2(m_device); - image_2.init(&ci); - ASSERT_TRUE(image_2.initialized()); - - m_commandBuffer->begin(); - - VkImageCopy copy_region; - copy_region.extent = {48, 48, 1}; - copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.srcSubresource.mipLevel = 0; - copy_region.dstSubresource.mipLevel = 0; - copy_region.srcSubresource.baseArrayLayer = 0; - copy_region.dstSubresource.baseArrayLayer = 0; - copy_region.srcSubresource.layerCount = 1; - copy_region.dstSubresource.layerCount = 1; - copy_region.srcOffset = {0, 0, 0}; - copy_region.dstOffset = {0, 0, 0}; - - // Sanity check - m_errorMonitor->ExpectSuccess(); - m_commandBuffer->CopyImage(image_1.image(), VK_IMAGE_LAYOUT_GENERAL, image_2.image(), VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); - m_errorMonitor->VerifyNotFound(); - - std::string vuid; - bool ycbcr = (DeviceExtensionEnabled(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME) || - (DeviceValidationVersion() >= VK_API_VERSION_1_1)); - - // Src, Dest offsets must be multiples of compressed block sizes {4, 4, 1} - // Image transfer granularity gets set to compressed block size, so an ITG error is also (unavoidably) triggered. - vuid = ycbcr ? "VUID-VkImageCopy-srcImage-01727" : "VUID-VkImageCopy-srcOffset-00157"; - copy_region.srcOffset = {2, 4, 0}; // source width - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImage-srcOffset-01783"); // srcOffset image transfer granularity - m_commandBuffer->CopyImage(image_1.image(), VK_IMAGE_LAYOUT_GENERAL, image_2.image(), VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); - m_errorMonitor->VerifyFound(); - copy_region.srcOffset = {12, 1, 0}; // source height - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImage-srcOffset-01783"); // srcOffset image transfer granularity - m_commandBuffer->CopyImage(image_1.image(), VK_IMAGE_LAYOUT_GENERAL, image_2.image(), VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); - m_errorMonitor->VerifyFound(); - copy_region.srcOffset = {0, 0, 0}; - - vuid = ycbcr ? "VUID-VkImageCopy-dstImage-01731" : "VUID-VkImageCopy-dstOffset-00162"; - copy_region.dstOffset = {1, 0, 0}; // dest width - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImage-dstOffset-01784"); // dstOffset image transfer granularity - m_commandBuffer->CopyImage(image_1.image(), VK_IMAGE_LAYOUT_GENERAL, image_2.image(), VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); - m_errorMonitor->VerifyFound(); - copy_region.dstOffset = {4, 1, 0}; // dest height - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImage-dstOffset-01784"); // dstOffset image transfer granularity - m_commandBuffer->CopyImage(image_1.image(), VK_IMAGE_LAYOUT_GENERAL, image_2.image(), VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); - m_errorMonitor->VerifyFound(); - copy_region.dstOffset = {0, 0, 0}; - - // Copy extent must be multiples of compressed block sizes {4, 4, 1} if not full width/height - vuid = ycbcr ? "VUID-VkImageCopy-srcImage-01728" : "VUID-VkImageCopy-extent-00158"; - copy_region.extent = {62, 60, 1}; // source width - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImage-srcOffset-01783"); // src extent image transfer granularity - m_commandBuffer->CopyImage(image_1.image(), VK_IMAGE_LAYOUT_GENERAL, image_2.image(), VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); - m_errorMonitor->VerifyFound(); - vuid = ycbcr ? "VUID-VkImageCopy-srcImage-01729" : "VUID-VkImageCopy-extent-00159"; - copy_region.extent = {60, 62, 1}; // source height - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImage-srcOffset-01783"); // src extent image transfer granularity - m_commandBuffer->CopyImage(image_1.image(), VK_IMAGE_LAYOUT_GENERAL, image_2.image(), VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); - m_errorMonitor->VerifyFound(); - - vuid = ycbcr ? "VUID-VkImageCopy-dstImage-01732" : "VUID-VkImageCopy-extent-00163"; - copy_region.extent = {62, 60, 1}; // dest width - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImage-dstOffset-01784"); // dst extent image transfer granularity - m_commandBuffer->CopyImage(image_2.image(), VK_IMAGE_LAYOUT_GENERAL, image_1.image(), VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); - m_errorMonitor->VerifyFound(); - vuid = ycbcr ? "VUID-VkImageCopy-dstImage-01733" : "VUID-VkImageCopy-extent-00164"; - copy_region.extent = {60, 62, 1}; // dest height - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImage-dstOffset-01784"); // dst extent image transfer granularity - m_commandBuffer->CopyImage(image_2.image(), VK_IMAGE_LAYOUT_GENERAL, image_1.image(), VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); - m_errorMonitor->VerifyFound(); - - // Note: "VUID-VkImageCopy-extent-00160", "VUID-VkImageCopy-extent-00165", "VUID-VkImageCopy-srcImage-01730", - // "VUID-VkImageCopy-dstImage-01734" - // There are currently no supported compressed formats with a block depth other than 1, - // so impossible to create a 'not a multiple' condition for depth. - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, CopyImageSinglePlane422Alignment) { - // Image copy tests on single-plane _422 formats with block alignment errors - - // Enable KHR multiplane req'd extensions - bool mp_extensions = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, - VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION); - if (mp_extensions) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - if (mp_extensions) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - } else { - printf("%s test requires KHR multiplane extensions, not available. Skipping.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - // Select a _422 format and verify support - VkImageCreateInfo ci = {}; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_2D; - ci.format = VK_FORMAT_G8B8G8R8_422_UNORM_KHR; - ci.tiling = VK_IMAGE_TILING_OPTIMAL; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - ci.mipLevels = 1; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.queueFamilyIndexCount = 0; - ci.pQueueFamilyIndices = NULL; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - // Verify formats - VkFormatFeatureFlags features = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT; - bool supported = ImageFormatAndFeaturesSupported(instance(), gpu(), ci, features); - if (!supported) { - printf("%s Single-plane _422 image format not supported. Skipping test.\n", kSkipPrefix); - return; // Assume there's low ROI on searching for different mp formats - } - - // Create images - ci.extent = {64, 64, 1}; - VkImageObj image_422(m_device); - image_422.init(&ci); - ASSERT_TRUE(image_422.initialized()); - - ci.extent = {64, 64, 1}; - ci.format = VK_FORMAT_R8G8B8A8_UNORM; - VkImageObj image_ucmp(m_device); - image_ucmp.init(&ci); - ASSERT_TRUE(image_ucmp.initialized()); - - m_commandBuffer->begin(); - - VkImageCopy copy_region; - copy_region.extent = {48, 48, 1}; - copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.srcSubresource.mipLevel = 0; - copy_region.dstSubresource.mipLevel = 0; - copy_region.srcSubresource.baseArrayLayer = 0; - copy_region.dstSubresource.baseArrayLayer = 0; - copy_region.srcSubresource.layerCount = 1; - copy_region.dstSubresource.layerCount = 1; - copy_region.srcOffset = {0, 0, 0}; - copy_region.dstOffset = {0, 0, 0}; - - // Src offsets must be multiples of compressed block sizes - copy_region.srcOffset = {3, 4, 0}; // source offset x - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcImage-01727"); - m_commandBuffer->CopyImage(image_422.image(), VK_IMAGE_LAYOUT_GENERAL, image_ucmp.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - copy_region.srcOffset = {0, 0, 0}; - - // Dst offsets must be multiples of compressed block sizes - copy_region.dstOffset = {1, 0, 0}; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-dstImage-01731"); - m_commandBuffer->CopyImage(image_ucmp.image(), VK_IMAGE_LAYOUT_GENERAL, image_422.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - copy_region.dstOffset = {0, 0, 0}; - - // Copy extent must be multiples of compressed block sizes if not full width/height - copy_region.extent = {31, 60, 1}; // 422 source, extent.x - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcImage-01728"); - m_commandBuffer->CopyImage(image_422.image(), VK_IMAGE_LAYOUT_GENERAL, image_ucmp.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - - // 422 dest, extent.x - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-dstImage-01732"); - m_commandBuffer->CopyImage(image_ucmp.image(), VK_IMAGE_LAYOUT_GENERAL, image_422.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - copy_region.dstOffset = {0, 0, 0}; - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, MultiplaneImageSamplerConversionMismatch) { - TEST_DESCRIPTION( - "Create sampler with ycbcr conversion and use with an image created without ycrcb conversion or immutable sampler"); - - // Enable KHR multiplane req'd extensions - bool mp_extensions = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION); - if (mp_extensions) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - SetTargetApiVersion(VK_API_VERSION_1_1); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - if (mp_extensions) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - } else { - printf("%s test requires KHR multiplane extensions, not available. Skipping.\n", kSkipPrefix); - return; - } - - // Enable Ycbcr Conversion Features - VkPhysicalDeviceSamplerYcbcrConversionFeatures ycbcr_features = {}; - ycbcr_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES; - ycbcr_features.samplerYcbcrConversion = VK_TRUE; - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &ycbcr_features)); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const VkImageCreateInfo ci = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - NULL, - 0, - VK_IMAGE_TYPE_2D, - VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR, - {128, 128, 1}, - 1, - 1, - VK_SAMPLE_COUNT_1_BIT, - VK_IMAGE_TILING_LINEAR, - VK_IMAGE_USAGE_SAMPLED_BIT, - VK_SHARING_MODE_EXCLUSIVE, - VK_IMAGE_LAYOUT_UNDEFINED}; - - // Verify formats - bool supported = ImageFormatAndFeaturesSupported(instance(), gpu(), ci, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT); - if (!supported) { - printf("%s Multiplane image format not supported. Skipping test.\n", kSkipPrefix); - return; - } - - // Create Ycbcr conversion - VkSamplerYcbcrConversionCreateInfo ycbcr_create_info = {VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO, - NULL, - VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, - VK_SAMPLER_YCBCR_RANGE_ITU_FULL, - {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, - VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}, - VK_CHROMA_LOCATION_COSITED_EVEN, - VK_CHROMA_LOCATION_COSITED_EVEN, - VK_FILTER_NEAREST, - false}; - VkSamplerYcbcrConversion conversions[2]; - vkCreateSamplerYcbcrConversion(m_device->handle(), &ycbcr_create_info, nullptr, &conversions[0]); - ycbcr_create_info.components.r = VK_COMPONENT_SWIZZLE_ZERO; // Just anything different than above - vkCreateSamplerYcbcrConversion(m_device->handle(), &ycbcr_create_info, nullptr, &conversions[1]); - - VkSamplerYcbcrConversionInfo ycbcr_info = {}; - ycbcr_info.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO; - ycbcr_info.conversion = conversions[0]; - - // Create a sampler using conversion - VkSamplerCreateInfo sci = SafeSaneSamplerCreateInfo(); - sci.pNext = &ycbcr_info; - // Create two samplers with two different conversions, such that one will mismatch - // It will make the second sampler fail to see if the log prints the second sampler or the first sampler. - VkSampler samplers[2]; - VkResult err = vkCreateSampler(m_device->device(), &sci, NULL, &samplers[0]); - ASSERT_VK_SUCCESS(err); - ycbcr_info.conversion = conversions[1]; // Need two samplers with different conversions - err = vkCreateSampler(m_device->device(), &sci, NULL, &samplers[1]); - ASSERT_VK_SUCCESS(err); - - // Create an image without a Ycbcr conversion - VkImageObj mpimage(m_device); - mpimage.init(&ci); - - VkImageView views[2]; - VkImageViewCreateInfo ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ycbcr_info.conversion = conversions[0]; // Need two samplers with different conversions - ivci.pNext = &ycbcr_info; - ivci.image = mpimage.handle(); - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR; - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - ivci.subresourceRange.levelCount = 1; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - vkCreateImageView(m_device->device(), &ivci, nullptr, &views[0]); - - // Use the image and sampler together in a descriptor set - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, VK_SHADER_STAGE_ALL, samplers}, - }); - - // Use the same image view twice, using the same sampler, with the *second* mismatched with the *second* immutable sampler - VkDescriptorImageInfo image_infos[2]; - image_infos[0] = {}; - image_infos[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - image_infos[0].imageView = views[0]; - image_infos[0].sampler = samplers[0]; - image_infos[1] = image_infos[0]; - - // Update the descriptor set expecting to get an error - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 2; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_write.pImageInfo = image_infos; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-01948"); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - - // pImmutableSamplers = nullptr causes an error , VUID-01947. - // Because if pNext chains a VkSamplerYcbcrConversionInfo, the sampler has to be a immutable sampler. - OneOffDescriptorSet ds_1947(m_device, { - {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - descriptor_write.dstSet = ds_1947.set_; - descriptor_write.descriptorCount = 1; - descriptor_write.pImageInfo = &image_infos[0]; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-01947"); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - - // Now for a positive test set up two different image view matching the two different immutable samplers. - ycbcr_info.conversion = conversions[1]; - vkCreateImageView(m_device->device(), &ivci, nullptr, &views[1]); - image_infos[1].imageView = views[1]; - image_infos[1].sampler = samplers[1]; - descriptor_write.dstSet = ds.set_; - descriptor_write.descriptorCount = 2; - descriptor_write.pImageInfo = image_infos; - m_errorMonitor->ExpectSuccess(); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyNotFound(); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(set=0, binding=0) uniform sampler2D s[2];\n" - "layout(location=0) out vec4 x;\n" - "void main(){\n" - " x = texture(s[0], vec2(1));\n" - " x = texture(s[1], vec2(1));\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - const VkPipelineLayoutObj pl(m_device, {&ds.layout_}); - pipe.CreateVKPipeline(pl.handle(), renderPass()); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pl.handle(), 0, 1, &ds.set_, 0, NULL); - - m_errorMonitor->ExpectSuccess(); - m_commandBuffer->Draw(1, 0, 0, 0); - m_errorMonitor->VerifyNotFound(); - vkCmdEndRenderPass(m_commandBuffer->handle()); - m_commandBuffer->end(); - - vkDestroySamplerYcbcrConversion(m_device->device(), conversions[0], nullptr); - vkDestroySamplerYcbcrConversion(m_device->device(), conversions[1], nullptr); - vkDestroyImageView(m_device->device(), views[0], NULL); - vkDestroyImageView(m_device->device(), views[1], NULL); - vkDestroySampler(m_device->device(), samplers[0], nullptr); - vkDestroySampler(m_device->device(), samplers[1], nullptr); -} - -TEST_F(VkLayerTest, CopyImageMultiplaneAspectBits) { - // Image copy tests on multiplane images with aspect errors - - // Enable KHR multiplane req'd extensions - bool mp_extensions = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, - VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION); - if (mp_extensions) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - if (mp_extensions) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - } else { - printf("%s test requires KHR multiplane extensions, not available. Skipping.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - // Select multi-plane formats and verify support - VkFormat mp3_format = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR; - VkFormat mp2_format = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR; - - VkImageCreateInfo ci = {}; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_2D; - ci.format = mp2_format; - ci.extent = {256, 256, 1}; - ci.tiling = VK_IMAGE_TILING_OPTIMAL; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - ci.mipLevels = 1; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.queueFamilyIndexCount = 0; - ci.pQueueFamilyIndices = NULL; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - // Verify formats - VkFormatFeatureFlags features = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT; - bool supported = ImageFormatAndFeaturesSupported(instance(), gpu(), ci, features); - ci.format = mp3_format; - supported = supported && ImageFormatAndFeaturesSupported(instance(), gpu(), ci, features); - if (!supported) { - printf("%s Multiplane image formats not supported. Skipping test.\n", kSkipPrefix); - return; // Assume there's low ROI on searching for different mp formats - } - - // Create images - VkImageObj mp3_image(m_device); - mp3_image.init(&ci); - ASSERT_TRUE(mp3_image.initialized()); - - ci.format = mp2_format; - VkImageObj mp2_image(m_device); - mp2_image.init(&ci); - ASSERT_TRUE(mp2_image.initialized()); - - ci.format = VK_FORMAT_D24_UNORM_S8_UINT; - VkImageObj sp_image(m_device); - sp_image.init(&ci); - ASSERT_TRUE(sp_image.initialized()); - - m_commandBuffer->begin(); - - VkImageCopy copy_region; - copy_region.extent = {128, 128, 1}; - copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR; - copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR; - copy_region.srcSubresource.mipLevel = 0; - copy_region.dstSubresource.mipLevel = 0; - copy_region.srcSubresource.baseArrayLayer = 0; - copy_region.dstSubresource.baseArrayLayer = 0; - copy_region.srcSubresource.layerCount = 1; - copy_region.dstSubresource.layerCount = 1; - copy_region.srcOffset = {0, 0, 0}; - copy_region.dstOffset = {0, 0, 0}; - - m_errorMonitor->SetUnexpectedError("VUID-vkCmdCopyImage-srcImage-00135"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcImage-01552"); - m_commandBuffer->CopyImage(mp2_image.image(), VK_IMAGE_LAYOUT_GENERAL, mp3_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - - copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT_KHR; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcImage-01553"); - m_commandBuffer->CopyImage(mp3_image.image(), VK_IMAGE_LAYOUT_GENERAL, mp2_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - - copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT_KHR; - copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR; - m_errorMonitor->SetUnexpectedError("VUID-vkCmdCopyImage-srcImage-00135"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-dstImage-01554"); - m_commandBuffer->CopyImage(mp3_image.image(), VK_IMAGE_LAYOUT_GENERAL, mp2_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - - copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - m_errorMonitor->SetUnexpectedError("VUID-vkCmdCopyImage-srcImage-00135"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-dstImage-01555"); - m_commandBuffer->CopyImage(mp2_image.image(), VK_IMAGE_LAYOUT_GENERAL, mp3_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - - copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcImage-01556"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "dest image depth/stencil formats"); // also - m_commandBuffer->CopyImage(mp2_image.image(), VK_IMAGE_LAYOUT_GENERAL, sp_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - - copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-dstImage-01557"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "dest image depth/stencil formats"); // also - m_commandBuffer->CopyImage(sp_image.image(), VK_IMAGE_LAYOUT_GENERAL, mp3_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, CopyImageSrcSizeExceeded) { - // Image copy with source region specified greater than src image size - ASSERT_NO_FATAL_FAILURE(Init()); - - // Create images with full mip chain - VkImageCreateInfo ci; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_3D; - ci.format = VK_FORMAT_R8G8B8A8_UNORM; - ci.extent = {32, 32, 8}; - ci.mipLevels = 6; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.tiling = VK_IMAGE_TILING_OPTIMAL; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.queueFamilyIndexCount = 0; - ci.pQueueFamilyIndices = NULL; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkImageObj src_image(m_device); - src_image.init(&ci); - ASSERT_TRUE(src_image.initialized()); - - // Dest image with one more mip level - ci.extent = {64, 64, 16}; - ci.mipLevels = 7; - ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; - VkImageObj dst_image(m_device); - dst_image.init(&ci); - ASSERT_TRUE(dst_image.initialized()); - - m_commandBuffer->begin(); - - VkImageCopy copy_region; - copy_region.extent = {32, 32, 8}; - copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.srcSubresource.mipLevel = 0; - copy_region.dstSubresource.mipLevel = 0; - copy_region.srcSubresource.baseArrayLayer = 0; - copy_region.dstSubresource.baseArrayLayer = 0; - copy_region.srcSubresource.layerCount = 1; - copy_region.dstSubresource.layerCount = 1; - copy_region.srcOffset = {0, 0, 0}; - copy_region.dstOffset = {0, 0, 0}; - - m_errorMonitor->ExpectSuccess(); - m_commandBuffer->CopyImage(src_image.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyNotFound(); - - // Source exceeded in x-dim, VU 01202 - copy_region.srcOffset.x = 4; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImage-pRegions-00122"); // General "contained within" VU - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcOffset-00144"); - m_commandBuffer->CopyImage(src_image.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - - // Source exceeded in y-dim, VU 01203 - copy_region.srcOffset.x = 0; - copy_region.extent.height = 48; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImage-pRegions-00122"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcOffset-00145"); - m_commandBuffer->CopyImage(src_image.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - - // Source exceeded in z-dim, VU 01204 - copy_region.extent = {4, 4, 4}; - copy_region.srcSubresource.mipLevel = 2; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImage-pRegions-00122"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-srcOffset-00147"); - m_commandBuffer->CopyImage(src_image.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, CopyImageDstSizeExceeded) { - // Image copy with dest region specified greater than dest image size - ASSERT_NO_FATAL_FAILURE(Init()); - - // Create images with full mip chain - VkImageCreateInfo ci; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_3D; - ci.format = VK_FORMAT_R8G8B8A8_UNORM; - ci.extent = {32, 32, 8}; - ci.mipLevels = 6; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.tiling = VK_IMAGE_TILING_OPTIMAL; - ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.queueFamilyIndexCount = 0; - ci.pQueueFamilyIndices = NULL; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkImageObj dst_image(m_device); - dst_image.init(&ci); - ASSERT_TRUE(dst_image.initialized()); - - // Src image with one more mip level - ci.extent = {64, 64, 16}; - ci.mipLevels = 7; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - VkImageObj src_image(m_device); - src_image.init(&ci); - ASSERT_TRUE(src_image.initialized()); - - m_commandBuffer->begin(); - - VkImageCopy copy_region; - copy_region.extent = {32, 32, 8}; - copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.srcSubresource.mipLevel = 0; - copy_region.dstSubresource.mipLevel = 0; - copy_region.srcSubresource.baseArrayLayer = 0; - copy_region.dstSubresource.baseArrayLayer = 0; - copy_region.srcSubresource.layerCount = 1; - copy_region.dstSubresource.layerCount = 1; - copy_region.srcOffset = {0, 0, 0}; - copy_region.dstOffset = {0, 0, 0}; - - m_errorMonitor->ExpectSuccess(); - m_commandBuffer->CopyImage(src_image.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyNotFound(); - - // Dest exceeded in x-dim, VU 01205 - copy_region.dstOffset.x = 4; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdCopyImage-pRegions-00123"); // General "contained within" VU - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-dstOffset-00150"); - m_commandBuffer->CopyImage(src_image.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - - // Dest exceeded in y-dim, VU 01206 - copy_region.dstOffset.x = 0; - copy_region.extent.height = 48; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImage-pRegions-00123"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-dstOffset-00151"); - m_commandBuffer->CopyImage(src_image.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - - // Dest exceeded in z-dim, VU 01207 - copy_region.extent = {4, 4, 4}; - copy_region.dstSubresource.mipLevel = 2; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImage-pRegions-00123"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-dstOffset-00153"); - m_commandBuffer->CopyImage(src_image.image(), VK_IMAGE_LAYOUT_GENERAL, dst_image.image(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©_region); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, CopyImageFormatSizeMismatch) { - VkResult err; - bool pass; - - // Create color images with different format sizes and try to copy between them - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImage-srcImage-00135"); - - SetTargetApiVersion(VK_API_VERSION_1_1); - ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - - // Create two images of different types and try to copy between them - VkImage srcImage; - VkImage dstImage; - VkDeviceMemory srcMem; - VkDeviceMemory destMem; - VkMemoryRequirements memReqs; - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM; - image_create_info.extent.width = 32; - image_create_info.extent.height = 32; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_LINEAR; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - image_create_info.flags = 0; - - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &srcImage); - ASSERT_VK_SUCCESS(err); - - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; - // Introduce failure by creating second image with a different-sized format. - image_create_info.format = VK_FORMAT_R5G5B5A1_UNORM_PACK16; - VkFormatProperties properties; - vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), image_create_info.format, &properties); - if (properties.optimalTilingFeatures == 0) { - vkDestroyImage(m_device->device(), srcImage, NULL); - printf("%s Image format not supported; skipped.\n", kSkipPrefix); - return; - } - - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &dstImage); - ASSERT_VK_SUCCESS(err); - - // Allocate memory - VkMemoryAllocateInfo memAlloc = {}; - memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memAlloc.pNext = NULL; - memAlloc.allocationSize = 0; - memAlloc.memoryTypeIndex = 0; - - vkGetImageMemoryRequirements(m_device->device(), srcImage, &memReqs); - memAlloc.allocationSize = memReqs.size; - pass = m_device->phy().set_memory_type(memReqs.memoryTypeBits, &memAlloc, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(m_device->device(), &memAlloc, NULL, &srcMem); - ASSERT_VK_SUCCESS(err); - - vkGetImageMemoryRequirements(m_device->device(), dstImage, &memReqs); - memAlloc.allocationSize = memReqs.size; - pass = m_device->phy().set_memory_type(memReqs.memoryTypeBits, &memAlloc, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(m_device->device(), &memAlloc, NULL, &destMem); - ASSERT_VK_SUCCESS(err); - - err = vkBindImageMemory(m_device->device(), srcImage, srcMem, 0); - ASSERT_VK_SUCCESS(err); - err = vkBindImageMemory(m_device->device(), dstImage, destMem, 0); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - VkImageCopy copyRegion; - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.srcSubresource.mipLevel = 0; - copyRegion.srcSubresource.baseArrayLayer = 0; - copyRegion.srcSubresource.layerCount = 1; - copyRegion.srcOffset.x = 0; - copyRegion.srcOffset.y = 0; - copyRegion.srcOffset.z = 0; - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.dstSubresource.mipLevel = 0; - copyRegion.dstSubresource.baseArrayLayer = 0; - copyRegion.dstSubresource.layerCount = 1; - copyRegion.dstOffset.x = 0; - copyRegion.dstOffset.y = 0; - copyRegion.dstOffset.z = 0; - copyRegion.extent.width = 1; - copyRegion.extent.height = 1; - copyRegion.extent.depth = 1; - m_commandBuffer->CopyImage(srcImage, VK_IMAGE_LAYOUT_GENERAL, dstImage, VK_IMAGE_LAYOUT_GENERAL, 1, ©Region); - m_commandBuffer->end(); - - m_errorMonitor->VerifyFound(); - - vkDestroyImage(m_device->device(), dstImage, NULL); - vkFreeMemory(m_device->device(), destMem, NULL); - - // Copy to multiplane image with mismatched sizes - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImage-srcImage-00135"); - - VkImageCreateInfo ci; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_2D; - ci.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; - ci.extent = {32, 32, 1}; - ci.mipLevels = 1; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.tiling = VK_IMAGE_TILING_LINEAR; - ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.queueFamilyIndexCount = 0; - ci.pQueueFamilyIndices = NULL; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkFormatFeatureFlags features = VK_FORMAT_FEATURE_TRANSFER_DST_BIT; - bool supported = ImageFormatAndFeaturesSupported(instance(), gpu(), ci, features); - bool ycbcr = (DeviceExtensionEnabled(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME) || - (DeviceValidationVersion() >= VK_API_VERSION_1_1)); - if (!supported || !ycbcr) { - printf("%s Image format not supported; skipped multiplanar copy test.\n", kSkipPrefix); - vkDestroyImage(m_device->device(), srcImage, NULL); - vkFreeMemory(m_device->device(), srcMem, NULL); - return; - } - - VkImageObj mpImage(m_device); - mpImage.init(&ci); - ASSERT_TRUE(mpImage.initialized()); - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; - vkResetCommandBuffer(m_commandBuffer->handle(), 0); - m_commandBuffer->begin(); - m_commandBuffer->CopyImage(srcImage, VK_IMAGE_LAYOUT_GENERAL, mpImage.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ©Region); - m_commandBuffer->end(); - - m_errorMonitor->VerifyFound(); - - vkDestroyImage(m_device->device(), srcImage, NULL); - vkFreeMemory(m_device->device(), srcMem, NULL); -} - -TEST_F(VkLayerTest, CopyImageDepthStencilFormatMismatch) { - ASSERT_NO_FATAL_FAILURE(Init()); - auto depth_format = FindSupportedDepthStencilFormat(gpu()); - if (!depth_format) { - printf("%s Couldn't depth stencil image format.\n", kSkipPrefix); - return; - } - - VkFormatProperties properties; - vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), VK_FORMAT_D32_SFLOAT, &properties); - if (properties.optimalTilingFeatures == 0) { - printf("%s Image format not supported; skipped.\n", kSkipPrefix); - return; - } - - VkImageObj srcImage(m_device); - srcImage.Init(32, 32, 1, VK_FORMAT_D32_SFLOAT, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(srcImage.initialized()); - VkImageObj dstImage(m_device); - dstImage.Init(32, 32, 1, depth_format, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(dstImage.initialized()); - - // Create two images of different types and try to copy between them - - m_commandBuffer->begin(); - VkImageCopy copyRegion; - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - copyRegion.srcSubresource.mipLevel = 0; - copyRegion.srcSubresource.baseArrayLayer = 0; - copyRegion.srcSubresource.layerCount = 1; - copyRegion.srcOffset.x = 0; - copyRegion.srcOffset.y = 0; - copyRegion.srcOffset.z = 0; - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - copyRegion.dstSubresource.mipLevel = 0; - copyRegion.dstSubresource.baseArrayLayer = 0; - copyRegion.dstSubresource.layerCount = 1; - copyRegion.dstOffset.x = 0; - copyRegion.dstOffset.y = 0; - copyRegion.dstOffset.z = 0; - copyRegion.extent.width = 1; - copyRegion.extent.height = 1; - copyRegion.extent.depth = 1; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkCmdCopyImage called with unmatched source and dest image depth"); - m_commandBuffer->CopyImage(srcImage.handle(), VK_IMAGE_LAYOUT_GENERAL, dstImage.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©Region); - m_commandBuffer->end(); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CopyImageSampleCountMismatch) { - TEST_DESCRIPTION("Image copies with sample count mis-matches"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkImageFormatProperties image_format_properties; - vkGetPhysicalDeviceImageFormatProperties(gpu(), VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0, - &image_format_properties); - - if ((0 == (VK_SAMPLE_COUNT_2_BIT & image_format_properties.sampleCounts)) || - (0 == (VK_SAMPLE_COUNT_4_BIT & image_format_properties.sampleCounts))) { - printf("%s Image multi-sample support not found; skipped.\n", kSkipPrefix); - return; - } - - VkImageCreateInfo ci; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_2D; - ci.format = VK_FORMAT_R8G8B8A8_UNORM; - ci.extent = {128, 128, 1}; - ci.mipLevels = 1; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.tiling = VK_IMAGE_TILING_OPTIMAL; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.queueFamilyIndexCount = 0; - ci.pQueueFamilyIndices = NULL; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkImageObj image1(m_device); - image1.init(&ci); - ASSERT_TRUE(image1.initialized()); - - ci.samples = VK_SAMPLE_COUNT_2_BIT; - VkImageObj image2(m_device); - image2.init(&ci); - ASSERT_TRUE(image2.initialized()); - - ci.samples = VK_SAMPLE_COUNT_4_BIT; - VkImageObj image4(m_device); - image4.init(&ci); - ASSERT_TRUE(image4.initialized()); - - m_commandBuffer->begin(); - - VkImageCopy copyRegion; - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.srcSubresource.mipLevel = 0; - copyRegion.srcSubresource.baseArrayLayer = 0; - copyRegion.srcSubresource.layerCount = 1; - copyRegion.srcOffset = {0, 0, 0}; - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.dstSubresource.mipLevel = 0; - copyRegion.dstSubresource.baseArrayLayer = 0; - copyRegion.dstSubresource.layerCount = 1; - copyRegion.dstOffset = {0, 0, 0}; - copyRegion.extent = {128, 128, 1}; - - // Copy a single sample image to/from a multi-sample image - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImage-srcImage-00136"); - vkCmdCopyImage(m_commandBuffer->handle(), image1.handle(), VK_IMAGE_LAYOUT_GENERAL, image4.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©Region); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImage-srcImage-00136"); - vkCmdCopyImage(m_commandBuffer->handle(), image2.handle(), VK_IMAGE_LAYOUT_GENERAL, image1.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©Region); - m_errorMonitor->VerifyFound(); - - // Copy between multi-sample images with different sample counts - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImage-srcImage-00136"); - vkCmdCopyImage(m_commandBuffer->handle(), image2.handle(), VK_IMAGE_LAYOUT_GENERAL, image4.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©Region); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyImage-srcImage-00136"); - vkCmdCopyImage(m_commandBuffer->handle(), image4.handle(), VK_IMAGE_LAYOUT_GENERAL, image2.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, - ©Region); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, CopyImageAspectMismatch) { - TEST_DESCRIPTION("Image copies with aspect mask errors"); - SetTargetApiVersion(VK_API_VERSION_1_1); - ASSERT_NO_FATAL_FAILURE(Init()); - auto ds_format = FindSupportedDepthStencilFormat(gpu()); - if (!ds_format) { - printf("%s Couldn't find depth stencil format.\n", kSkipPrefix); - return; - } - - VkFormatProperties properties; - vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), VK_FORMAT_D32_SFLOAT, &properties); - if (properties.optimalTilingFeatures == 0) { - printf("%s Image format VK_FORMAT_D32_SFLOAT not supported; skipped.\n", kSkipPrefix); - return; - } - VkImageObj color_image(m_device), ds_image(m_device), depth_image(m_device); - color_image.Init(128, 128, 1, VK_FORMAT_R32_SFLOAT, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); - depth_image.Init(128, 128, 1, VK_FORMAT_D32_SFLOAT, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - ds_image.Init(128, 128, 1, ds_format, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(color_image.initialized()); - ASSERT_TRUE(depth_image.initialized()); - ASSERT_TRUE(ds_image.initialized()); - - VkImageCopy copyRegion; - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - copyRegion.srcSubresource.mipLevel = 0; - copyRegion.srcSubresource.baseArrayLayer = 0; - copyRegion.srcSubresource.layerCount = 1; - copyRegion.srcOffset = {0, 0, 0}; - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - copyRegion.dstSubresource.mipLevel = 0; - copyRegion.dstSubresource.baseArrayLayer = 0; - copyRegion.dstSubresource.layerCount = 1; - copyRegion.dstOffset = {64, 0, 0}; - copyRegion.extent = {64, 128, 1}; - - // Submitting command before command buffer is in recording state - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "You must call vkBeginCommandBuffer"); // "VUID-vkCmdCopyImage-commandBuffer-recording"); - vkCmdCopyImage(m_commandBuffer->handle(), depth_image.handle(), VK_IMAGE_LAYOUT_GENERAL, depth_image.handle(), - VK_IMAGE_LAYOUT_GENERAL, 1, ©Region); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->begin(); - - // Src and dest aspect masks don't match - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; - bool ycbcr = (DeviceExtensionEnabled(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME) || - (DeviceValidationVersion() >= VK_API_VERSION_1_1)); - std::string vuid = (ycbcr ? "VUID-VkImageCopy-srcImage-01551" : "VUID-VkImageCopy-aspectMask-00137"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid); - vkCmdCopyImage(m_commandBuffer->handle(), ds_image.handle(), VK_IMAGE_LAYOUT_GENERAL, ds_image.handle(), - VK_IMAGE_LAYOUT_GENERAL, 1, ©Region); - m_errorMonitor->VerifyFound(); - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - - // Illegal combinations of aspect bits - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT; // color must be alone - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageSubresourceLayers-aspectMask-00167"); - // These aspect/format mismatches are redundant but unavoidable here - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-aspectMask-00142"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid); - vkCmdCopyImage(m_commandBuffer->handle(), color_image.handle(), VK_IMAGE_LAYOUT_GENERAL, color_image.handle(), - VK_IMAGE_LAYOUT_GENERAL, 1, ©Region); - m_errorMonitor->VerifyFound(); - // same test for dstSubresource - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT; // color must be alone - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageSubresourceLayers-aspectMask-00167"); - // These aspect/format mismatches are redundant but unavoidable here - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-aspectMask-00143"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid); - vkCmdCopyImage(m_commandBuffer->handle(), color_image.handle(), VK_IMAGE_LAYOUT_GENERAL, color_image.handle(), - VK_IMAGE_LAYOUT_GENERAL, 1, ©Region); - m_errorMonitor->VerifyFound(); - - // Metadata aspect is illegal - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT; - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageSubresourceLayers-aspectMask-00168"); - // These aspect/format mismatches are redundant but unavoidable here - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid); - vkCmdCopyImage(m_commandBuffer->handle(), color_image.handle(), VK_IMAGE_LAYOUT_GENERAL, color_image.handle(), - VK_IMAGE_LAYOUT_GENERAL, 1, ©Region); - m_errorMonitor->VerifyFound(); - // same test for dstSubresource - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageSubresourceLayers-aspectMask-00168"); - // These aspect/format mismatches are redundant but unavoidable here - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid); - vkCmdCopyImage(m_commandBuffer->handle(), color_image.handle(), VK_IMAGE_LAYOUT_GENERAL, color_image.handle(), - VK_IMAGE_LAYOUT_GENERAL, 1, ©Region); - m_errorMonitor->VerifyFound(); - - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - - // Aspect mask doesn't match source image format - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-aspectMask-00142"); - // Again redundant but unavoidable - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "unmatched source and dest image depth/stencil formats"); - vkCmdCopyImage(m_commandBuffer->handle(), color_image.handle(), VK_IMAGE_LAYOUT_GENERAL, depth_image.handle(), - VK_IMAGE_LAYOUT_GENERAL, 1, ©Region); - m_errorMonitor->VerifyFound(); - - // Aspect mask doesn't match dest image format - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCopy-aspectMask-00143"); - // Again redundant but unavoidable - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "unmatched source and dest image depth/stencil formats"); - vkCmdCopyImage(m_commandBuffer->handle(), color_image.handle(), VK_IMAGE_LAYOUT_GENERAL, depth_image.handle(), - VK_IMAGE_LAYOUT_GENERAL, 1, ©Region); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, ResolveImageLowSampleCount) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkCmdResolveImage called with source sample count less than 2."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // Create two images of sample count 1 and try to Resolve between them - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM; - image_create_info.extent.width = 32; - image_create_info.extent.height = 1; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - image_create_info.flags = 0; - - VkImageObj srcImage(m_device); - srcImage.init(&image_create_info); - ASSERT_TRUE(srcImage.initialized()); - - VkImageObj dstImage(m_device); - dstImage.init(&image_create_info); - ASSERT_TRUE(dstImage.initialized()); - - m_commandBuffer->begin(); - VkImageResolve resolveRegion; - resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - resolveRegion.srcSubresource.mipLevel = 0; - resolveRegion.srcSubresource.baseArrayLayer = 0; - resolveRegion.srcSubresource.layerCount = 1; - resolveRegion.srcOffset.x = 0; - resolveRegion.srcOffset.y = 0; - resolveRegion.srcOffset.z = 0; - resolveRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - resolveRegion.dstSubresource.mipLevel = 0; - resolveRegion.dstSubresource.baseArrayLayer = 0; - resolveRegion.dstSubresource.layerCount = 1; - resolveRegion.dstOffset.x = 0; - resolveRegion.dstOffset.y = 0; - resolveRegion.dstOffset.z = 0; - resolveRegion.extent.width = 1; - resolveRegion.extent.height = 1; - resolveRegion.extent.depth = 1; - m_commandBuffer->ResolveImage(srcImage.handle(), VK_IMAGE_LAYOUT_GENERAL, dstImage.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, - &resolveRegion); - m_commandBuffer->end(); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, ResolveImageHighSampleCount) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkCmdResolveImage called with dest sample count greater than 1."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // Create two images of sample count 4 and try to Resolve between them - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM; - image_create_info.extent.width = 32; - image_create_info.extent.height = 1; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_4_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - // Note: Some implementations expect color attachment usage for any - // multisample surface - image_create_info.usage = - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - image_create_info.flags = 0; - - VkImageObj srcImage(m_device); - srcImage.init(&image_create_info); - ASSERT_TRUE(srcImage.initialized()); - - VkImageObj dstImage(m_device); - dstImage.init(&image_create_info); - ASSERT_TRUE(dstImage.initialized()); - - m_commandBuffer->begin(); - // Need memory barrier to VK_IMAGE_LAYOUT_GENERAL for source and dest? - // VK_IMAGE_LAYOUT_UNDEFINED = 0, - // VK_IMAGE_LAYOUT_GENERAL = 1, - VkImageResolve resolveRegion; - resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - resolveRegion.srcSubresource.mipLevel = 0; - resolveRegion.srcSubresource.baseArrayLayer = 0; - resolveRegion.srcSubresource.layerCount = 1; - resolveRegion.srcOffset.x = 0; - resolveRegion.srcOffset.y = 0; - resolveRegion.srcOffset.z = 0; - resolveRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - resolveRegion.dstSubresource.mipLevel = 0; - resolveRegion.dstSubresource.baseArrayLayer = 0; - resolveRegion.dstSubresource.layerCount = 1; - resolveRegion.dstOffset.x = 0; - resolveRegion.dstOffset.y = 0; - resolveRegion.dstOffset.z = 0; - resolveRegion.extent.width = 1; - resolveRegion.extent.height = 1; - resolveRegion.extent.depth = 1; - m_commandBuffer->ResolveImage(srcImage.handle(), VK_IMAGE_LAYOUT_GENERAL, dstImage.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, - &resolveRegion); - m_commandBuffer->end(); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, ResolveImageFormatMismatch) { - VkResult err; - bool pass; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, - "vkCmdResolveImage called with unmatched source and dest formats."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // Create two images of different types and try to copy between them - VkImage srcImage; - VkImage dstImage; - VkDeviceMemory srcMem; - VkDeviceMemory destMem; - VkMemoryRequirements memReqs; - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM; - image_create_info.extent.width = 32; - image_create_info.extent.height = 1; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_2_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - // Note: Some implementations expect color attachment usage for any - // multisample surface - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - image_create_info.flags = 0; - - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &srcImage); - ASSERT_VK_SUCCESS(err); - - // Set format to something other than source image - image_create_info.format = VK_FORMAT_R32_SFLOAT; - // Note: Some implementations expect color attachment usage for any - // multisample surface - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &dstImage); - ASSERT_VK_SUCCESS(err); - - // Allocate memory - VkMemoryAllocateInfo memAlloc = {}; - memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memAlloc.pNext = NULL; - memAlloc.allocationSize = 0; - memAlloc.memoryTypeIndex = 0; - - vkGetImageMemoryRequirements(m_device->device(), srcImage, &memReqs); - memAlloc.allocationSize = memReqs.size; - pass = m_device->phy().set_memory_type(memReqs.memoryTypeBits, &memAlloc, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(m_device->device(), &memAlloc, NULL, &srcMem); - ASSERT_VK_SUCCESS(err); - - vkGetImageMemoryRequirements(m_device->device(), dstImage, &memReqs); - memAlloc.allocationSize = memReqs.size; - pass = m_device->phy().set_memory_type(memReqs.memoryTypeBits, &memAlloc, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(m_device->device(), &memAlloc, NULL, &destMem); - ASSERT_VK_SUCCESS(err); - - err = vkBindImageMemory(m_device->device(), srcImage, srcMem, 0); - ASSERT_VK_SUCCESS(err); - err = vkBindImageMemory(m_device->device(), dstImage, destMem, 0); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - // Need memory barrier to VK_IMAGE_LAYOUT_GENERAL for source and dest? - // VK_IMAGE_LAYOUT_UNDEFINED = 0, - // VK_IMAGE_LAYOUT_GENERAL = 1, - VkImageResolve resolveRegion; - resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - resolveRegion.srcSubresource.mipLevel = 0; - resolveRegion.srcSubresource.baseArrayLayer = 0; - resolveRegion.srcSubresource.layerCount = 1; - resolveRegion.srcOffset.x = 0; - resolveRegion.srcOffset.y = 0; - resolveRegion.srcOffset.z = 0; - resolveRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - resolveRegion.dstSubresource.mipLevel = 0; - resolveRegion.dstSubresource.baseArrayLayer = 0; - resolveRegion.dstSubresource.layerCount = 1; - resolveRegion.dstOffset.x = 0; - resolveRegion.dstOffset.y = 0; - resolveRegion.dstOffset.z = 0; - resolveRegion.extent.width = 1; - resolveRegion.extent.height = 1; - resolveRegion.extent.depth = 1; - m_commandBuffer->ResolveImage(srcImage, VK_IMAGE_LAYOUT_GENERAL, dstImage, VK_IMAGE_LAYOUT_GENERAL, 1, &resolveRegion); - m_commandBuffer->end(); - - m_errorMonitor->VerifyFound(); - - vkDestroyImage(m_device->device(), srcImage, NULL); - vkDestroyImage(m_device->device(), dstImage, NULL); - vkFreeMemory(m_device->device(), srcMem, NULL); - vkFreeMemory(m_device->device(), destMem, NULL); -} - -TEST_F(VkLayerTest, ResolveImageTypeMismatch) { - VkResult err; - bool pass; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, - "vkCmdResolveImage called with unmatched source and dest image types."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // Create two images of different types and try to copy between them - VkImage srcImage; - VkImage dstImage; - VkDeviceMemory srcMem; - VkDeviceMemory destMem; - VkMemoryRequirements memReqs; - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM; - image_create_info.extent.width = 32; - image_create_info.extent.height = 1; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_2_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - // Note: Some implementations expect color attachment usage for any - // multisample surface - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - image_create_info.flags = 0; - - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &srcImage); - ASSERT_VK_SUCCESS(err); - - image_create_info.imageType = VK_IMAGE_TYPE_1D; - // Note: Some implementations expect color attachment usage for any - // multisample surface - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &dstImage); - ASSERT_VK_SUCCESS(err); - - // Allocate memory - VkMemoryAllocateInfo memAlloc = {}; - memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memAlloc.pNext = NULL; - memAlloc.allocationSize = 0; - memAlloc.memoryTypeIndex = 0; - - vkGetImageMemoryRequirements(m_device->device(), srcImage, &memReqs); - memAlloc.allocationSize = memReqs.size; - pass = m_device->phy().set_memory_type(memReqs.memoryTypeBits, &memAlloc, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(m_device->device(), &memAlloc, NULL, &srcMem); - ASSERT_VK_SUCCESS(err); - - vkGetImageMemoryRequirements(m_device->device(), dstImage, &memReqs); - memAlloc.allocationSize = memReqs.size; - pass = m_device->phy().set_memory_type(memReqs.memoryTypeBits, &memAlloc, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(m_device->device(), &memAlloc, NULL, &destMem); - ASSERT_VK_SUCCESS(err); - - err = vkBindImageMemory(m_device->device(), srcImage, srcMem, 0); - ASSERT_VK_SUCCESS(err); - err = vkBindImageMemory(m_device->device(), dstImage, destMem, 0); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - // Need memory barrier to VK_IMAGE_LAYOUT_GENERAL for source and dest? - // VK_IMAGE_LAYOUT_UNDEFINED = 0, - // VK_IMAGE_LAYOUT_GENERAL = 1, - VkImageResolve resolveRegion; - resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - resolveRegion.srcSubresource.mipLevel = 0; - resolveRegion.srcSubresource.baseArrayLayer = 0; - resolveRegion.srcSubresource.layerCount = 1; - resolveRegion.srcOffset.x = 0; - resolveRegion.srcOffset.y = 0; - resolveRegion.srcOffset.z = 0; - resolveRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - resolveRegion.dstSubresource.mipLevel = 0; - resolveRegion.dstSubresource.baseArrayLayer = 0; - resolveRegion.dstSubresource.layerCount = 1; - resolveRegion.dstOffset.x = 0; - resolveRegion.dstOffset.y = 0; - resolveRegion.dstOffset.z = 0; - resolveRegion.extent.width = 1; - resolveRegion.extent.height = 1; - resolveRegion.extent.depth = 1; - m_commandBuffer->ResolveImage(srcImage, VK_IMAGE_LAYOUT_GENERAL, dstImage, VK_IMAGE_LAYOUT_GENERAL, 1, &resolveRegion); - m_commandBuffer->end(); - - m_errorMonitor->VerifyFound(); - - vkDestroyImage(m_device->device(), srcImage, NULL); - vkDestroyImage(m_device->device(), dstImage, NULL); - vkFreeMemory(m_device->device(), srcMem, NULL); - vkFreeMemory(m_device->device(), destMem, NULL); -} - -TEST_F(VkLayerTest, ResolveImageLayoutMismatch) { - ASSERT_NO_FATAL_FAILURE(Init()); - - // Create two images of different types and try to copy between them - VkImageObj srcImage(m_device); - VkImageObj dstImage(m_device); - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM; - image_create_info.extent.width = 32; - image_create_info.extent.height = 32; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_2_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = - VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - // Note: Some implementations expect color attachment usage for any - // multisample surface - image_create_info.flags = 0; - srcImage.init(&image_create_info); - ASSERT_TRUE(srcImage.initialized()); - - // Note: Some implementations expect color attachment usage for any - // multisample surface - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - dstImage.init(&image_create_info); - ASSERT_TRUE(dstImage.initialized()); - - m_commandBuffer->begin(); - // source image must have valid contents before resolve - VkClearColorValue clear_color = {{0, 0, 0, 0}}; - VkImageSubresourceRange subresource = {}; - subresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresource.layerCount = 1; - subresource.levelCount = 1; - srcImage.SetLayout(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - m_commandBuffer->ClearColorImage(srcImage.image(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &subresource); - srcImage.SetLayout(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - dstImage.SetLayout(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - VkImageResolve resolveRegion; - resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - resolveRegion.srcSubresource.mipLevel = 0; - resolveRegion.srcSubresource.baseArrayLayer = 0; - resolveRegion.srcSubresource.layerCount = 1; - resolveRegion.srcOffset.x = 0; - resolveRegion.srcOffset.y = 0; - resolveRegion.srcOffset.z = 0; - resolveRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - resolveRegion.dstSubresource.mipLevel = 0; - resolveRegion.dstSubresource.baseArrayLayer = 0; - resolveRegion.dstSubresource.layerCount = 1; - resolveRegion.dstOffset.x = 0; - resolveRegion.dstOffset.y = 0; - resolveRegion.dstOffset.z = 0; - resolveRegion.extent.width = 1; - resolveRegion.extent.height = 1; - resolveRegion.extent.depth = 1; - // source image layout mismatch - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdResolveImage-srcImageLayout-00260"); - m_commandBuffer->ResolveImage(srcImage.image(), VK_IMAGE_LAYOUT_GENERAL, dstImage.image(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, &resolveRegion); - m_errorMonitor->VerifyFound(); - // dst image layout mismatch - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdResolveImage-dstImageLayout-00262"); - m_commandBuffer->ResolveImage(srcImage.image(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage.image(), VK_IMAGE_LAYOUT_GENERAL, - 1, &resolveRegion); - m_errorMonitor->VerifyFound(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, ResolveInvalidSubresource) { - ASSERT_NO_FATAL_FAILURE(Init()); - - // Create two images of different types and try to copy between them - VkImageObj srcImage(m_device); - VkImageObj dstImage(m_device); - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM; - image_create_info.extent.width = 32; - image_create_info.extent.height = 32; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_2_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = - VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - // Note: Some implementations expect color attachment usage for any - // multisample surface - image_create_info.flags = 0; - srcImage.init(&image_create_info); - ASSERT_TRUE(srcImage.initialized()); - - // Note: Some implementations expect color attachment usage for any - // multisample surface - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - dstImage.init(&image_create_info); - ASSERT_TRUE(dstImage.initialized()); - - m_commandBuffer->begin(); - // source image must have valid contents before resolve - VkClearColorValue clear_color = {{0, 0, 0, 0}}; - VkImageSubresourceRange subresource = {}; - subresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresource.layerCount = 1; - subresource.levelCount = 1; - srcImage.SetLayout(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - m_commandBuffer->ClearColorImage(srcImage.image(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &subresource); - srcImage.SetLayout(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - dstImage.SetLayout(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - VkImageResolve resolveRegion; - resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - resolveRegion.srcSubresource.mipLevel = 0; - resolveRegion.srcSubresource.baseArrayLayer = 0; - resolveRegion.srcSubresource.layerCount = 1; - resolveRegion.srcOffset.x = 0; - resolveRegion.srcOffset.y = 0; - resolveRegion.srcOffset.z = 0; - resolveRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - resolveRegion.dstSubresource.mipLevel = 0; - resolveRegion.dstSubresource.baseArrayLayer = 0; - resolveRegion.dstSubresource.layerCount = 1; - resolveRegion.dstOffset.x = 0; - resolveRegion.dstOffset.y = 0; - resolveRegion.dstOffset.z = 0; - resolveRegion.extent.width = 1; - resolveRegion.extent.height = 1; - resolveRegion.extent.depth = 1; - // invalid source mip level - resolveRegion.srcSubresource.mipLevel = image_create_info.mipLevels; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdResolveImage-srcSubresource-01709"); - m_commandBuffer->ResolveImage(srcImage.image(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage.image(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &resolveRegion); - m_errorMonitor->VerifyFound(); - resolveRegion.srcSubresource.mipLevel = 0; - // invalid dest mip level - resolveRegion.dstSubresource.mipLevel = image_create_info.mipLevels; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdResolveImage-dstSubresource-01710"); - m_commandBuffer->ResolveImage(srcImage.image(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage.image(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &resolveRegion); - m_errorMonitor->VerifyFound(); - resolveRegion.dstSubresource.mipLevel = 0; - // invalid source array layer range - resolveRegion.srcSubresource.baseArrayLayer = image_create_info.arrayLayers; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdResolveImage-srcSubresource-01711"); - m_commandBuffer->ResolveImage(srcImage.image(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage.image(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &resolveRegion); - m_errorMonitor->VerifyFound(); - resolveRegion.srcSubresource.baseArrayLayer = 0; - // invalid dest array layer range - resolveRegion.dstSubresource.baseArrayLayer = image_create_info.arrayLayers; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdResolveImage-dstSubresource-01712"); - m_commandBuffer->ResolveImage(srcImage.image(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage.image(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &resolveRegion); - m_errorMonitor->VerifyFound(); - resolveRegion.dstSubresource.baseArrayLayer = 0; - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, DepthStencilImageViewWithColorAspectBitError) { - // Create a single Image descriptor and cause it to first hit an error due - // to using a DS format, then cause it to hit error due to COLOR_BIT not - // set in aspect - // The image format check comes 2nd in validation so we trigger it first, - // then when we cause aspect fail next, bad format check will be preempted - VkResult err; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "Combination depth/stencil image formats can have only the "); - - ASSERT_NO_FATAL_FAILURE(Init()); - auto depth_format = FindSupportedDepthStencilFormat(gpu()); - if (!depth_format) { - printf("%s Couldn't find depth stencil format.\n", kSkipPrefix); - return; - } - - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool; - err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 0; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding}); - - VkDescriptorSet descriptorSet; - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorSetCount = 1; - alloc_info.descriptorPool = ds_pool; - alloc_info.pSetLayouts = &ds_layout.handle(); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptorSet); - ASSERT_VK_SUCCESS(err); - - VkImage image_bad; - VkImage image_good; - // One bad format and one good format for Color attachment - const VkFormat tex_format_bad = depth_format; - const VkFormat tex_format_good = VK_FORMAT_B8G8R8A8_UNORM; - const int32_t tex_width = 32; - const int32_t tex_height = 32; - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = tex_format_bad; - image_create_info.extent.width = tex_width; - image_create_info.extent.height = tex_height; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - image_create_info.flags = 0; - - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image_bad); - ASSERT_VK_SUCCESS(err); - image_create_info.format = tex_format_good; - image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image_good); - ASSERT_VK_SUCCESS(err); - - // ---Bind image memory--- - VkMemoryRequirements img_mem_reqs; - vkGetImageMemoryRequirements(m_device->device(), image_bad, &img_mem_reqs); - VkMemoryAllocateInfo image_alloc_info = {}; - image_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - image_alloc_info.pNext = NULL; - image_alloc_info.memoryTypeIndex = 0; - image_alloc_info.allocationSize = img_mem_reqs.size; - bool pass = - m_device->phy().set_memory_type(img_mem_reqs.memoryTypeBits, &image_alloc_info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - ASSERT_TRUE(pass); - VkDeviceMemory mem; - err = vkAllocateMemory(m_device->device(), &image_alloc_info, NULL, &mem); - ASSERT_VK_SUCCESS(err); - err = vkBindImageMemory(m_device->device(), image_bad, mem, 0); - ASSERT_VK_SUCCESS(err); - // ----------------------- - - VkImageViewCreateInfo image_view_create_info = {}; - image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - image_view_create_info.image = image_bad; - image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - image_view_create_info.format = tex_format_bad; - image_view_create_info.subresourceRange.baseArrayLayer = 0; - image_view_create_info.subresourceRange.baseMipLevel = 0; - image_view_create_info.subresourceRange.layerCount = 1; - image_view_create_info.subresourceRange.levelCount = 1; - image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT; - - VkImageView view; - err = vkCreateImageView(m_device->device(), &image_view_create_info, NULL, &view); - - m_errorMonitor->VerifyFound(); - - vkDestroyImage(m_device->device(), image_bad, NULL); - vkDestroyImage(m_device->device(), image_good, NULL); - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); - - vkFreeMemory(m_device->device(), mem, NULL); -} - -TEST_F(VkLayerTest, ClearImageErrors) { - TEST_DESCRIPTION("Call ClearColorImage w/ a depth|stencil image and ClearDepthStencilImage with a color image."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - m_commandBuffer->begin(); - - // Color image - VkClearColorValue clear_color; - memset(clear_color.uint32, 0, sizeof(uint32_t) * 4); - const VkFormat color_format = VK_FORMAT_B8G8R8A8_UNORM; - const int32_t img_width = 32; - const int32_t img_height = 32; - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = color_format; - image_create_info.extent.width = img_width; - image_create_info.extent.height = img_height; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - - image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - vk_testing::Image color_image_no_transfer; - color_image_no_transfer.init(*m_device, image_create_info); - - image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - vk_testing::Image color_image; - color_image.init(*m_device, image_create_info); - - const VkImageSubresourceRange color_range = vk_testing::Image::subresource_range(image_create_info, VK_IMAGE_ASPECT_COLOR_BIT); - - // Depth/Stencil image - VkClearDepthStencilValue clear_value = {0}; - VkImageCreateInfo ds_image_create_info = vk_testing::Image::create_info(); - ds_image_create_info.imageType = VK_IMAGE_TYPE_2D; - ds_image_create_info.format = VK_FORMAT_D16_UNORM; - ds_image_create_info.extent.width = 64; - ds_image_create_info.extent.height = 64; - ds_image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - ds_image_create_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - - vk_testing::Image ds_image; - ds_image.init(*m_device, ds_image_create_info); - - const VkImageSubresourceRange ds_range = vk_testing::Image::subresource_range(ds_image_create_info, VK_IMAGE_ASPECT_DEPTH_BIT); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "vkCmdClearColorImage called with depth/stencil image."); - - vkCmdClearColorImage(m_commandBuffer->handle(), ds_image.handle(), VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &color_range); - - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkCmdClearColorImage called with image created without VK_IMAGE_USAGE_TRANSFER_DST_BIT"); - - vkCmdClearColorImage(m_commandBuffer->handle(), color_image_no_transfer.handle(), VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, - &color_range); - - m_errorMonitor->VerifyFound(); - - // Call CmdClearDepthStencilImage with color image - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkCmdClearDepthStencilImage called without a depth/stencil image."); - - vkCmdClearDepthStencilImage(m_commandBuffer->handle(), color_image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_value, - 1, &ds_range); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CommandQueueFlags) { - TEST_DESCRIPTION( - "Allocate a command buffer on a queue that does not support graphics and try to issue a graphics-only command"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - uint32_t queueFamilyIndex = m_device->QueueFamilyWithoutCapabilities(VK_QUEUE_GRAPHICS_BIT); - if (queueFamilyIndex == UINT32_MAX) { - printf("%s Non-graphics queue family not found; skipped.\n", kSkipPrefix); - return; - } else { - // Create command pool on a non-graphics queue - VkCommandPoolObj command_pool(m_device, queueFamilyIndex); - - // Setup command buffer on pool - VkCommandBufferObj command_buffer(m_device, &command_pool); - command_buffer.begin(); - - // Issue a graphics only command - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-commandBuffer-cmdpool"); - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - command_buffer.SetViewport(0, 1, &viewport); - m_errorMonitor->VerifyFound(); - } -} - -TEST_F(VkLayerTest, ExecuteUnrecordedSecondaryCB) { - TEST_DESCRIPTION("Attempt vkCmdExecuteCommands with a CB in the initial state"); - ASSERT_NO_FATAL_FAILURE(Init()); - VkCommandBufferObj secondary(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); - // never record secondary - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdExecuteCommands-pCommandBuffers-00089"); - m_commandBuffer->begin(); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary.handle()); - m_errorMonitor->VerifyFound(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, ExecuteUnrecordedPrimaryCB) { - TEST_DESCRIPTION("Attempt vkQueueSubmit with a CB in the initial state"); - ASSERT_NO_FATAL_FAILURE(Init()); - // never record m_commandBuffer - - VkSubmitInfo si = {}; - si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - si.commandBufferCount = 1; - si.pCommandBuffers = &m_commandBuffer->handle(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkQueueSubmit-pCommandBuffers-00072"); - vkQueueSubmit(m_device->m_queue, 1, &si, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); -} -TEST_F(VkLayerTest, ExecuteSecondaryCBWithLayoutMismatch) { - TEST_DESCRIPTION("Attempt vkCmdExecuteCommands with a CB with incorrect initial layout."); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM; - image_create_info.extent.width = 32; - image_create_info.extent.height = 1; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - image_create_info.flags = 0; - - VkImageSubresource image_sub = VkImageObj::subresource(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0); - VkImageSubresourceRange image_sub_range = VkImageObj::subresource_range(image_sub); - - VkImageObj image(m_device); - image.init(&image_create_info); - ASSERT_TRUE(image.initialized()); - VkImageMemoryBarrier image_barrier = - image.image_memory_barrier(0, 0, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, image_sub_range); - - auto pipeline = [&image_barrier](const VkCommandBufferObj &cb, VkImageLayout old_layout, VkImageLayout new_layout) { - image_barrier.oldLayout = old_layout; - image_barrier.newLayout = new_layout; - vkCmdPipelineBarrier(cb.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, - nullptr, 1, &image_barrier); - }; - - // Validate that mismatched use of image layout in secondary command buffer is caught at record time - VkCommandBufferObj secondary(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); - secondary.begin(); - pipeline(secondary, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - secondary.end(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "UNASSIGNED-vkCmdExecuteCommands-commandBuffer-00001"); - m_commandBuffer->begin(); - pipeline(*m_commandBuffer, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary.handle()); - m_errorMonitor->VerifyFound(); - - // Validate that we've tracked the changes from the secondary CB correctly - m_errorMonitor->ExpectSuccess(); - pipeline(*m_commandBuffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL); - m_errorMonitor->VerifyNotFound(); - m_commandBuffer->end(); - - m_commandBuffer->reset(); - secondary.reset(); - - // Validate that UNDEFINED doesn't false positive on us - secondary.begin(); - pipeline(secondary, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - secondary.end(); - m_commandBuffer->begin(); - pipeline(*m_commandBuffer, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - m_errorMonitor->ExpectSuccess(); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary.handle()); - m_errorMonitor->VerifyNotFound(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, ExtensionNotEnabled) { - TEST_DESCRIPTION("Validate that using an API from an unenabled extension returns an error"); - - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - // Required extensions except VK_KHR_GET_MEMORY_REQUIREMENTS_2 -- to create the needed error - std::vector<const char *> required_device_extensions = {VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, - VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME}; - for (auto dev_ext : required_device_extensions) { - if (DeviceExtensionSupported(gpu(), nullptr, dev_ext)) { - m_device_extension_names.push_back(dev_ext); - } else { - printf("%s Did not find required device extension %s; skipped.\n", kSkipPrefix, dev_ext); - break; - } - } - - // Need to ignore this error to get to the one we're testing - m_errorMonitor->SetUnexpectedError("VUID-vkCreateDevice-ppEnabledExtensionNames-01387"); - ASSERT_NO_FATAL_FAILURE(InitState()); - - // Find address of extension API - auto vkCreateSamplerYcbcrConversionKHR = - (PFN_vkCreateSamplerYcbcrConversionKHR)vkGetDeviceProcAddr(m_device->handle(), "vkCreateSamplerYcbcrConversionKHR"); - if (vkCreateSamplerYcbcrConversionKHR == nullptr) { - printf("%s VK_KHR_sampler_ycbcr_conversion not supported by device; skipped.\n", kSkipPrefix); - return; - } - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "UNASSIGNED-GeneralParameterError-ExtensionNotEnabled"); - VkSamplerYcbcrConversionCreateInfo ycbcr_info = {VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO, - NULL, - VK_FORMAT_UNDEFINED, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, - VK_SAMPLER_YCBCR_RANGE_ITU_FULL, - {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, - VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}, - VK_CHROMA_LOCATION_COSITED_EVEN, - VK_CHROMA_LOCATION_COSITED_EVEN, - VK_FILTER_NEAREST, - false}; - VkSamplerYcbcrConversion conversion; - vkCreateSamplerYcbcrConversionKHR(m_device->handle(), &ycbcr_info, nullptr, &conversion); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, Maintenance1AndNegativeViewport) { - TEST_DESCRIPTION("Attempt to enable AMD_negative_viewport_height and Maintenance1_KHR extension simultaneously"); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (!((DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME)) && - (DeviceExtensionSupported(gpu(), nullptr, VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME)))) { - printf("%s Maintenance1 and AMD_negative viewport height extensions not supported, skipping test\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - vk_testing::QueueCreateInfoArray queue_info(m_device->queue_props); - const char *extension_names[2] = {"VK_KHR_maintenance1", "VK_AMD_negative_viewport_height"}; - VkDevice testDevice; - VkDeviceCreateInfo device_create_info = {}; - auto features = m_device->phy().features(); - device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - device_create_info.pNext = NULL; - device_create_info.queueCreateInfoCount = queue_info.size(); - device_create_info.pQueueCreateInfos = queue_info.data(); - device_create_info.enabledLayerCount = 0; - device_create_info.ppEnabledLayerNames = NULL; - device_create_info.enabledExtensionCount = 2; - device_create_info.ppEnabledExtensionNames = (const char *const *)extension_names; - device_create_info.pEnabledFeatures = &features; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-00374"); - // The following unexpected error is coming from the LunarG loader. Do not make it a desired message because platforms that do - // not use the LunarG loader (e.g. Android) will not see the message and the test will fail. - m_errorMonitor->SetUnexpectedError("Failed to create device chain."); - vkCreateDevice(gpu(), &device_create_info, NULL, &testDevice); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, InvalidCreateDescriptorPool) { - TEST_DESCRIPTION("Attempt to create descriptor pool with invalid parameters"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - const uint32_t default_descriptor_count = 1; - const VkDescriptorPoolSize dp_size_template{VK_DESCRIPTOR_TYPE_SAMPLER, default_descriptor_count}; - - const VkDescriptorPoolCreateInfo dp_ci_template{VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - nullptr, // pNext - 0, // flags - 1, // maxSets - 1, // poolSizeCount - &dp_size_template}; - - // try maxSets = 0 - { - VkDescriptorPoolCreateInfo invalid_dp_ci = dp_ci_template; - invalid_dp_ci.maxSets = 0; // invalid maxSets value - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorPoolCreateInfo-maxSets-00301"); - { - VkDescriptorPool pool; - vkCreateDescriptorPool(m_device->device(), &invalid_dp_ci, nullptr, &pool); - } - m_errorMonitor->VerifyFound(); - } - - // try descriptorCount = 0 - { - VkDescriptorPoolSize invalid_dp_size = dp_size_template; - invalid_dp_size.descriptorCount = 0; // invalid descriptorCount value - - VkDescriptorPoolCreateInfo dp_ci = dp_ci_template; - dp_ci.pPoolSizes = &invalid_dp_size; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorPoolSize-descriptorCount-00302"); - { - VkDescriptorPool pool; - vkCreateDescriptorPool(m_device->device(), &dp_ci, nullptr, &pool); - } - m_errorMonitor->VerifyFound(); - } -} - -TEST_F(VkLayerTest, InvalidCreateBufferSize) { - TEST_DESCRIPTION("Attempt to create VkBuffer with size of zero"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkBufferCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferCreateInfo-size-00912"); - info.size = 0; - VkBuffer buffer; - vkCreateBuffer(m_device->device(), &info, nullptr, &buffer); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, SetDynViewportParamTests) { - TEST_DESCRIPTION("Test parameters of vkCmdSetViewport without multiViewport feature"); - - SetTargetApiVersion(VK_API_VERSION_1_1); - VkPhysicalDeviceFeatures features{}; - ASSERT_NO_FATAL_FAILURE(Init(&features)); - - const VkViewport vp = {0.0, 0.0, 64.0, 64.0, 0.0, 1.0}; - const VkViewport viewports[] = {vp, vp}; - - m_commandBuffer->begin(); - - // array tests - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-firstViewport-01224"); - vkCmdSetViewport(m_commandBuffer->handle(), 1, 1, viewports); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-viewportCount-arraylength"); - vkCmdSetViewport(m_commandBuffer->handle(), 0, 0, nullptr); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-viewportCount-01225"); - vkCmdSetViewport(m_commandBuffer->handle(), 0, 2, viewports); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-firstViewport-01224"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-viewportCount-arraylength"); - vkCmdSetViewport(m_commandBuffer->handle(), 1, 0, viewports); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-firstViewport-01224"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-viewportCount-01225"); - vkCmdSetViewport(m_commandBuffer->handle(), 1, 2, viewports); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-pViewports-parameter"); - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, nullptr); - m_errorMonitor->VerifyFound(); - - // core viewport tests - using std::vector; - struct TestCase { - VkViewport vp; - std::string veid; - }; - - // not necessarily boundary values (unspecified cast rounding), but guaranteed to be over limit - const auto one_past_max_w = NearestGreater(static_cast<float>(m_device->props.limits.maxViewportDimensions[0])); - const auto one_past_max_h = NearestGreater(static_cast<float>(m_device->props.limits.maxViewportDimensions[1])); - - const auto min_bound = m_device->props.limits.viewportBoundsRange[0]; - const auto max_bound = m_device->props.limits.viewportBoundsRange[1]; - const auto one_before_min_bounds = NearestSmaller(min_bound); - const auto one_past_max_bounds = NearestGreater(max_bound); - - const auto below_zero = NearestSmaller(0.0f); - const auto past_one = NearestGreater(1.0f); - - vector<TestCase> test_cases = { - {{0.0, 0.0, 0.0, 64.0, 0.0, 1.0}, "VUID-VkViewport-width-01770"}, - {{0.0, 0.0, one_past_max_w, 64.0, 0.0, 1.0}, "VUID-VkViewport-width-01771"}, - {{0.0, 0.0, NAN, 64.0, 0.0, 1.0}, "VUID-VkViewport-width-01770"}, - {{0.0, 0.0, 64.0, one_past_max_h, 0.0, 1.0}, "VUID-VkViewport-height-01773"}, - {{one_before_min_bounds, 0.0, 64.0, 64.0, 0.0, 1.0}, "VUID-VkViewport-x-01774"}, - {{one_past_max_bounds, 0.0, 64.0, 64.0, 0.0, 1.0}, "VUID-VkViewport-x-01232"}, - {{NAN, 0.0, 64.0, 64.0, 0.0, 1.0}, "VUID-VkViewport-x-01774"}, - {{0.0, one_before_min_bounds, 64.0, 64.0, 0.0, 1.0}, "VUID-VkViewport-y-01775"}, - {{0.0, NAN, 64.0, 64.0, 0.0, 1.0}, "VUID-VkViewport-y-01775"}, - {{max_bound, 0.0, 1.0, 64.0, 0.0, 1.0}, "VUID-VkViewport-x-01232"}, - {{0.0, max_bound, 64.0, 1.0, 0.0, 1.0}, "VUID-VkViewport-y-01233"}, - {{0.0, 0.0, 64.0, 64.0, below_zero, 1.0}, "VUID-VkViewport-minDepth-01234"}, - {{0.0, 0.0, 64.0, 64.0, past_one, 1.0}, "VUID-VkViewport-minDepth-01234"}, - {{0.0, 0.0, 64.0, 64.0, NAN, 1.0}, "VUID-VkViewport-minDepth-01234"}, - {{0.0, 0.0, 64.0, 64.0, 0.0, below_zero}, "VUID-VkViewport-maxDepth-01235"}, - {{0.0, 0.0, 64.0, 64.0, 0.0, past_one}, "VUID-VkViewport-maxDepth-01235"}, - {{0.0, 0.0, 64.0, 64.0, 0.0, NAN}, "VUID-VkViewport-maxDepth-01235"}, - }; - - if (DeviceValidationVersion() < VK_API_VERSION_1_1) { - test_cases.push_back({{0.0, 0.0, 64.0, 0.0, 0.0, 1.0}, "VUID-VkViewport-height-01772"}); - test_cases.push_back({{0.0, 0.0, 64.0, NAN, 0.0, 1.0}, "VUID-VkViewport-height-01772"}); - } else { - test_cases.push_back({{0.0, 0.0, 64.0, NAN, 0.0, 1.0}, "VUID-VkViewport-height-01773"}); - } - - for (const auto &test_case : test_cases) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.veid); - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &test_case.vp); - m_errorMonitor->VerifyFound(); - } -} - -void NegHeightViewportTests(VkDeviceObj *m_device, VkCommandBufferObj *m_commandBuffer, ErrorMonitor *m_errorMonitor) { - const auto &limits = m_device->props.limits; - - m_commandBuffer->begin(); - - using std::vector; - struct TestCase { - VkViewport vp; - vector<std::string> vuids; - }; - - // not necessarily boundary values (unspecified cast rounding), but guaranteed to be over limit - const auto one_before_min_h = NearestSmaller(-static_cast<float>(limits.maxViewportDimensions[1])); - const auto one_past_max_h = NearestGreater(static_cast<float>(limits.maxViewportDimensions[1])); - - const auto min_bound = limits.viewportBoundsRange[0]; - const auto max_bound = limits.viewportBoundsRange[1]; - const auto one_before_min_bound = NearestSmaller(min_bound); - const auto one_past_max_bound = NearestGreater(max_bound); - - const vector<TestCase> test_cases = {{{0.0, 0.0, 64.0, one_before_min_h, 0.0, 1.0}, {"VUID-VkViewport-height-01773"}}, - {{0.0, 0.0, 64.0, one_past_max_h, 0.0, 1.0}, {"VUID-VkViewport-height-01773"}}, - {{0.0, 0.0, 64.0, NAN, 0.0, 1.0}, {"VUID-VkViewport-height-01773"}}, - {{0.0, one_before_min_bound, 64.0, 1.0, 0.0, 1.0}, {"VUID-VkViewport-y-01775"}}, - {{0.0, one_past_max_bound, 64.0, -1.0, 0.0, 1.0}, {"VUID-VkViewport-y-01776"}}, - {{0.0, min_bound, 64.0, -1.0, 0.0, 1.0}, {"VUID-VkViewport-y-01777"}}, - {{0.0, max_bound, 64.0, 1.0, 0.0, 1.0}, {"VUID-VkViewport-y-01233"}}}; - - for (const auto &test_case : test_cases) { - for (const auto vuid : test_case.vuids) { - if (vuid == "VUID-Undefined") - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "is less than VkPhysicalDeviceLimits::viewportBoundsRange[0]"); - else - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid); - } - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &test_case.vp); - m_errorMonitor->VerifyFound(); - } -} - -TEST_F(VkLayerTest, SetDynViewportParamMaintenance1Tests) { - TEST_DESCRIPTION("Verify errors are detected on misuse of SetViewport with a negative viewport extension enabled."); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - } else { - printf("%s VK_KHR_maintenance1 extension not supported -- skipping test\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - NegHeightViewportTests(m_device, m_commandBuffer, m_errorMonitor); -} - -TEST_F(VkLayerTest, SetDynViewportParamMultiviewportTests) { - TEST_DESCRIPTION("Test parameters of vkCmdSetViewport with multiViewport feature enabled"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - if (!m_device->phy().features().multiViewport) { - printf("%s VkPhysicalDeviceFeatures::multiViewport is not supported -- skipping test.\n", kSkipPrefix); - return; - } - - const auto max_viewports = m_device->props.limits.maxViewports; - const uint32_t too_many_viewports = 65536 + 1; // let's say this is too much to allocate pViewports for - - m_commandBuffer->begin(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-viewportCount-arraylength"); - vkCmdSetViewport(m_commandBuffer->handle(), 0, 0, nullptr); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-pViewports-parameter"); - vkCmdSetViewport(m_commandBuffer->handle(), 0, max_viewports, nullptr); - m_errorMonitor->VerifyFound(); - - if (max_viewports >= too_many_viewports) { - printf( - "%s VkPhysicalDeviceLimits::maxViewports is too large to practically test against -- skipping " - "part of " - "test.\n", - kSkipPrefix); - return; - } - - const VkViewport vp = {0.0, 0.0, 64.0, 64.0, 0.0, 1.0}; - const std::vector<VkViewport> viewports(max_viewports + 1, vp); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-firstViewport-01223"); - vkCmdSetViewport(m_commandBuffer->handle(), 0, max_viewports + 1, viewports.data()); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-firstViewport-01223"); - vkCmdSetViewport(m_commandBuffer->handle(), max_viewports, 1, viewports.data()); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-firstViewport-01223"); - vkCmdSetViewport(m_commandBuffer->handle(), 1, max_viewports, viewports.data()); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-viewportCount-arraylength"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetViewport-firstViewport-01223"); - vkCmdSetViewport(m_commandBuffer->handle(), max_viewports + 1, 0, viewports.data()); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, BadRenderPassScopeSecondaryCmdBuffer) { - TEST_DESCRIPTION( - "Test secondary buffers executed in wrong render pass scope wrt VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkCommandBufferObj sec_cmdbuff_inside_rp(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); - VkCommandBufferObj sec_cmdbuff_outside_rp(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); - - const VkCommandBufferInheritanceInfo cmdbuff_ii = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, - nullptr, // pNext - m_renderPass, - 0, // subpass - m_framebuffer, - }; - const VkCommandBufferBeginInfo cmdbuff_bi_tmpl = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - nullptr, // pNext - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, &cmdbuff_ii}; - - VkCommandBufferBeginInfo cmdbuff_inside_rp_bi = cmdbuff_bi_tmpl; - cmdbuff_inside_rp_bi.flags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; - sec_cmdbuff_inside_rp.begin(&cmdbuff_inside_rp_bi); - sec_cmdbuff_inside_rp.end(); - - VkCommandBufferBeginInfo cmdbuff_outside_rp_bi = cmdbuff_bi_tmpl; - cmdbuff_outside_rp_bi.flags &= ~VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; - sec_cmdbuff_outside_rp.begin(&cmdbuff_outside_rp_bi); - sec_cmdbuff_outside_rp.end(); - - m_commandBuffer->begin(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdExecuteCommands-pCommandBuffers-00100"); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &sec_cmdbuff_inside_rp.handle()); - m_errorMonitor->VerifyFound(); - - const VkRenderPassBeginInfo rp_bi{VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - nullptr, // pNext - m_renderPass, - m_framebuffer, - {{0, 0}, {32, 32}}, - static_cast<uint32_t>(m_renderPassClearValues.size()), - m_renderPassClearValues.data()}; - vkCmdBeginRenderPass(m_commandBuffer->handle(), &rp_bi, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdExecuteCommands-pCommandBuffers-00096"); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &sec_cmdbuff_outside_rp.handle()); - m_errorMonitor->VerifyFound(); -} - -// -// POSITIVE VALIDATION TESTS -// -// These tests do not expect to encounter ANY validation errors pass only if this is true - -TEST_F(VkPositiveLayerTest, StatelessValidationDisable) { - TEST_DESCRIPTION("Specify a non-zero value for a reserved parameter with stateless validation disabled"); - - VkValidationFeatureDisableEXT disables[] = {VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT}; - VkValidationFeaturesEXT features = {}; - features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT; - features.disabledValidationFeatureCount = 1; - features.pDisabledValidationFeatures = disables; - VkCommandPoolCreateFlags pool_flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, pool_flags, &features)); - - m_errorMonitor->ExpectSuccess(); - // Specify 0 for a reserved VkFlags parameter. Normally this is expected to trigger an stateless validation error, but this - // validation was disabled via the features extension, so no errors should be forthcoming. - VkEvent event_handle = VK_NULL_HANDLE; - VkEventCreateInfo event_info = {}; - event_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - event_info.flags = 1; - vkCreateEvent(device(), &event_info, NULL, &event_handle); - vkDestroyEvent(device(), event_handle, NULL); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, PointSizeWriteInFunction) { - TEST_DESCRIPTION("Create a pipeline using TOPOLOGY_POINT_LIST and write PointSize in vertex shader function."); - - ASSERT_NO_FATAL_FAILURE(Init()); - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(InitViewport()); - - // Create VS declaring PointSize and write to it in a function call. - static const char PointSizeWriteVertShaderFcn[] = - "#version 450\n" - "vec2 vertices[3];\n" - "out gl_PerVertex\n" - "{\n" - " vec4 gl_Position;\n" - " float gl_PointSize;\n" - "};\n" - "void OutPointSize() {\n" - " gl_PointSize = 7.0;\n" - "}\n" - "void main() {\n" - " vertices[0] = vec2(-1.0, -1.0);\n" - " vertices[1] = vec2( 1.0, -1.0);\n" - " vertices[2] = vec2( 0.0, 1.0);\n" - " gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);\n" - " OutPointSize();\n" - "}\n"; - - VkShaderObj vs(m_device, PointSizeWriteVertShaderFcn, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj ps(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - { - VkPipelineObj pipelineobj(m_device); - pipelineobj.AddDefaultColorAttachment(); - pipelineobj.AddShader(&vs); - pipelineobj.AddShader(&ps); - - // Set Input Assembly to TOPOLOGY POINT LIST - VkPipelineInputAssemblyStateCreateInfo ia_state = {}; - ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - ia_state.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; - pipelineobj.SetInputAssembly(&ia_state); - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - m_commandBuffer->begin(); - m_commandBuffer->ClearAllBuffers(m_renderTargets, m_clear_color, m_depthStencil, m_depth_clear_color, - m_stencil_clear_color); - m_commandBuffer->PrepareAttachments(m_renderTargets, m_depthStencil); - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - } - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, PointSizeGeomShaderSuccess) { - TEST_DESCRIPTION( - "Create a pipeline using TOPOLOGY_POINT_LIST, set PointSize vertex shader, and write in the final geometry stage."); - - ASSERT_NO_FATAL_FAILURE(Init()); - m_errorMonitor->ExpectSuccess(); - - if ((!m_device->phy().features().geometryShader) || (!m_device->phy().features().shaderTessellationAndGeometryPointSize)) { - printf("%s Device does not support the required geometry shader features; skipped.\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitViewport()); - - // Create VS declaring PointSize and writing to it - static const char PointSizeVertShader[] = - "#version 450\n" - "vec2 vertices[3];\n" - "out gl_PerVertex\n" - "{\n" - " vec4 gl_Position;\n" - " float gl_PointSize;\n" - "};\n" - "void main() {\n" - " vertices[0] = vec2(-1.0, -1.0);\n" - " vertices[1] = vec2( 1.0, -1.0);\n" - " vertices[2] = vec2( 0.0, 1.0);\n" - " gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);\n" - " gl_PointSize = 5.0;\n" - "}\n"; - static char const *gsSource = - "#version 450\n" - "layout (points) in;\n" - "layout (points) out;\n" - "layout (max_vertices = 1) out;\n" - "void main() {\n" - " gl_Position = vec4(1.0, 0.5, 0.5, 0.0);\n" - " gl_PointSize = 3.3;\n" - " EmitVertex();\n" - "}\n"; - - VkShaderObj vs(m_device, PointSizeVertShader, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj gs(m_device, gsSource, VK_SHADER_STAGE_GEOMETRY_BIT, this); - VkShaderObj ps(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipelineobj(m_device); - pipelineobj.AddDefaultColorAttachment(); - pipelineobj.AddShader(&vs); - pipelineobj.AddShader(&gs); - pipelineobj.AddShader(&ps); - - // Set Input Assembly to TOPOLOGY POINT LIST - VkPipelineInputAssemblyStateCreateInfo ia_state = {}; - ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - ia_state.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; - pipelineobj.SetInputAssembly(&ia_state); - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - m_commandBuffer->begin(); - m_commandBuffer->ClearAllBuffers(m_renderTargets, m_clear_color, m_depthStencil, m_depth_clear_color, m_stencil_clear_color); - m_commandBuffer->PrepareAttachments(m_renderTargets, m_depthStencil); - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, LoosePointSizeWrite) { - TEST_DESCRIPTION("Create a pipeline using TOPOLOGY_POINT_LIST and write PointSize outside of a structure."); - - ASSERT_NO_FATAL_FAILURE(Init()); - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(InitViewport()); - - const std::string LoosePointSizeWrite = R"( - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %glposition %glpointsize %gl_VertexIndex - OpSource GLSL 450 - OpName %main "main" - OpName %vertices "vertices" - OpName %glposition "glposition" - OpName %glpointsize "glpointsize" - OpName %gl_VertexIndex "gl_VertexIndex" - OpDecorate %glposition BuiltIn Position - OpDecorate %glpointsize BuiltIn PointSize - OpDecorate %gl_VertexIndex BuiltIn VertexIndex - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %uint = OpTypeInt 32 0 - %uint_3 = OpConstant %uint 3 - %_arr_v2float_uint_3 = OpTypeArray %v2float %uint_3 - %_ptr_Private__arr_v2float_uint_3 = OpTypePointer Private %_arr_v2float_uint_3 - %vertices = OpVariable %_ptr_Private__arr_v2float_uint_3 Private - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %float_n1 = OpConstant %float -1 - %16 = OpConstantComposite %v2float %float_n1 %float_n1 - %_ptr_Private_v2float = OpTypePointer Private %v2float - %int_1 = OpConstant %int 1 - %float_1 = OpConstant %float 1 - %21 = OpConstantComposite %v2float %float_1 %float_n1 - %int_2 = OpConstant %int 2 - %float_0 = OpConstant %float 0 - %25 = OpConstantComposite %v2float %float_0 %float_1 - %v4float = OpTypeVector %float 4 - %_ptr_Output_gl_Position = OpTypePointer Output %v4float - %glposition = OpVariable %_ptr_Output_gl_Position Output - %_ptr_Output_gl_PointSize = OpTypePointer Output %float - %glpointsize = OpVariable %_ptr_Output_gl_PointSize Output - %_ptr_Input_int = OpTypePointer Input %int - %gl_VertexIndex = OpVariable %_ptr_Input_int Input - %int_3 = OpConstant %int 3 - %_ptr_Output_v4float = OpTypePointer Output %v4float - %_ptr_Output_float = OpTypePointer Output %float - %main = OpFunction %void None %3 - %5 = OpLabel - %18 = OpAccessChain %_ptr_Private_v2float %vertices %int_0 - OpStore %18 %16 - %22 = OpAccessChain %_ptr_Private_v2float %vertices %int_1 - OpStore %22 %21 - %26 = OpAccessChain %_ptr_Private_v2float %vertices %int_2 - OpStore %26 %25 - %33 = OpLoad %int %gl_VertexIndex - %35 = OpSMod %int %33 %int_3 - %36 = OpAccessChain %_ptr_Private_v2float %vertices %35 - %37 = OpLoad %v2float %36 - %38 = OpCompositeExtract %float %37 0 - %39 = OpCompositeExtract %float %37 1 - %40 = OpCompositeConstruct %v4float %38 %39 %float_0 %float_1 - %42 = OpAccessChain %_ptr_Output_v4float %glposition - OpStore %42 %40 - OpStore %glpointsize %float_1 - OpReturn - OpFunctionEnd - )"; - - // Create VS declaring PointSize and write to it in a function call. - VkShaderObj vs(m_device, LoosePointSizeWrite, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj ps(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - { - VkPipelineObj pipelineobj(m_device); - pipelineobj.AddDefaultColorAttachment(); - pipelineobj.AddShader(&vs); - pipelineobj.AddShader(&ps); - - // Set Input Assembly to TOPOLOGY POINT LIST - VkPipelineInputAssemblyStateCreateInfo ia_state = {}; - ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - ia_state.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; - pipelineobj.SetInputAssembly(&ia_state); - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - m_commandBuffer->begin(); - m_commandBuffer->ClearAllBuffers(m_renderTargets, m_clear_color, m_depthStencil, m_depth_clear_color, - m_stencil_clear_color); - m_commandBuffer->PrepareAttachments(m_renderTargets, m_depthStencil); - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - } - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, UncompressedToCompressedImageCopy) { - TEST_DESCRIPTION("Image copies between compressed and uncompressed images"); - ASSERT_NO_FATAL_FAILURE(Init()); - - // Verify format support - // Size-compatible (64-bit) formats. Uncompressed is 64 bits per texel, compressed is 64 bits per 4x4 block (or 4bpt). - if (!ImageFormatAndFeaturesSupported(gpu(), VK_FORMAT_R16G16B16A16_UINT, VK_IMAGE_TILING_OPTIMAL, - VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR | VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR) || - !ImageFormatAndFeaturesSupported(gpu(), VK_FORMAT_BC1_RGBA_SRGB_BLOCK, VK_IMAGE_TILING_OPTIMAL, - VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR | VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR)) { - printf("%s Required formats/features not supported - UncompressedToCompressedImageCopy skipped.\n", kSkipPrefix); - return; - } - - VkImageObj uncomp_10x10t_image(m_device); // Size = 10 * 10 * 64 = 6400 - VkImageObj comp_10x10b_40x40t_image(m_device); // Size = 40 * 40 * 4 = 6400 - - uncomp_10x10t_image.Init(10, 10, 1, VK_FORMAT_R16G16B16A16_UINT, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL); - comp_10x10b_40x40t_image.Init(40, 40, 1, VK_FORMAT_BC1_RGBA_SRGB_BLOCK, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL); - - if (!uncomp_10x10t_image.initialized() || !comp_10x10b_40x40t_image.initialized()) { - printf("%s Unable to initialize surfaces - UncompressedToCompressedImageCopy skipped.\n", kSkipPrefix); - return; - } - - // Both copies represent the same number of bytes. Bytes Per Texel = 1 for bc6, 16 for uncompressed - // Copy compressed to uncompressed - VkImageCopy copy_region = {}; - copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region.srcSubresource.mipLevel = 0; - copy_region.dstSubresource.mipLevel = 0; - copy_region.srcSubresource.baseArrayLayer = 0; - copy_region.dstSubresource.baseArrayLayer = 0; - copy_region.srcSubresource.layerCount = 1; - copy_region.dstSubresource.layerCount = 1; - copy_region.srcOffset = {0, 0, 0}; - copy_region.dstOffset = {0, 0, 0}; - - m_errorMonitor->ExpectSuccess(); - m_commandBuffer->begin(); - - // Copy from uncompressed to compressed - copy_region.extent = {10, 10, 1}; // Dimensions in (uncompressed) texels - vkCmdCopyImage(m_commandBuffer->handle(), uncomp_10x10t_image.handle(), VK_IMAGE_LAYOUT_GENERAL, - comp_10x10b_40x40t_image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); - - // And from compressed to uncompressed - copy_region.extent = {40, 40, 1}; // Dimensions in (compressed) texels - vkCmdCopyImage(m_commandBuffer->handle(), comp_10x10b_40x40t_image.handle(), VK_IMAGE_LAYOUT_GENERAL, - uncomp_10x10t_image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ©_region); - - m_errorMonitor->VerifyNotFound(); - m_commandBuffer->end(); -} - -TEST_F(VkPositiveLayerTest, DeleteDescriptorSetLayoutsBeforeDescriptorSets) { - TEST_DESCRIPTION("Create DSLayouts and DescriptorSets and then delete the DSLayouts before the DescriptorSets."); - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - VkResult err; - - m_errorMonitor->ExpectSuccess(); - - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_SAMPLER; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool_one; - err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool_one); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 0; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding.pImmutableSamplers = NULL; - - VkDescriptorSet descriptorSet; - { - const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding}); - - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorSetCount = 1; - alloc_info.descriptorPool = ds_pool_one; - alloc_info.pSetLayouts = &ds_layout.handle(); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptorSet); - ASSERT_VK_SUCCESS(err); - } // ds_layout destroyed - err = vkFreeDescriptorSets(m_device->device(), ds_pool_one, 1, &descriptorSet); - - vkDestroyDescriptorPool(m_device->device(), ds_pool_one, NULL); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, CommandPoolDeleteWithReferences) { - TEST_DESCRIPTION("Ensure the validation layers bookkeeping tracks the implicit command buffer frees."); - ASSERT_NO_FATAL_FAILURE(Init()); - - VkCommandPoolCreateInfo cmd_pool_info = {}; - cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - cmd_pool_info.pNext = NULL; - cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - cmd_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - cmd_pool_info.flags = 0; - - VkCommandPool secondary_cmd_pool; - VkResult res = vkCreateCommandPool(m_device->handle(), &cmd_pool_info, NULL, &secondary_cmd_pool); - ASSERT_VK_SUCCESS(res); - - VkCommandBufferAllocateInfo cmdalloc = vk_testing::CommandBuffer::create_info(secondary_cmd_pool); - cmdalloc.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY; - - VkCommandBuffer secondary_cmds; - res = vkAllocateCommandBuffers(m_device->handle(), &cmdalloc, &secondary_cmds); - - VkCommandBufferInheritanceInfo cmd_buf_inheritance_info = {}; - cmd_buf_inheritance_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; - cmd_buf_inheritance_info.pNext = NULL; - cmd_buf_inheritance_info.renderPass = VK_NULL_HANDLE; - cmd_buf_inheritance_info.subpass = 0; - cmd_buf_inheritance_info.framebuffer = VK_NULL_HANDLE; - cmd_buf_inheritance_info.occlusionQueryEnable = VK_FALSE; - cmd_buf_inheritance_info.queryFlags = 0; - cmd_buf_inheritance_info.pipelineStatistics = 0; - - VkCommandBufferBeginInfo secondary_begin = {}; - secondary_begin.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - secondary_begin.pNext = NULL; - secondary_begin.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - secondary_begin.pInheritanceInfo = &cmd_buf_inheritance_info; - - res = vkBeginCommandBuffer(secondary_cmds, &secondary_begin); - ASSERT_VK_SUCCESS(res); - vkEndCommandBuffer(secondary_cmds); - - m_commandBuffer->begin(); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary_cmds); - m_commandBuffer->end(); - - // DestroyCommandPool *implicitly* frees the command buffers allocated from it - vkDestroyCommandPool(m_device->handle(), secondary_cmd_pool, NULL); - // If bookkeeping has been lax, validating the reset will attempt to touch deleted data - res = vkResetCommandPool(m_device->handle(), m_commandPool->handle(), 0); - ASSERT_VK_SUCCESS(res); -} - -TEST_F(VkLayerTest, SecondaryCommandBufferClearColorAttachmentsRenderArea) { - TEST_DESCRIPTION( - "Create a secondary command buffer with CmdClearAttachments call that has a rect outside of renderPass renderArea"); - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkCommandBufferAllocateInfo command_buffer_allocate_info = {}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = m_commandPool->handle(); - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY; - command_buffer_allocate_info.commandBufferCount = 1; - - VkCommandBuffer secondary_command_buffer; - ASSERT_VK_SUCCESS(vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, &secondary_command_buffer)); - VkCommandBufferBeginInfo command_buffer_begin_info = {}; - VkCommandBufferInheritanceInfo command_buffer_inheritance_info = {}; - command_buffer_inheritance_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; - command_buffer_inheritance_info.renderPass = m_renderPass; - command_buffer_inheritance_info.framebuffer = m_framebuffer; - - command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - command_buffer_begin_info.flags = - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; - command_buffer_begin_info.pInheritanceInfo = &command_buffer_inheritance_info; - - vkBeginCommandBuffer(secondary_command_buffer, &command_buffer_begin_info); - VkClearAttachment color_attachment; - color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - color_attachment.clearValue.color.float32[0] = 0; - color_attachment.clearValue.color.float32[1] = 0; - color_attachment.clearValue.color.float32[2] = 0; - color_attachment.clearValue.color.float32[3] = 0; - color_attachment.colorAttachment = 0; - // x extent of 257 exceeds render area of 256 - VkClearRect clear_rect = {{{0, 0}, {257, 32}}}; - vkCmdClearAttachments(secondary_command_buffer, 1, &color_attachment, 1, &clear_rect); - vkEndCommandBuffer(secondary_command_buffer); - m_commandBuffer->begin(); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearAttachments-pRects-00016"); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary_command_buffer); - m_errorMonitor->VerifyFound(); - - vkCmdEndRenderPass(m_commandBuffer->handle()); - m_commandBuffer->end(); -} - -TEST_F(VkPositiveLayerTest, SecondaryCommandBufferClearColorAttachments) { - TEST_DESCRIPTION("Create a secondary command buffer and record a CmdClearAttachments call into it"); - m_errorMonitor->ExpectSuccess(); - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkCommandBufferAllocateInfo command_buffer_allocate_info = {}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = m_commandPool->handle(); - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY; - command_buffer_allocate_info.commandBufferCount = 1; - - VkCommandBuffer secondary_command_buffer; - ASSERT_VK_SUCCESS(vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, &secondary_command_buffer)); - VkCommandBufferBeginInfo command_buffer_begin_info = {}; - VkCommandBufferInheritanceInfo command_buffer_inheritance_info = {}; - command_buffer_inheritance_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; - command_buffer_inheritance_info.renderPass = m_renderPass; - command_buffer_inheritance_info.framebuffer = m_framebuffer; - - command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - command_buffer_begin_info.flags = - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; - command_buffer_begin_info.pInheritanceInfo = &command_buffer_inheritance_info; - - vkBeginCommandBuffer(secondary_command_buffer, &command_buffer_begin_info); - VkClearAttachment color_attachment; - color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - color_attachment.clearValue.color.float32[0] = 0; - color_attachment.clearValue.color.float32[1] = 0; - color_attachment.clearValue.color.float32[2] = 0; - color_attachment.clearValue.color.float32[3] = 0; - color_attachment.colorAttachment = 0; - VkClearRect clear_rect = {{{0, 0}, {32, 32}}}; - vkCmdClearAttachments(secondary_command_buffer, 1, &color_attachment, 1, &clear_rect); - vkEndCommandBuffer(secondary_command_buffer); - m_commandBuffer->begin(); - vkCmdBeginRenderPass(m_commandBuffer->handle(), &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); - vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary_command_buffer); - vkCmdEndRenderPass(m_commandBuffer->handle()); - m_commandBuffer->end(); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, SecondaryCommandBufferImageLayoutTransitions) { - TEST_DESCRIPTION("Perform an image layout transition in a secondary command buffer followed by a transition in the primary."); - VkResult err; - m_errorMonitor->ExpectSuccess(); - ASSERT_NO_FATAL_FAILURE(Init()); - auto depth_format = FindSupportedDepthStencilFormat(gpu()); - if (!depth_format) { - printf("%s Couldn't find depth stencil format.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - // Allocate a secondary and primary cmd buffer - VkCommandBufferAllocateInfo command_buffer_allocate_info = {}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = m_commandPool->handle(); - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY; - command_buffer_allocate_info.commandBufferCount = 1; - - VkCommandBuffer secondary_command_buffer; - ASSERT_VK_SUCCESS(vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, &secondary_command_buffer)); - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - VkCommandBuffer primary_command_buffer; - ASSERT_VK_SUCCESS(vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, &primary_command_buffer)); - VkCommandBufferBeginInfo command_buffer_begin_info = {}; - VkCommandBufferInheritanceInfo command_buffer_inheritance_info = {}; - command_buffer_inheritance_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; - command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - command_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - command_buffer_begin_info.pInheritanceInfo = &command_buffer_inheritance_info; - - err = vkBeginCommandBuffer(secondary_command_buffer, &command_buffer_begin_info); - ASSERT_VK_SUCCESS(err); - VkImageObj image(m_device); - image.Init(128, 128, 1, depth_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - VkImageMemoryBarrier img_barrier = {}; - img_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - img_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; - img_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - img_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - img_barrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - img_barrier.image = image.handle(); - img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - img_barrier.subresourceRange.baseArrayLayer = 0; - img_barrier.subresourceRange.baseMipLevel = 0; - img_barrier.subresourceRange.layerCount = 1; - img_barrier.subresourceRange.levelCount = 1; - vkCmdPipelineBarrier(secondary_command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, - 0, nullptr, 1, &img_barrier); - err = vkEndCommandBuffer(secondary_command_buffer); - ASSERT_VK_SUCCESS(err); - - // Now update primary cmd buffer to execute secondary and transitions image - command_buffer_begin_info.pInheritanceInfo = nullptr; - err = vkBeginCommandBuffer(primary_command_buffer, &command_buffer_begin_info); - ASSERT_VK_SUCCESS(err); - vkCmdExecuteCommands(primary_command_buffer, 1, &secondary_command_buffer); - VkImageMemoryBarrier img_barrier2 = {}; - img_barrier2.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - img_barrier2.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; - img_barrier2.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - img_barrier2.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - img_barrier2.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - img_barrier2.image = image.handle(); - img_barrier2.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier2.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier2.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - img_barrier2.subresourceRange.baseArrayLayer = 0; - img_barrier2.subresourceRange.baseMipLevel = 0; - img_barrier2.subresourceRange.layerCount = 1; - img_barrier2.subresourceRange.levelCount = 1; - vkCmdPipelineBarrier(primary_command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &img_barrier2); - err = vkEndCommandBuffer(primary_command_buffer); - ASSERT_VK_SUCCESS(err); - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &primary_command_buffer; - err = vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - ASSERT_VK_SUCCESS(err); - m_errorMonitor->VerifyNotFound(); - err = vkDeviceWaitIdle(m_device->device()); - ASSERT_VK_SUCCESS(err); - vkFreeCommandBuffers(m_device->device(), m_commandPool->handle(), 1, &secondary_command_buffer); - vkFreeCommandBuffers(m_device->device(), m_commandPool->handle(), 1, &primary_command_buffer); -} - -// This is a positive test. No failures are expected. -TEST_F(VkPositiveLayerTest, IgnoreUnrelatedDescriptor) { - TEST_DESCRIPTION( - "Ensure that the vkUpdateDescriptorSets validation code is ignoring VkWriteDescriptorSet members that are not related to " - "the descriptor type specified by VkWriteDescriptorSet::descriptorType. Correct validation behavior will result in the " - "test running to completion without validation errors."); - - const uintptr_t invalid_ptr = 0xcdcdcdcd; - - ASSERT_NO_FATAL_FAILURE(Init()); - - // Verify VK_FORMAT_R8_UNORM supports VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT - const VkFormat format_texel_case = VK_FORMAT_R8_UNORM; - const char *format_texel_case_string = "VK_FORMAT_R8_UNORM"; - VkFormatProperties format_properties; - vkGetPhysicalDeviceFormatProperties(gpu(), format_texel_case, &format_properties); - if (!(format_properties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT)) { - printf("%s Test requires %s to support VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT\n", kSkipPrefix, format_texel_case_string); - return; - } - - // Image Case - { - m_errorMonitor->ExpectSuccess(); - - VkImageObj image(m_device); - image.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - - VkImageView view = image.targetView(VK_FORMAT_B8G8R8A8_UNORM); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - VkDescriptorImageInfo image_info = {}; - image_info.imageView = view; - image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - descriptor_write.pImageInfo = &image_info; - - // Set pBufferInfo and pTexelBufferView to invalid values, which should - // be - // ignored for descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE. - // This will most likely produce a crash if the parameter_validation - // layer - // does not correctly ignore pBufferInfo. - descriptor_write.pBufferInfo = reinterpret_cast<const VkDescriptorBufferInfo *>(invalid_ptr); - descriptor_write.pTexelBufferView = reinterpret_cast<const VkBufferView *>(invalid_ptr); - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - m_errorMonitor->VerifyNotFound(); - } - - // Buffer Case - { - m_errorMonitor->ExpectSuccess(); - - VkBuffer buffer; - uint32_t queue_family_index = 0; - VkBufferCreateInfo buffer_create_info = {}; - buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_create_info.size = 1024; - buffer_create_info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - buffer_create_info.queueFamilyIndexCount = 1; - buffer_create_info.pQueueFamilyIndices = &queue_family_index; - - VkResult err = vkCreateBuffer(m_device->device(), &buffer_create_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - VkMemoryRequirements memory_reqs; - VkDeviceMemory buffer_memory; - bool pass; - VkMemoryAllocateInfo memory_info = {}; - memory_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_info.pNext = NULL; - memory_info.allocationSize = 0; - memory_info.memoryTypeIndex = 0; - - vkGetBufferMemoryRequirements(m_device->device(), buffer, &memory_reqs); - memory_info.allocationSize = memory_reqs.size; - pass = m_device->phy().set_memory_type(memory_reqs.memoryTypeBits, &memory_info, 0); - ASSERT_TRUE(pass); - - err = vkAllocateMemory(m_device->device(), &memory_info, NULL, &buffer_memory); - ASSERT_VK_SUCCESS(err); - err = vkBindBufferMemory(m_device->device(), buffer, buffer_memory, 0); - ASSERT_VK_SUCCESS(err); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - VkDescriptorBufferInfo buffer_info = {}; - buffer_info.buffer = buffer; - buffer_info.offset = 0; - buffer_info.range = 1024; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_write.pBufferInfo = &buffer_info; - - // Set pImageInfo and pTexelBufferView to invalid values, which should - // be - // ignored for descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER. - // This will most likely produce a crash if the parameter_validation - // layer - // does not correctly ignore pImageInfo. - descriptor_write.pImageInfo = reinterpret_cast<const VkDescriptorImageInfo *>(invalid_ptr); - descriptor_write.pTexelBufferView = reinterpret_cast<const VkBufferView *>(invalid_ptr); - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - m_errorMonitor->VerifyNotFound(); - - vkDestroyBuffer(m_device->device(), buffer, NULL); - vkFreeMemory(m_device->device(), buffer_memory, NULL); - } - - // Texel Buffer Case - { - m_errorMonitor->ExpectSuccess(); - - VkBuffer buffer; - uint32_t queue_family_index = 0; - VkBufferCreateInfo buffer_create_info = {}; - buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_create_info.size = 1024; - buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; - buffer_create_info.queueFamilyIndexCount = 1; - buffer_create_info.pQueueFamilyIndices = &queue_family_index; - - VkResult err = vkCreateBuffer(m_device->device(), &buffer_create_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - VkMemoryRequirements memory_reqs; - VkDeviceMemory buffer_memory; - bool pass; - VkMemoryAllocateInfo memory_info = {}; - memory_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_info.pNext = NULL; - memory_info.allocationSize = 0; - memory_info.memoryTypeIndex = 0; - - vkGetBufferMemoryRequirements(m_device->device(), buffer, &memory_reqs); - memory_info.allocationSize = memory_reqs.size; - pass = m_device->phy().set_memory_type(memory_reqs.memoryTypeBits, &memory_info, 0); - ASSERT_TRUE(pass); - - err = vkAllocateMemory(m_device->device(), &memory_info, NULL, &buffer_memory); - ASSERT_VK_SUCCESS(err); - err = vkBindBufferMemory(m_device->device(), buffer, buffer_memory, 0); - ASSERT_VK_SUCCESS(err); - - VkBufferViewCreateInfo buff_view_ci = {}; - buff_view_ci.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; - buff_view_ci.buffer = buffer; - buff_view_ci.format = format_texel_case; - buff_view_ci.range = VK_WHOLE_SIZE; - VkBufferView buffer_view; - err = vkCreateBufferView(m_device->device(), &buff_view_ci, NULL, &buffer_view); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - descriptor_write.pTexelBufferView = &buffer_view; - - // Set pImageInfo and pBufferInfo to invalid values, which should be - // ignored for descriptorType == - // VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER. - // This will most likely produce a crash if the parameter_validation - // layer - // does not correctly ignore pImageInfo and pBufferInfo. - descriptor_write.pImageInfo = reinterpret_cast<const VkDescriptorImageInfo *>(invalid_ptr); - descriptor_write.pBufferInfo = reinterpret_cast<const VkDescriptorBufferInfo *>(invalid_ptr); - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - m_errorMonitor->VerifyNotFound(); - - vkDestroyBufferView(m_device->device(), buffer_view, NULL); - vkDestroyBuffer(m_device->device(), buffer, NULL); - vkFreeMemory(m_device->device(), buffer_memory, NULL); - } -} - -TEST_F(VkPositiveLayerTest, ImmutableSamplerOnlyDescriptor) { - TEST_DESCRIPTION("Bind a DescriptorSet with only an immutable sampler and make sure that we don't warn for no update."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}, - }); - - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - VkSampler sampler; - VkResult err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler); - ASSERT_VK_SUCCESS(err); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - - m_errorMonitor->ExpectSuccess(); - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, &ds.set_, 0, - nullptr); - m_errorMonitor->VerifyNotFound(); - - vkDestroySampler(m_device->device(), sampler, NULL); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, DuplicateDescriptorBinding) { - TEST_DESCRIPTION("Create a descriptor set layout with a duplicate binding number."); - - ASSERT_NO_FATAL_FAILURE(Init()); - // Create layout where two binding #s are "1" - static const uint32_t NUM_BINDINGS = 3; - VkDescriptorSetLayoutBinding dsl_binding[NUM_BINDINGS] = {}; - dsl_binding[0].binding = 1; - dsl_binding[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - dsl_binding[0].descriptorCount = 1; - dsl_binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - dsl_binding[0].pImmutableSamplers = NULL; - dsl_binding[1].binding = 0; - dsl_binding[1].descriptorCount = 1; - dsl_binding[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - dsl_binding[1].descriptorCount = 1; - dsl_binding[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - dsl_binding[1].pImmutableSamplers = NULL; - dsl_binding[2].binding = 1; // Duplicate binding should cause error - dsl_binding[2].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - dsl_binding[2].descriptorCount = 1; - dsl_binding[2].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - dsl_binding[2].pImmutableSamplers = NULL; - - VkDescriptorSetLayoutCreateInfo ds_layout_ci = {}; - ds_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - ds_layout_ci.pNext = NULL; - ds_layout_ci.bindingCount = NUM_BINDINGS; - ds_layout_ci.pBindings = dsl_binding; - VkDescriptorSetLayout ds_layout; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorSetLayoutCreateInfo-binding-00279"); - vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, InvalidPushDescriptorSetLayout) { - TEST_DESCRIPTION("Create a push descriptor set layout with invalid bindings."); - - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Did not find VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME; skipped.\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - - // Get the push descriptor limits - auto push_descriptor_prop = GetPushDescriptorProperties(instance(), gpu()); - if (push_descriptor_prop.maxPushDescriptors < 1) { - // Some implementations report an invalid maxPushDescriptors of 0 - printf("%s maxPushDescriptors is zero, skipping tests\n", kSkipPrefix); - return; - } - - VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}; - - auto ds_layout_ci = lvl_init_struct<VkDescriptorSetLayoutCreateInfo>(); - ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; - ds_layout_ci.bindingCount = 1; - ds_layout_ci.pBindings = &binding; - - // Note that as binding is referenced in ds_layout_ci, it is effectively in the closure by reference as well. - auto test_create_ds_layout = [&ds_layout_ci, this](std::string error) { - VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, error); - vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout); - m_errorMonitor->VerifyFound(); - vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr); - }; - - // Starting with the initial VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC type set above.. - test_create_ds_layout("VUID-VkDescriptorSetLayoutCreateInfo-flags-00280"); - - binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; - test_create_ds_layout( - "VUID-VkDescriptorSetLayoutCreateInfo-flags-00280"); // This is the same VUID as above, just a second error condition. - - if (!(push_descriptor_prop.maxPushDescriptors == std::numeric_limits<uint32_t>::max())) { - binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - binding.descriptorCount = push_descriptor_prop.maxPushDescriptors + 1; - test_create_ds_layout("VUID-VkDescriptorSetLayoutCreateInfo-flags-00281"); - } else { - printf("%s maxPushDescriptors is set to maximum unit32_t value, skipping 'out of range test'.\n", kSkipPrefix); - } -} - -TEST_F(VkLayerTest, PushDescriptorSetLayoutWithoutExtension) { - TEST_DESCRIPTION("Create a push descriptor set layout without loading the needed extension."); - ASSERT_NO_FATAL_FAILURE(Init()); - - VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}; - - auto ds_layout_ci = lvl_init_struct<VkDescriptorSetLayoutCreateInfo>(); - ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; - ds_layout_ci.bindingCount = 1; - ds_layout_ci.pBindings = &binding; - - std::string error = "Attempted to use VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR in "; - error = error + "VkDescriptorSetLayoutCreateInfo::flags but its required extension "; - error = error + VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME; - error = error + " has not been enabled."; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, error.c_str()); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorSetLayoutCreateInfo-flags-00281"); - VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE; - vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout); - m_errorMonitor->VerifyFound(); - vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr); -} - -TEST_F(VkLayerTest, DescriptorIndexingSetLayoutWithoutExtension) { - TEST_DESCRIPTION("Create an update_after_bind set layout without loading the needed extension."); - ASSERT_NO_FATAL_FAILURE(Init()); - - auto ds_layout_ci = lvl_init_struct<VkDescriptorSetLayoutCreateInfo>(); - ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT; - - std::string error = "Attemped to use VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT in "; - error = error + "VkDescriptorSetLayoutCreateInfo::flags but its required extension "; - error = error + VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME; - error = error + " has not been enabled."; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, error.c_str()); - VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE; - vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout); - m_errorMonitor->VerifyFound(); - vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr); -} - -TEST_F(VkLayerTest, DescriptorIndexingSetLayout) { - TEST_DESCRIPTION("Exercise various create/allocate-time errors related to VK_EXT_descriptor_indexing."); - - if (!(CheckDescriptorIndexingSupportAndInitFramework(this, m_instance_extension_names, m_device_extension_names, NULL, - m_errorMonitor))) { - printf("Descriptor indexing or one of its dependencies not supported, skipping tests\n"); - return; - } - - PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = - (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR"); - ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr); - - // Create a device that enables all supported indexing features except descriptorBindingUniformBufferUpdateAfterBind - auto indexing_features = lvl_init_struct<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>(); - auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&indexing_features); - vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2); - - indexing_features.descriptorBindingUniformBufferUpdateAfterBind = VK_FALSE; - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); - - std::array<VkDescriptorBindingFlagsEXT, 2> flags = {VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT, - VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT}; - auto flags_create_info = lvl_init_struct<VkDescriptorSetLayoutBindingFlagsCreateInfoEXT>(); - flags_create_info.bindingCount = (uint32_t)flags.size(); - flags_create_info.pBindingFlags = flags.data(); - - VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}; - auto ds_layout_ci = lvl_init_struct<VkDescriptorSetLayoutCreateInfo>(&flags_create_info); - ds_layout_ci.bindingCount = 1; - ds_layout_ci.pBindings = &binding; - VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE; - - // VU for VkDescriptorSetLayoutBindingFlagsCreateInfoEXT::bindingCount - flags_create_info.bindingCount = 2; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-bindingCount-03002"); - VkResult err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout); - m_errorMonitor->VerifyFound(); - vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr); - - flags_create_info.bindingCount = 1; - - // set is missing UPDATE_AFTER_BIND_POOL flag. - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorSetLayoutCreateInfo-flags-03000"); - // binding uses a feature we disabled - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingUniformBufferUpdateAfterBind-03005"); - err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout); - m_errorMonitor->VerifyFound(); - vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr); - - ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT; - ds_layout_ci.bindingCount = 0; - flags_create_info.bindingCount = 0; - err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout); - ASSERT_VK_SUCCESS(err); - - VkDescriptorPoolSize pool_size = {binding.descriptorType, binding.descriptorCount}; - auto dspci = lvl_init_struct<VkDescriptorPoolCreateInfo>(); - dspci.poolSizeCount = 1; - dspci.pPoolSizes = &pool_size; - dspci.maxSets = 1; - VkDescriptorPool pool; - err = vkCreateDescriptorPool(m_device->handle(), &dspci, nullptr, &pool); - ASSERT_VK_SUCCESS(err); - - auto ds_alloc_info = lvl_init_struct<VkDescriptorSetAllocateInfo>(); - ds_alloc_info.descriptorPool = pool; - ds_alloc_info.descriptorSetCount = 1; - ds_alloc_info.pSetLayouts = &ds_layout; - - VkDescriptorSet ds = VK_NULL_HANDLE; - // mismatch between descriptor set and pool - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-03044"); - vkAllocateDescriptorSets(m_device->handle(), &ds_alloc_info, &ds); - m_errorMonitor->VerifyFound(); - - vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr); - vkDestroyDescriptorPool(m_device->handle(), pool, nullptr); - - if (indexing_features.descriptorBindingVariableDescriptorCount) { - ds_layout_ci.flags = 0; - ds_layout_ci.bindingCount = 1; - flags_create_info.bindingCount = 1; - flags[0] = VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT; - err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout); - ASSERT_VK_SUCCESS(err); - - pool_size = {binding.descriptorType, binding.descriptorCount}; - dspci = lvl_init_struct<VkDescriptorPoolCreateInfo>(); - dspci.poolSizeCount = 1; - dspci.pPoolSizes = &pool_size; - dspci.maxSets = 1; - err = vkCreateDescriptorPool(m_device->handle(), &dspci, nullptr, &pool); - ASSERT_VK_SUCCESS(err); - - auto count_alloc_info = lvl_init_struct<VkDescriptorSetVariableDescriptorCountAllocateInfoEXT>(); - count_alloc_info.descriptorSetCount = 1; - // Set variable count larger than what was in the descriptor binding - uint32_t variable_count = 2; - count_alloc_info.pDescriptorCounts = &variable_count; - - ds_alloc_info = lvl_init_struct<VkDescriptorSetAllocateInfo>(&count_alloc_info); - ds_alloc_info.descriptorPool = pool; - ds_alloc_info.descriptorSetCount = 1; - ds_alloc_info.pSetLayouts = &ds_layout; - - ds = VK_NULL_HANDLE; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkDescriptorSetVariableDescriptorCountAllocateInfoEXT-pSetLayouts-03046"); - vkAllocateDescriptorSets(m_device->handle(), &ds_alloc_info, &ds); - m_errorMonitor->VerifyFound(); - - vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr); - vkDestroyDescriptorPool(m_device->handle(), pool, nullptr); - } -} - -TEST_F(VkLayerTest, DescriptorIndexingUpdateAfterBind) { - TEST_DESCRIPTION("Exercise errors for updating a descriptor set after it is bound."); - - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME) && - DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE3_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME); - } else { - printf("%s Descriptor Indexing or Maintenance3 Extension not supported, skipping tests\n", kSkipPrefix); - return; - } - - PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = - (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR"); - ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr); - - // Create a device that enables all supported indexing features except descriptorBindingUniformBufferUpdateAfterBind - auto indexing_features = lvl_init_struct<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>(); - auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&indexing_features); - vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2); - - indexing_features.descriptorBindingUniformBufferUpdateAfterBind = VK_FALSE; - - if (VK_FALSE == indexing_features.descriptorBindingStorageBufferUpdateAfterBind) { - printf("%s Test requires (unsupported) descriptorBindingStorageBufferUpdateAfterBind, skipping\n", kSkipPrefix); - return; - } - if (VK_FALSE == features2.features.fragmentStoresAndAtomics) { - printf("%s Test requires (unsupported) fragmentStoresAndAtomics, skipping\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorBindingFlagsEXT flags[2] = {0, VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT}; - auto flags_create_info = lvl_init_struct<VkDescriptorSetLayoutBindingFlagsCreateInfoEXT>(); - flags_create_info.bindingCount = 2; - flags_create_info.pBindingFlags = &flags[0]; - - // Descriptor set has two bindings - only the second is update_after_bind - VkDescriptorSetLayoutBinding binding[2] = { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}, - {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}, - }; - auto ds_layout_ci = lvl_init_struct<VkDescriptorSetLayoutCreateInfo>(&flags_create_info); - ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT; - ds_layout_ci.bindingCount = 2; - ds_layout_ci.pBindings = &binding[0]; - VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE; - - VkResult err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout); - - VkDescriptorPoolSize pool_sizes[2] = { - {binding[0].descriptorType, binding[0].descriptorCount}, - {binding[1].descriptorType, binding[1].descriptorCount}, - }; - auto dspci = lvl_init_struct<VkDescriptorPoolCreateInfo>(); - dspci.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT; - dspci.poolSizeCount = 2; - dspci.pPoolSizes = &pool_sizes[0]; - dspci.maxSets = 1; - VkDescriptorPool pool; - err = vkCreateDescriptorPool(m_device->handle(), &dspci, nullptr, &pool); - ASSERT_VK_SUCCESS(err); - - auto ds_alloc_info = lvl_init_struct<VkDescriptorSetAllocateInfo>(); - ds_alloc_info.descriptorPool = pool; - ds_alloc_info.descriptorSetCount = 1; - ds_alloc_info.pSetLayouts = &ds_layout; - - VkDescriptorSet ds = VK_NULL_HANDLE; - vkAllocateDescriptorSets(m_device->handle(), &ds_alloc_info, &ds); - ASSERT_VK_SUCCESS(err); - - VkBufferCreateInfo buffCI = {}; - buffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffCI.size = 1024; - buffCI.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - - VkBuffer dyub; - err = vkCreateBuffer(m_device->device(), &buffCI, NULL, &dyub); - ASSERT_VK_SUCCESS(err); - - VkDeviceMemory mem; - VkMemoryRequirements mem_reqs; - vkGetBufferMemoryRequirements(m_device->device(), dyub, &mem_reqs); - - VkMemoryAllocateInfo mem_alloc_info = {}; - mem_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc_info.allocationSize = mem_reqs.size; - m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &mem_alloc_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - err = vkAllocateMemory(m_device->device(), &mem_alloc_info, NULL, &mem); - ASSERT_VK_SUCCESS(err); - - err = vkBindBufferMemory(m_device->device(), dyub, mem, 0); - ASSERT_VK_SUCCESS(err); - - VkDescriptorBufferInfo buffInfo[2] = {}; - buffInfo[0].buffer = dyub; - buffInfo[0].offset = 0; - buffInfo[0].range = 1024; - - VkWriteDescriptorSet descriptor_write[2] = {}; - descriptor_write[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write[0].dstSet = ds; - descriptor_write[0].dstBinding = 0; - descriptor_write[0].descriptorCount = 1; - descriptor_write[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_write[0].pBufferInfo = buffInfo; - descriptor_write[1] = descriptor_write[0]; - descriptor_write[1].dstBinding = 1; - descriptor_write[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - - VkPipelineLayout pipeline_layout; - VkPipelineLayoutCreateInfo pipeline_layout_ci = {}; - pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_ci.setLayoutCount = 1; - pipeline_layout_ci.pSetLayouts = &ds_layout; - - vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - - // Create a dummy pipeline, since VL inspects which bindings are actually used at draw time - char const *vsSource = - "#version 450\n" - "void main(){\n" - " gl_Position = vec4(0);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "layout(set=0, binding=0) uniform foo0 { float x0; } bar0;\n" - "layout(set=0, binding=1) buffer foo1 { float x1; } bar1;\n" - "void main(){\n" - " color = vec4(bar0.x0 + bar1.x1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.SetViewport(m_viewports); - pipe.SetScissor(m_scissors); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.CreateVKPipeline(pipeline_layout, m_renderPass); - - // Make both bindings valid before binding to the command buffer - vkUpdateDescriptorSets(m_device->device(), 2, &descriptor_write[0], 0, NULL); - m_errorMonitor->VerifyNotFound(); - - // Two subtests. First only updates the update_after_bind binding and expects - // no error. Second updates the other binding and expects an error when the - // command buffer is ended. - for (uint32_t i = 0; i < 2; ++i) { - m_commandBuffer->begin(); - - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &ds, 0, NULL); - - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdDraw(m_commandBuffer->handle(), 0, 0, 0, 0); - vkCmdEndRenderPass(m_commandBuffer->handle()); - - m_errorMonitor->VerifyNotFound(); - // Valid to update binding 1 after being bound - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write[1], 0, NULL); - m_errorMonitor->VerifyNotFound(); - - if (i == 0) { - // expect no errors - m_commandBuffer->end(); - m_errorMonitor->VerifyNotFound(); - } else { - // Invalid to update binding 0 after being bound. But the error is actually - // generated during vkEndCommandBuffer - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write[0], 0, NULL); - m_errorMonitor->VerifyNotFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "is invalid because bound DescriptorSet"); - - vkEndCommandBuffer(m_commandBuffer->handle()); - m_errorMonitor->VerifyFound(); - } - } - - vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr); - vkDestroyDescriptorPool(m_device->handle(), pool, nullptr); - vkDestroyBuffer(m_device->handle(), dyub, NULL); - vkFreeMemory(m_device->handle(), mem, NULL); - vkDestroyPipelineLayout(m_device->handle(), pipeline_layout, NULL); -} - -TEST_F(VkLayerTest, AllocatePushDescriptorSet) { - TEST_DESCRIPTION("Attempt to allocate a push descriptor set."); - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - auto push_descriptor_prop = GetPushDescriptorProperties(instance(), gpu()); - if (push_descriptor_prop.maxPushDescriptors < 1) { - // Some implementations report an invalid maxPushDescriptors of 0 - printf("%s maxPushDescriptors is zero, skipping tests\n", kSkipPrefix); - return; - } - - VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}; - auto ds_layout_ci = lvl_init_struct<VkDescriptorSetLayoutCreateInfo>(); - ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; - ds_layout_ci.bindingCount = 1; - ds_layout_ci.pBindings = &binding; - VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE; - VkResult err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout); - ASSERT_VK_SUCCESS(err); - - VkDescriptorPoolSize pool_size = {binding.descriptorType, binding.descriptorCount}; - auto dspci = lvl_init_struct<VkDescriptorPoolCreateInfo>(); - dspci.poolSizeCount = 1; - dspci.pPoolSizes = &pool_size; - dspci.maxSets = 1; - VkDescriptorPool pool; - err = vkCreateDescriptorPool(m_device->handle(), &dspci, nullptr, &pool); - ASSERT_VK_SUCCESS(err); - - auto ds_alloc_info = lvl_init_struct<VkDescriptorSetAllocateInfo>(); - ds_alloc_info.descriptorPool = pool; - ds_alloc_info.descriptorSetCount = 1; - ds_alloc_info.pSetLayouts = &ds_layout; - - VkDescriptorSet ds = VK_NULL_HANDLE; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-00308"); - vkAllocateDescriptorSets(m_device->handle(), &ds_alloc_info, &ds); - m_errorMonitor->VerifyFound(); - - vkDestroyDescriptorPool(m_device->handle(), pool, nullptr); - vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr); -} - -TEST_F(VkLayerTest, PushDescriptorSetCmdPushBadArgs) { - TEST_DESCRIPTION("Attempt to push a push descriptor set with incorrect arguments."); - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - auto push_descriptor_prop = GetPushDescriptorProperties(instance(), gpu()); - if (push_descriptor_prop.maxPushDescriptors < 1) { - // Some implementations report an invalid maxPushDescriptors of 0 - printf("%s maxPushDescriptors is zero, skipping tests\n", kSkipPrefix); - return; - } - - // Create ordinary and push descriptor set layout - VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}; - const VkDescriptorSetLayoutObj ds_layout(m_device, {binding}); - ASSERT_TRUE(ds_layout.initialized()); - const VkDescriptorSetLayoutObj push_ds_layout(m_device, {binding}, VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR); - ASSERT_TRUE(push_ds_layout.initialized()); - - // Now use the descriptor set layouts to create a pipeline layout - const VkPipelineLayoutObj pipeline_layout(m_device, {&push_ds_layout, &ds_layout}); - ASSERT_TRUE(pipeline_layout.initialized()); - - // Create a descriptor to push - const uint32_t buffer_data[4] = {4, 5, 6, 7}; - VkConstantBufferObj buffer_obj(m_device, sizeof(buffer_data), &buffer_data); - ASSERT_TRUE(buffer_obj.initialized()); - - // Create a "write" struct, noting that the buffer_info cannot be a temporary arg (the return from write_descriptor_set - // references its data), and the DescriptorSet() can be temporary, because the value is ignored - VkDescriptorBufferInfo buffer_info = {buffer_obj.handle(), 0, VK_WHOLE_SIZE}; - - VkWriteDescriptorSet descriptor_write = vk_testing::Device::write_descriptor_set( - vk_testing::DescriptorSet(), 0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, &buffer_info); - - // Find address of extension call and make the call - PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR = - (PFN_vkCmdPushDescriptorSetKHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdPushDescriptorSetKHR"); - ASSERT_TRUE(vkCmdPushDescriptorSetKHR != nullptr); - - // Section 1: Queue family matching/capabilities. - // Create command pool on a non-graphics queue - const uint32_t no_gfx_qfi = m_device->QueueFamilyMatching(VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_BIT); - const uint32_t transfer_only_qfi = - m_device->QueueFamilyMatching(VK_QUEUE_TRANSFER_BIT, (VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT)); - if ((UINT32_MAX == transfer_only_qfi) && (UINT32_MAX == no_gfx_qfi)) { - printf("%s No compute or transfer only queue family, skipping bindpoint and queue tests.", kSkipPrefix); - } else { - const uint32_t err_qfi = (UINT32_MAX == no_gfx_qfi) ? transfer_only_qfi : no_gfx_qfi; - - VkCommandPoolObj command_pool(m_device, err_qfi); - ASSERT_TRUE(command_pool.initialized()); - VkCommandBufferObj command_buffer(m_device, &command_pool); - ASSERT_TRUE(command_buffer.initialized()); - command_buffer.begin(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdPushDescriptorSetKHR-pipelineBindPoint-00363"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-00330"); - if (err_qfi == transfer_only_qfi) { - // This as this queue neither supports the gfx or compute bindpoints, we'll get two errors - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdPushDescriptorSetKHR-commandBuffer-cmdpool"); - } - vkCmdPushDescriptorSetKHR(command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptor_write); - m_errorMonitor->VerifyFound(); - command_buffer.end(); - - // If we succeed in testing only one condition above, we need to test the other below. - if ((UINT32_MAX != transfer_only_qfi) && (err_qfi != transfer_only_qfi)) { - // Need to test the neither compute/gfx supported case separately. - VkCommandPoolObj tran_command_pool(m_device, transfer_only_qfi); - ASSERT_TRUE(tran_command_pool.initialized()); - VkCommandBufferObj tran_command_buffer(m_device, &tran_command_pool); - ASSERT_TRUE(tran_command_buffer.initialized()); - tran_command_buffer.begin(); - - // We can't avoid getting *both* errors in this case - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdPushDescriptorSetKHR-pipelineBindPoint-00363"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-00330"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdPushDescriptorSetKHR-commandBuffer-cmdpool"); - vkCmdPushDescriptorSetKHR(tran_command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptor_write); - m_errorMonitor->VerifyFound(); - tran_command_buffer.end(); - } - } - - // Push to the non-push binding - m_commandBuffer->begin(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPushDescriptorSetKHR-set-00365"); - vkCmdPushDescriptorSetKHR(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 1, 1, - &descriptor_write); - m_errorMonitor->VerifyFound(); - - // Specify set out of bounds - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPushDescriptorSetKHR-set-00364"); - vkCmdPushDescriptorSetKHR(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 2, 1, - &descriptor_write); - m_errorMonitor->VerifyFound(); - m_commandBuffer->end(); - - // This is a test for VUID-vkCmdPushDescriptorSetKHR-commandBuffer-recording - // TODO: Add VALIDATION_ERROR_ code support to core_validation::ValidateCmd - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "You must call vkBeginCommandBuffer() before this call to vkCmdPushDescriptorSetKHR()"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-00330"); - vkCmdPushDescriptorSetKHR(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptor_write); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, SetDynScissorParamTests) { - TEST_DESCRIPTION("Test parameters of vkCmdSetScissor without multiViewport feature"); - - VkPhysicalDeviceFeatures features{}; - ASSERT_NO_FATAL_FAILURE(Init(&features)); - - const VkRect2D scissor = {{0, 0}, {16, 16}}; - const VkRect2D scissors[] = {scissor, scissor}; - - m_commandBuffer->begin(); - - // array tests - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetScissor-firstScissor-00593"); - vkCmdSetScissor(m_commandBuffer->handle(), 1, 1, scissors); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetScissor-scissorCount-arraylength"); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 0, nullptr); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetScissor-scissorCount-00594"); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 2, scissors); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetScissor-firstScissor-00593"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetScissor-scissorCount-arraylength"); - vkCmdSetScissor(m_commandBuffer->handle(), 1, 0, scissors); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetScissor-firstScissor-00593"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetScissor-scissorCount-00594"); - vkCmdSetScissor(m_commandBuffer->handle(), 1, 2, scissors); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetScissor-pScissors-parameter"); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, nullptr); - m_errorMonitor->VerifyFound(); - - struct TestCase { - VkRect2D scissor; - std::string vuid; - }; - - std::vector<TestCase> test_cases = {{{{-1, 0}, {16, 16}}, "VUID-vkCmdSetScissor-x-00595"}, - {{{0, -1}, {16, 16}}, "VUID-vkCmdSetScissor-x-00595"}, - {{{1, 0}, {INT32_MAX, 16}}, "VUID-vkCmdSetScissor-offset-00596"}, - {{{INT32_MAX, 0}, {1, 16}}, "VUID-vkCmdSetScissor-offset-00596"}, - {{{0, 0}, {uint32_t{INT32_MAX} + 1, 16}}, "VUID-vkCmdSetScissor-offset-00596"}, - {{{0, 1}, {16, INT32_MAX}}, "VUID-vkCmdSetScissor-offset-00597"}, - {{{0, INT32_MAX}, {16, 1}}, "VUID-vkCmdSetScissor-offset-00597"}, - {{{0, 0}, {16, uint32_t{INT32_MAX} + 1}}, "VUID-vkCmdSetScissor-offset-00597"}}; - - for (const auto &test_case : test_cases) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuid); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &test_case.scissor); - m_errorMonitor->VerifyFound(); - } - - m_commandBuffer->end(); -} - -TEST_F(VkLayerTest, SetDynScissorParamMultiviewportTests) { - TEST_DESCRIPTION("Test parameters of vkCmdSetScissor with multiViewport feature enabled"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - if (!m_device->phy().features().multiViewport) { - printf("%s VkPhysicalDeviceFeatures::multiViewport is not supported -- skipping test.\n", kSkipPrefix); - return; - } - - const auto max_scissors = m_device->props.limits.maxViewports; - const uint32_t too_many_scissors = 65536 + 1; // let's say this is too much to allocate pScissors for - - m_commandBuffer->begin(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetScissor-scissorCount-arraylength"); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 0, nullptr); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetScissor-pScissors-parameter"); - vkCmdSetScissor(m_commandBuffer->handle(), 0, max_scissors, nullptr); - m_errorMonitor->VerifyFound(); - - if (max_scissors >= too_many_scissors) { - printf( - "%s VkPhysicalDeviceLimits::maxViewports is too large to practically test against -- skipping " - "part of " - "test.\n", - kSkipPrefix); - return; - } - - const VkRect2D scissor = {{0, 0}, {16, 16}}; - const std::vector<VkRect2D> scissors(max_scissors + 1, scissor); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetScissor-firstScissor-00592"); - vkCmdSetScissor(m_commandBuffer->handle(), 0, max_scissors + 1, scissors.data()); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetScissor-firstScissor-00592"); - vkCmdSetScissor(m_commandBuffer->handle(), max_scissors, 1, scissors.data()); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetScissor-firstScissor-00592"); - vkCmdSetScissor(m_commandBuffer->handle(), 1, max_scissors, scissors.data()); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetScissor-scissorCount-arraylength"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetScissor-firstScissor-00592"); - vkCmdSetScissor(m_commandBuffer->handle(), max_scissors + 1, 0, scissors.data()); - m_errorMonitor->VerifyFound(); -} - -// This is a positive test. No failures are expected. -TEST_F(VkPositiveLayerTest, EmptyDescriptorUpdateTest) { - TEST_DESCRIPTION("Update last descriptor in a set that includes an empty binding"); - VkResult err; - - ASSERT_NO_FATAL_FAILURE(Init()); - m_errorMonitor->ExpectSuccess(); - - // Create layout with two uniform buffer descriptors w/ empty binding between them - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - {1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0 /*!*/, 0, nullptr}, - {2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, - }); - - // Create a buffer to be used for update - VkBufferCreateInfo buff_ci = {}; - buff_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buff_ci.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - buff_ci.size = 256; - buff_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VkBuffer buffer; - err = vkCreateBuffer(m_device->device(), &buff_ci, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - // Have to bind memory to buffer before descriptor update - VkMemoryAllocateInfo mem_alloc = {}; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.allocationSize = 512; // one allocation for both buffers - mem_alloc.memoryTypeIndex = 0; - - VkMemoryRequirements mem_reqs; - vkGetBufferMemoryRequirements(m_device->device(), buffer, &mem_reqs); - bool pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &mem_alloc, 0); - if (!pass) { - printf("%s Failed to allocate memory.\n", kSkipPrefix); - vkDestroyBuffer(m_device->device(), buffer, NULL); - return; - } - // Make sure allocation is sufficiently large to accommodate buffer requirements - if (mem_reqs.size > mem_alloc.allocationSize) { - mem_alloc.allocationSize = mem_reqs.size; - } - - VkDeviceMemory mem; - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &mem); - ASSERT_VK_SUCCESS(err); - err = vkBindBufferMemory(m_device->device(), buffer, mem, 0); - ASSERT_VK_SUCCESS(err); - - // Only update the descriptor at binding 2 - VkDescriptorBufferInfo buff_info = {}; - buff_info.buffer = buffer; - buff_info.offset = 0; - buff_info.range = VK_WHOLE_SIZE; - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstBinding = 2; - descriptor_write.descriptorCount = 1; - descriptor_write.pTexelBufferView = nullptr; - descriptor_write.pBufferInfo = &buff_info; - descriptor_write.pImageInfo = nullptr; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_write.dstSet = ds.set_; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - m_errorMonitor->VerifyNotFound(); - // Cleanup - vkFreeMemory(m_device->device(), mem, NULL); - vkDestroyBuffer(m_device->device(), buffer, NULL); -} - -TEST_F(VkLayerTest, MultiplePushDescriptorSets) { - TEST_DESCRIPTION("Verify an error message for multiple push descriptor sets."); - - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Did not find VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME; skipped.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - } else { - printf("%s Push Descriptors Extension not supported, skipping tests\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - auto push_descriptor_prop = GetPushDescriptorProperties(instance(), gpu()); - if (push_descriptor_prop.maxPushDescriptors < 1) { - // Some implementations report an invalid maxPushDescriptors of 0 - printf("%s maxPushDescriptors is zero, skipping tests\n", kSkipPrefix); - return; - } - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 0; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - dsl_binding.pImmutableSamplers = NULL; - - const unsigned int descriptor_set_layout_count = 2; - std::vector<VkDescriptorSetLayoutObj> ds_layouts; - for (uint32_t i = 0; i < descriptor_set_layout_count; ++i) { - dsl_binding.binding = i; - ds_layouts.emplace_back(m_device, std::vector<VkDescriptorSetLayoutBinding>(1, dsl_binding), - VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR); - } - const auto &ds_vk_layouts = MakeVkHandles<VkDescriptorSetLayout>(ds_layouts); - - VkPipelineLayout pipeline_layout; - VkPipelineLayoutCreateInfo pipeline_layout_ci = {}; - pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_ci.pNext = NULL; - pipeline_layout_ci.pushConstantRangeCount = 0; - pipeline_layout_ci.pPushConstantRanges = NULL; - pipeline_layout_ci.setLayoutCount = ds_vk_layouts.size(); - pipeline_layout_ci.pSetLayouts = ds_vk_layouts.data(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00293"); - vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CreateDescriptorUpdateTemplate) { - TEST_DESCRIPTION("Verify error messages for invalid vkCreateDescriptorUpdateTemplate calls."); - - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Did not find VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME; skipped.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - // Note: Includes workaround for some implementations which incorrectly return 0 maxPushDescriptors - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME) && - DeviceExtensionSupported(gpu(), nullptr, VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME) && - (GetPushDescriptorProperties(instance(), gpu()).maxPushDescriptors > 0)) { - m_device_extension_names.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME); - } else { - printf("%s Push Descriptors and Descriptor Update Template Extensions not supported, skipping tests\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 0; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_ALL; - dsl_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout_ub(m_device, {dsl_binding}); - const VkDescriptorSetLayoutObj ds_layout_ub1(m_device, {dsl_binding}); - const VkDescriptorSetLayoutObj ds_layout_ub_push(m_device, {dsl_binding}, - VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR); - const VkPipelineLayoutObj pipeline_layout(m_device, {{&ds_layout_ub, &ds_layout_ub1, &ds_layout_ub_push}}); - PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR = - (PFN_vkCreateDescriptorUpdateTemplateKHR)vkGetDeviceProcAddr(m_device->device(), "vkCreateDescriptorUpdateTemplateKHR"); - ASSERT_NE(vkCreateDescriptorUpdateTemplateKHR, nullptr); - PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR = - (PFN_vkDestroyDescriptorUpdateTemplateKHR)vkGetDeviceProcAddr(m_device->device(), "vkDestroyDescriptorUpdateTemplateKHR"); - ASSERT_NE(vkDestroyDescriptorUpdateTemplateKHR, nullptr); - - VkDescriptorUpdateTemplateEntry entries = {0, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, sizeof(VkBuffer)}; - VkDescriptorUpdateTemplateCreateInfo create_info = {}; - create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO; - create_info.pNext = nullptr; - create_info.flags = 0; - create_info.descriptorUpdateEntryCount = 1; - create_info.pDescriptorUpdateEntries = &entries; - - auto do_test = [&](std::string err) { - VkDescriptorUpdateTemplateKHR dut = VK_NULL_HANDLE; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, err); - if (VK_SUCCESS == vkCreateDescriptorUpdateTemplateKHR(m_device->handle(), &create_info, nullptr, &dut)) { - vkDestroyDescriptorUpdateTemplateKHR(m_device->handle(), dut, nullptr); - } - m_errorMonitor->VerifyFound(); - }; - - // Descriptor set type template - create_info.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET; - // descriptorSetLayout is NULL - do_test("VUID-VkDescriptorUpdateTemplateCreateInfo-templateType-00350"); - - // Push descriptor type template - create_info.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR; - create_info.pipelineBindPoint = VK_PIPELINE_BIND_POINT_COMPUTE; - create_info.pipelineLayout = pipeline_layout.handle(); - create_info.set = 2; - - // Bad bindpoint -- force fuzz the bind point - memset(&create_info.pipelineBindPoint, 0xFE, sizeof(create_info.pipelineBindPoint)); - do_test("VUID-VkDescriptorUpdateTemplateCreateInfo-templateType-00351"); - create_info.pipelineBindPoint = VK_PIPELINE_BIND_POINT_COMPUTE; - - // Bad pipeline layout - create_info.pipelineLayout = VK_NULL_HANDLE; - do_test("VUID-VkDescriptorUpdateTemplateCreateInfo-templateType-00352"); - create_info.pipelineLayout = pipeline_layout.handle(); - - // Wrong set # - create_info.set = 0; - do_test("VUID-VkDescriptorUpdateTemplateCreateInfo-templateType-00353"); - - // Invalid set # - create_info.set = 42; - do_test("VUID-VkDescriptorUpdateTemplateCreateInfo-templateType-00353"); -} - -// This is a positive test. No failures are expected. -TEST_F(VkPositiveLayerTest, PushDescriptorNullDstSetTest) { - TEST_DESCRIPTION("Use null dstSet in CmdPushDescriptorSetKHR"); - - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Did not find VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME; skipped.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - } else { - printf("%s Push Descriptors Extension not supported, skipping tests\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - m_errorMonitor->ExpectSuccess(); - - auto push_descriptor_prop = GetPushDescriptorProperties(instance(), gpu()); - if (push_descriptor_prop.maxPushDescriptors < 1) { - // Some implementations report an invalid maxPushDescriptors of 0 - printf("%s maxPushDescriptors is zero, skipping tests\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 2; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - dsl_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding}); - // Create push descriptor set layout - const VkDescriptorSetLayoutObj push_ds_layout(m_device, {dsl_binding}, VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR); - - // Use helper to create graphics pipeline - CreatePipelineHelper helper(*this); - helper.InitInfo(); - helper.InitState(); - helper.pipeline_layout_ = VkPipelineLayoutObj(m_device, {&push_ds_layout, &ds_layout}); - helper.CreateGraphicsPipeline(); - - static const float vbo_data[3] = {1.f, 0.f, 1.f}; - VkConstantBufferObj vbo(m_device, sizeof(vbo_data), (const void *)&vbo_data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); - - VkDescriptorBufferInfo buff_info; - buff_info.buffer = vbo.handle(); - buff_info.offset = 0; - buff_info.range = sizeof(vbo_data); - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstBinding = 2; - descriptor_write.descriptorCount = 1; - descriptor_write.pTexelBufferView = nullptr; - descriptor_write.pBufferInfo = &buff_info; - descriptor_write.pImageInfo = nullptr; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_write.dstSet = 0; // Should not cause a validation error - - // Find address of extension call and make the call - PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR = - (PFN_vkCmdPushDescriptorSetKHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdPushDescriptorSetKHR"); - assert(vkCmdPushDescriptorSetKHR != nullptr); - - m_commandBuffer->begin(); - - // In Intel GPU, it needs to bind pipeline before push descriptor set. - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, helper.pipeline_); - vkCmdPushDescriptorSetKHR(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, helper.pipeline_layout_.handle(), 0, 1, - &descriptor_write); - - m_errorMonitor->VerifyNotFound(); -} - -// This is a positive test. No failures are expected. -TEST_F(VkPositiveLayerTest, PushDescriptorUnboundSetTest) { - TEST_DESCRIPTION("Ensure that no validation errors are produced for not bound push descriptor sets"); - VkResult err; - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Did not find VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME; skipped.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - } else { - printf("%s Push Descriptors Extension not supported, skipping tests\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - auto push_descriptor_prop = GetPushDescriptorProperties(instance(), gpu()); - if (push_descriptor_prop.maxPushDescriptors < 1) { - // Some implementations report an invalid maxPushDescriptors of 0 - printf("%s maxPushDescriptors is zero, skipping tests\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - m_errorMonitor->ExpectSuccess(); - - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool; - err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - ASSERT_VK_SUCCESS(err); - - // Create descriptor set layout - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 2; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - dsl_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding}); - - // Create push descriptor set layout - const VkDescriptorSetLayoutObj push_ds_layout(m_device, {dsl_binding}, VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR); - - // Allocate descriptor set - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.pNext = NULL; - alloc_info.descriptorPool = ds_pool; - alloc_info.descriptorSetCount = 1; - alloc_info.pSetLayouts = &ds_layout.handle(); - VkDescriptorSet descriptor_set; - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptor_set); - ASSERT_VK_SUCCESS(err); - - // Now use the descriptor layouts to create a pipeline layout - const VkPipelineLayoutObj pipeline_layout(m_device, {&push_ds_layout, &ds_layout}); - - // Create PSO - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 x;\n" - "layout(set=0) layout(binding=2) uniform foo1 { float x; } bar1;\n" - "layout(set=1) layout(binding=2) uniform foo2 { float y; } bar2;\n" - "void main(){\n" - " x = vec4(bar1.x) + vec4(bar2.y);\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.SetViewport(m_viewports); - pipe.SetScissor(m_scissors); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - static const float bo_data[1] = {1.f}; - VkConstantBufferObj buffer(m_device, sizeof(bo_data), (const void *)&bo_data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); - - // Update descriptor set - VkDescriptorBufferInfo buff_info; - buff_info.buffer = buffer.handle(); - buff_info.offset = 0; - buff_info.range = sizeof(bo_data); - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstBinding = 2; - descriptor_write.descriptorCount = 1; - descriptor_write.pTexelBufferView = nullptr; - descriptor_write.pBufferInfo = &buff_info; - descriptor_write.pImageInfo = nullptr; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_write.dstSet = descriptor_set; - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR = - (PFN_vkCmdPushDescriptorSetKHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdPushDescriptorSetKHR"); - assert(vkCmdPushDescriptorSetKHR != nullptr); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - - // Push descriptors and bind descriptor set - vkCmdPushDescriptorSetKHR(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, - &descriptor_write); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 1, 1, - &descriptor_set, 0, NULL); - - // No errors should be generated. - vkCmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); - - m_errorMonitor->VerifyNotFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); -} - -// This is a positive test. No failures are expected. -TEST_F(VkPositiveLayerTest, TestAliasedMemoryTracking) { - VkResult err; - bool pass; - - TEST_DESCRIPTION( - "Create a buffer, allocate memory, bind memory, destroy the buffer, create an image, and bind the same memory to it"); - - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - - VkBuffer buffer; - VkImage image; - VkDeviceMemory mem; - VkMemoryRequirements mem_reqs; - - VkBufferCreateInfo buf_info = {}; - buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buf_info.pNext = NULL; - buf_info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - buf_info.size = 256; - buf_info.queueFamilyIndexCount = 0; - buf_info.pQueueFamilyIndices = NULL; - buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - buf_info.flags = 0; - err = vkCreateBuffer(m_device->device(), &buf_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - vkGetBufferMemoryRequirements(m_device->device(), buffer, &mem_reqs); - - VkMemoryAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.pNext = NULL; - alloc_info.memoryTypeIndex = 0; - - // Ensure memory is big enough for both bindings - alloc_info.allocationSize = 0x10000; - - pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &alloc_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - if (!pass) { - printf("%s Failed to allocate memory.\n", kSkipPrefix); - vkDestroyBuffer(m_device->device(), buffer, NULL); - return; - } - - err = vkAllocateMemory(m_device->device(), &alloc_info, NULL, &mem); - ASSERT_VK_SUCCESS(err); - - uint8_t *pData; - err = vkMapMemory(m_device->device(), mem, 0, mem_reqs.size, 0, (void **)&pData); - ASSERT_VK_SUCCESS(err); - - memset(pData, 0xCADECADE, static_cast<size_t>(mem_reqs.size)); - - vkUnmapMemory(m_device->device(), mem); - - err = vkBindBufferMemory(m_device->device(), buffer, mem, 0); - ASSERT_VK_SUCCESS(err); - - // NOW, destroy the buffer. Obviously, the resource no longer occupies this - // memory. In fact, it was never used by the GPU. - // Just be sure, wait for idle. - vkDestroyBuffer(m_device->device(), buffer, NULL); - vkDeviceWaitIdle(m_device->device()); - - // Use optimal as some platforms report linear support but then fail image creation - VkImageTiling image_tiling = VK_IMAGE_TILING_OPTIMAL; - VkImageFormatProperties image_format_properties; - vkGetPhysicalDeviceImageFormatProperties(gpu(), VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TYPE_2D, image_tiling, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0, &image_format_properties); - if (image_format_properties.maxExtent.width == 0) { - printf("%s Image format not supported; skipped.\n", kSkipPrefix); - vkFreeMemory(m_device->device(), mem, NULL); - return; - } - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; - image_create_info.extent.width = 64; - image_create_info.extent.height = 64; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = image_tiling; - image_create_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - image_create_info.queueFamilyIndexCount = 0; - image_create_info.pQueueFamilyIndices = NULL; - image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_create_info.flags = 0; - - /* Create a mappable image. It will be the texture if linear images are OK - * to be textures or it will be the staging image if they are not. - */ - err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - ASSERT_VK_SUCCESS(err); - - vkGetImageMemoryRequirements(m_device->device(), image, &mem_reqs); - - VkMemoryAllocateInfo mem_alloc = {}; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.allocationSize = 0; - mem_alloc.memoryTypeIndex = 0; - mem_alloc.allocationSize = mem_reqs.size; - - pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &mem_alloc, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - if (!pass) { - printf("%s Failed to allocate memory.\n", kSkipPrefix); - vkFreeMemory(m_device->device(), mem, NULL); - vkDestroyImage(m_device->device(), image, NULL); - return; - } - - // VALIDATION FAILURE: - err = vkBindImageMemory(m_device->device(), image, mem, 0); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->VerifyNotFound(); - - vkFreeMemory(m_device->device(), mem, NULL); - vkDestroyImage(m_device->device(), image, NULL); -} - -// This is a positive test. No failures are expected. -TEST_F(VkPositiveLayerTest, TestDestroyFreeNullHandles) { - VkResult err; - - TEST_DESCRIPTION("Call all applicable destroy and free routines with NULL handles, expecting no validation errors"); - - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - vkDestroyBuffer(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroyBufferView(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroyCommandPool(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroyDescriptorPool(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroyDescriptorSetLayout(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroyDevice(VK_NULL_HANDLE, NULL); - vkDestroyEvent(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroyFence(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroyFramebuffer(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroyImage(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroyImageView(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroyInstance(VK_NULL_HANDLE, NULL); - vkDestroyPipeline(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroyPipelineCache(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroyPipelineLayout(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroyQueryPool(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroyRenderPass(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroySampler(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroySemaphore(m_device->device(), VK_NULL_HANDLE, NULL); - vkDestroyShaderModule(m_device->device(), VK_NULL_HANDLE, NULL); - - VkCommandPool command_pool; - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool); - VkCommandBuffer command_buffers[3] = {}; - VkCommandBufferAllocateInfo command_buffer_allocate_info{}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = command_pool; - command_buffer_allocate_info.commandBufferCount = 1; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, &command_buffers[1]); - vkFreeCommandBuffers(m_device->device(), command_pool, 3, command_buffers); - vkDestroyCommandPool(m_device->device(), command_pool, NULL); - - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - ds_type_count.descriptorCount = 1; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.maxSets = 1; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool; - err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - ASSERT_VK_SUCCESS(err); - - VkDescriptorSetLayoutBinding dsl_binding = {}; - dsl_binding.binding = 2; - dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - dsl_binding.descriptorCount = 1; - dsl_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - dsl_binding.pImmutableSamplers = NULL; - - const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding}); - - VkDescriptorSet descriptor_sets[3] = {}; - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorSetCount = 1; - alloc_info.descriptorPool = ds_pool; - alloc_info.pSetLayouts = &ds_layout.handle(); - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptor_sets[1]); - ASSERT_VK_SUCCESS(err); - vkFreeDescriptorSets(m_device->device(), ds_pool, 3, descriptor_sets); - vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL); - - vkFreeMemory(m_device->device(), VK_NULL_HANDLE, NULL); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, QueueSubmitSemaphoresAndLayoutTracking) { - TEST_DESCRIPTION("Submit multiple command buffers with chained semaphore signals and layout transitions"); - - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - VkCommandBuffer cmd_bufs[4]; - VkCommandBufferAllocateInfo alloc_info; - alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - alloc_info.pNext = NULL; - alloc_info.commandBufferCount = 4; - alloc_info.commandPool = m_commandPool->handle(); - alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(m_device->device(), &alloc_info, cmd_bufs); - VkImageObj image(m_device); - image.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, - (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT), - VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - VkCommandBufferBeginInfo cb_binfo; - cb_binfo.pNext = NULL; - cb_binfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - cb_binfo.pInheritanceInfo = VK_NULL_HANDLE; - cb_binfo.flags = 0; - // Use 4 command buffers, each with an image layout transition, ColorAO->General->ColorAO->TransferSrc->TransferDst - vkBeginCommandBuffer(cmd_bufs[0], &cb_binfo); - VkImageMemoryBarrier img_barrier = {}; - img_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - img_barrier.pNext = NULL; - img_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; - img_barrier.dstAccessMask = VK_ACCESS_HOST_WRITE_BIT; - img_barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - img_barrier.image = image.handle(); - img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - img_barrier.subresourceRange.baseArrayLayer = 0; - img_barrier.subresourceRange.baseMipLevel = 0; - img_barrier.subresourceRange.layerCount = 1; - img_barrier.subresourceRange.levelCount = 1; - vkCmdPipelineBarrier(cmd_bufs[0], VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 0, nullptr, 1, - &img_barrier); - vkEndCommandBuffer(cmd_bufs[0]); - vkBeginCommandBuffer(cmd_bufs[1], &cb_binfo); - img_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - vkCmdPipelineBarrier(cmd_bufs[1], VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 0, nullptr, 1, - &img_barrier); - vkEndCommandBuffer(cmd_bufs[1]); - vkBeginCommandBuffer(cmd_bufs[2], &cb_binfo); - img_barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - vkCmdPipelineBarrier(cmd_bufs[2], VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 0, nullptr, 1, - &img_barrier); - vkEndCommandBuffer(cmd_bufs[2]); - vkBeginCommandBuffer(cmd_bufs[3], &cb_binfo); - img_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - vkCmdPipelineBarrier(cmd_bufs[3], VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 0, nullptr, 1, - &img_barrier); - vkEndCommandBuffer(cmd_bufs[3]); - - // Submit 4 command buffers in 3 submits, with submits 2 and 3 waiting for semaphores from submits 1 and 2 - VkSemaphore semaphore1, semaphore2; - VkSemaphoreCreateInfo semaphore_create_info{}; - semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - vkCreateSemaphore(m_device->device(), &semaphore_create_info, nullptr, &semaphore1); - vkCreateSemaphore(m_device->device(), &semaphore_create_info, nullptr, &semaphore2); - VkPipelineStageFlags flags[]{VK_PIPELINE_STAGE_ALL_COMMANDS_BIT}; - VkSubmitInfo submit_info[3]; - submit_info[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info[0].pNext = nullptr; - submit_info[0].commandBufferCount = 1; - submit_info[0].pCommandBuffers = &cmd_bufs[0]; - submit_info[0].signalSemaphoreCount = 1; - submit_info[0].pSignalSemaphores = &semaphore1; - submit_info[0].waitSemaphoreCount = 0; - submit_info[0].pWaitDstStageMask = nullptr; - submit_info[0].pWaitDstStageMask = flags; - submit_info[1].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info[1].pNext = nullptr; - submit_info[1].commandBufferCount = 1; - submit_info[1].pCommandBuffers = &cmd_bufs[1]; - submit_info[1].waitSemaphoreCount = 1; - submit_info[1].pWaitSemaphores = &semaphore1; - submit_info[1].signalSemaphoreCount = 1; - submit_info[1].pSignalSemaphores = &semaphore2; - submit_info[1].pWaitDstStageMask = flags; - submit_info[2].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info[2].pNext = nullptr; - submit_info[2].commandBufferCount = 2; - submit_info[2].pCommandBuffers = &cmd_bufs[2]; - submit_info[2].waitSemaphoreCount = 1; - submit_info[2].pWaitSemaphores = &semaphore2; - submit_info[2].signalSemaphoreCount = 0; - submit_info[2].pSignalSemaphores = nullptr; - submit_info[2].pWaitDstStageMask = flags; - vkQueueSubmit(m_device->m_queue, 3, submit_info, VK_NULL_HANDLE); - vkQueueWaitIdle(m_device->m_queue); - - vkDestroySemaphore(m_device->device(), semaphore1, NULL); - vkDestroySemaphore(m_device->device(), semaphore2, NULL); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, DynamicOffsetWithInactiveBinding) { - // Create a descriptorSet w/ dynamic descriptors where 1 binding is inactive - // We previously had a bug where dynamic offset of inactive bindings was still being used - VkResult err; - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitViewport()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - OneOffDescriptorSet ds(m_device, { - {2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}, - {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}, - {1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}, - }); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - - // Create two buffers to update the descriptors with - // The first will be 2k and used for bindings 0 & 1, the second is 1k for binding 2 - uint32_t qfi = 0; - VkBufferCreateInfo buffCI = {}; - buffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffCI.size = 2048; - buffCI.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - buffCI.queueFamilyIndexCount = 1; - buffCI.pQueueFamilyIndices = &qfi; - - VkBuffer dyub1; - err = vkCreateBuffer(m_device->device(), &buffCI, NULL, &dyub1); - ASSERT_VK_SUCCESS(err); - // buffer2 - buffCI.size = 1024; - VkBuffer dyub2; - err = vkCreateBuffer(m_device->device(), &buffCI, NULL, &dyub2); - ASSERT_VK_SUCCESS(err); - // Allocate memory and bind to buffers - VkMemoryAllocateInfo mem_alloc[2] = {}; - mem_alloc[0].sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc[0].pNext = NULL; - mem_alloc[0].memoryTypeIndex = 0; - mem_alloc[1].sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc[1].pNext = NULL; - mem_alloc[1].memoryTypeIndex = 0; - - VkMemoryRequirements mem_reqs1; - vkGetBufferMemoryRequirements(m_device->device(), dyub1, &mem_reqs1); - VkMemoryRequirements mem_reqs2; - vkGetBufferMemoryRequirements(m_device->device(), dyub2, &mem_reqs2); - mem_alloc[0].allocationSize = mem_reqs1.size; - bool pass = m_device->phy().set_memory_type(mem_reqs1.memoryTypeBits, &mem_alloc[0], 0); - mem_alloc[1].allocationSize = mem_reqs2.size; - pass &= m_device->phy().set_memory_type(mem_reqs2.memoryTypeBits, &mem_alloc[1], 0); - if (!pass) { - printf("%s Failed to allocate memory.\n", kSkipPrefix); - vkDestroyBuffer(m_device->device(), dyub1, NULL); - vkDestroyBuffer(m_device->device(), dyub2, NULL); - return; - } - - VkDeviceMemory mem1; - err = vkAllocateMemory(m_device->device(), &mem_alloc[0], NULL, &mem1); - ASSERT_VK_SUCCESS(err); - err = vkBindBufferMemory(m_device->device(), dyub1, mem1, 0); - ASSERT_VK_SUCCESS(err); - VkDeviceMemory mem2; - err = vkAllocateMemory(m_device->device(), &mem_alloc[1], NULL, &mem2); - ASSERT_VK_SUCCESS(err); - err = vkBindBufferMemory(m_device->device(), dyub2, mem2, 0); - ASSERT_VK_SUCCESS(err); - // Update descriptors - const uint32_t BINDING_COUNT = 3; - VkDescriptorBufferInfo buff_info[BINDING_COUNT] = {}; - buff_info[0].buffer = dyub1; - buff_info[0].offset = 0; - buff_info[0].range = 256; - buff_info[1].buffer = dyub1; - buff_info[1].offset = 256; - buff_info[1].range = 512; - buff_info[2].buffer = dyub2; - buff_info[2].offset = 0; - buff_info[2].range = 512; - - VkWriteDescriptorSet descriptor_write; - memset(&descriptor_write, 0, sizeof(descriptor_write)); - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = BINDING_COUNT; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - descriptor_write.pBufferInfo = buff_info; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - // Create PSO to be used for draw-time errors below - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 x;\n" - "layout(set=0) layout(binding=0) uniform foo1 { int x; int y; } bar1;\n" - "layout(set=0) layout(binding=2) uniform foo2 { int x; int y; } bar2;\n" - "void main(){\n" - " x = vec4(bar1.y) + vec4(bar2.y);\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.SetViewport(m_viewports); - pipe.SetScissor(m_scissors); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - // This update should succeed, but offset of inactive binding 1 oversteps binding 2 buffer size - // we used to have a bug in this case. - uint32_t dyn_off[BINDING_COUNT] = {0, 1024, 256}; - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, &ds.set_, - BINDING_COUNT, dyn_off); - m_commandBuffer->Draw(1, 0, 0, 0); - m_errorMonitor->VerifyNotFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - - vkDestroyBuffer(m_device->device(), dyub1, NULL); - vkDestroyBuffer(m_device->device(), dyub2, NULL); - vkFreeMemory(m_device->device(), mem1, NULL); - vkFreeMemory(m_device->device(), mem2, NULL); -} - -TEST_F(VkPositiveLayerTest, NonCoherentMemoryMapping) { - TEST_DESCRIPTION( - "Ensure that validations handling of non-coherent memory mapping while using VK_WHOLE_SIZE does not cause access " - "violations"); - VkResult err; - uint8_t *pData; - ASSERT_NO_FATAL_FAILURE(Init()); - - VkDeviceMemory mem; - VkMemoryRequirements mem_reqs; - mem_reqs.memoryTypeBits = 0xFFFFFFFF; - const VkDeviceSize atom_size = m_device->props.limits.nonCoherentAtomSize; - VkMemoryAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.pNext = NULL; - alloc_info.memoryTypeIndex = 0; - - static const VkDeviceSize allocation_size = 32 * atom_size; - alloc_info.allocationSize = allocation_size; - - // Find a memory configurations WITHOUT a COHERENT bit, otherwise exit - bool pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &alloc_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - if (!pass) { - pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &alloc_info, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - if (!pass) { - pass = m_device->phy().set_memory_type( - mem_reqs.memoryTypeBits, &alloc_info, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT, - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - if (!pass) { - printf("%s Couldn't find a memory type wihtout a COHERENT bit.\n", kSkipPrefix); - return; - } - } - } - - err = vkAllocateMemory(m_device->device(), &alloc_info, NULL, &mem); - ASSERT_VK_SUCCESS(err); - - // Map/Flush/Invalidate using WHOLE_SIZE and zero offsets and entire mapped range - m_errorMonitor->ExpectSuccess(); - err = vkMapMemory(m_device->device(), mem, 0, VK_WHOLE_SIZE, 0, (void **)&pData); - ASSERT_VK_SUCCESS(err); - VkMappedMemoryRange mmr = {}; - mmr.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - mmr.memory = mem; - mmr.offset = 0; - mmr.size = VK_WHOLE_SIZE; - err = vkFlushMappedMemoryRanges(m_device->device(), 1, &mmr); - ASSERT_VK_SUCCESS(err); - err = vkInvalidateMappedMemoryRanges(m_device->device(), 1, &mmr); - ASSERT_VK_SUCCESS(err); - m_errorMonitor->VerifyNotFound(); - vkUnmapMemory(m_device->device(), mem); - - // Map/Flush/Invalidate using WHOLE_SIZE and an offset and entire mapped range - m_errorMonitor->ExpectSuccess(); - err = vkMapMemory(m_device->device(), mem, 5 * atom_size, VK_WHOLE_SIZE, 0, (void **)&pData); - ASSERT_VK_SUCCESS(err); - mmr.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - mmr.memory = mem; - mmr.offset = 6 * atom_size; - mmr.size = VK_WHOLE_SIZE; - err = vkFlushMappedMemoryRanges(m_device->device(), 1, &mmr); - ASSERT_VK_SUCCESS(err); - err = vkInvalidateMappedMemoryRanges(m_device->device(), 1, &mmr); - ASSERT_VK_SUCCESS(err); - m_errorMonitor->VerifyNotFound(); - vkUnmapMemory(m_device->device(), mem); - - // Map with offset and size - // Flush/Invalidate subrange of mapped area with offset and size - m_errorMonitor->ExpectSuccess(); - err = vkMapMemory(m_device->device(), mem, 3 * atom_size, 9 * atom_size, 0, (void **)&pData); - ASSERT_VK_SUCCESS(err); - mmr.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - mmr.memory = mem; - mmr.offset = 4 * atom_size; - mmr.size = 2 * atom_size; - err = vkFlushMappedMemoryRanges(m_device->device(), 1, &mmr); - ASSERT_VK_SUCCESS(err); - err = vkInvalidateMappedMemoryRanges(m_device->device(), 1, &mmr); - ASSERT_VK_SUCCESS(err); - m_errorMonitor->VerifyNotFound(); - vkUnmapMemory(m_device->device(), mem); - - // Map without offset and flush WHOLE_SIZE with two separate offsets - m_errorMonitor->ExpectSuccess(); - err = vkMapMemory(m_device->device(), mem, 0, VK_WHOLE_SIZE, 0, (void **)&pData); - ASSERT_VK_SUCCESS(err); - mmr.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - mmr.memory = mem; - mmr.offset = allocation_size - (4 * atom_size); - mmr.size = VK_WHOLE_SIZE; - err = vkFlushMappedMemoryRanges(m_device->device(), 1, &mmr); - ASSERT_VK_SUCCESS(err); - mmr.offset = allocation_size - (6 * atom_size); - mmr.size = VK_WHOLE_SIZE; - err = vkFlushMappedMemoryRanges(m_device->device(), 1, &mmr); - ASSERT_VK_SUCCESS(err); - m_errorMonitor->VerifyNotFound(); - vkUnmapMemory(m_device->device(), mem); - - vkFreeMemory(m_device->device(), mem, NULL); -} - -// This is a positive test. We used to expect error in this case but spec now allows it -TEST_F(VkPositiveLayerTest, ResetUnsignaledFence) { - m_errorMonitor->ExpectSuccess(); - vk_testing::Fence testFence; - VkFenceCreateInfo fenceInfo = {}; - fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fenceInfo.pNext = NULL; - - ASSERT_NO_FATAL_FAILURE(Init()); - testFence.init(*m_device, fenceInfo); - VkFence fences[1] = {testFence.handle()}; - VkResult result = vkResetFences(m_device->device(), 1, fences); - ASSERT_VK_SUCCESS(result); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, CommandBufferSimultaneousUseSync) { - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - VkResult err; - - // Record (empty!) command buffer that can be submitted multiple times - // simultaneously. - VkCommandBufferBeginInfo cbbi = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, - VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, nullptr}; - m_commandBuffer->begin(&cbbi); - m_commandBuffer->end(); - - VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, 0}; - VkFence fence; - err = vkCreateFence(m_device->device(), &fci, nullptr, &fence); - ASSERT_VK_SUCCESS(err); - - VkSemaphoreCreateInfo sci = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, nullptr, 0}; - VkSemaphore s1, s2; - err = vkCreateSemaphore(m_device->device(), &sci, nullptr, &s1); - ASSERT_VK_SUCCESS(err); - err = vkCreateSemaphore(m_device->device(), &sci, nullptr, &s2); - ASSERT_VK_SUCCESS(err); - - // Submit CB once signaling s1, with fence so we can roll forward to its retirement. - VkSubmitInfo si = {VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, 0, nullptr, nullptr, 1, &m_commandBuffer->handle(), 1, &s1}; - err = vkQueueSubmit(m_device->m_queue, 1, &si, fence); - ASSERT_VK_SUCCESS(err); - - // Submit CB again, signaling s2. - si.pSignalSemaphores = &s2; - err = vkQueueSubmit(m_device->m_queue, 1, &si, VK_NULL_HANDLE); - ASSERT_VK_SUCCESS(err); - - // Wait for fence. - err = vkWaitForFences(m_device->device(), 1, &fence, VK_TRUE, UINT64_MAX); - ASSERT_VK_SUCCESS(err); - - // CB is still in flight from second submission, but semaphore s1 is no - // longer in flight. delete it. - vkDestroySemaphore(m_device->device(), s1, nullptr); - - m_errorMonitor->VerifyNotFound(); - - // Force device idle and clean up remaining objects - vkDeviceWaitIdle(m_device->device()); - vkDestroySemaphore(m_device->device(), s2, nullptr); - vkDestroyFence(m_device->device(), fence, nullptr); -} - -TEST_F(VkPositiveLayerTest, FenceCreateSignaledWaitHandling) { - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - VkResult err; - - // A fence created signaled - VkFenceCreateInfo fci1 = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, VK_FENCE_CREATE_SIGNALED_BIT}; - VkFence f1; - err = vkCreateFence(m_device->device(), &fci1, nullptr, &f1); - ASSERT_VK_SUCCESS(err); - - // A fence created not - VkFenceCreateInfo fci2 = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, 0}; - VkFence f2; - err = vkCreateFence(m_device->device(), &fci2, nullptr, &f2); - ASSERT_VK_SUCCESS(err); - - // Submit the unsignaled fence - VkSubmitInfo si = {VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, 0, nullptr, nullptr, 0, nullptr, 0, nullptr}; - err = vkQueueSubmit(m_device->m_queue, 1, &si, f2); - - // Wait on both fences, with signaled first. - VkFence fences[] = {f1, f2}; - vkWaitForFences(m_device->device(), 2, fences, VK_TRUE, UINT64_MAX); - - // Should have both retired! - vkDestroyFence(m_device->device(), f1, nullptr); - vkDestroyFence(m_device->device(), f2, nullptr); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, CreateImageViewFollowsParameterCompatibilityRequirements) { - TEST_DESCRIPTION("Verify that creating an ImageView with valid usage does not generate validation errors."); - - ASSERT_NO_FATAL_FAILURE(Init()); - - m_errorMonitor->ExpectSuccess(); - - VkImageCreateInfo imgInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - nullptr, - VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, - VK_IMAGE_TYPE_2D, - VK_FORMAT_R8G8B8A8_UNORM, - {128, 128, 1}, - 1, - 1, - VK_SAMPLE_COUNT_1_BIT, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_SHARING_MODE_EXCLUSIVE, - 0, - nullptr, - VK_IMAGE_LAYOUT_UNDEFINED}; - VkImageObj image(m_device); - image.init(&imgInfo); - ASSERT_TRUE(image.initialized()); - VkImageView imageView; - VkImageViewCreateInfo ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.image = image.handle(); - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.format = VK_FORMAT_R8G8B8A8_UNORM; - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - ivci.subresourceRange.levelCount = 1; - ivci.subresourceRange.baseArrayLayer = 0; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyNotFound(); - vkDestroyImageView(m_device->device(), imageView, NULL); -} - -TEST_F(VkPositiveLayerTest, ValidUsage) { - TEST_DESCRIPTION("Verify that creating an image view from an image with valid usage doesn't generate validation errors"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - m_errorMonitor->ExpectSuccess(); - // Verify that we can create a view with usage INPUT_ATTACHMENT - VkImageObj image(m_device); - image.Init(128, 128, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - VkImageView imageView; - VkImageViewCreateInfo ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.image = image.handle(); - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.format = VK_FORMAT_R8G8B8A8_UNORM; - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - ivci.subresourceRange.levelCount = 1; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - vkCreateImageView(m_device->device(), &ivci, NULL, &imageView); - m_errorMonitor->VerifyNotFound(); - vkDestroyImageView(m_device->device(), imageView, NULL); -} - -// This is a positive test. No failures are expected. -TEST_F(VkPositiveLayerTest, BindSparse) { - TEST_DESCRIPTION("Bind 2 memory ranges to one image using vkQueueBindSparse, destroy the image and then free the memory"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - auto index = m_device->graphics_queue_node_index_; - if (!(m_device->queue_props[index].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT)) { - printf("%s Graphics queue does not have sparse binding bit.\n", kSkipPrefix); - return; - } - if (!m_device->phy().features().sparseBinding) { - printf("%s Device does not support sparse bindings.\n", kSkipPrefix); - return; - } - - m_errorMonitor->ExpectSuccess(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT); - - VkImage image; - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM; - image_create_info.extent.width = 64; - image_create_info.extent.height = 64; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - image_create_info.flags = VK_IMAGE_CREATE_SPARSE_BINDING_BIT; - VkResult err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - ASSERT_VK_SUCCESS(err); - - VkMemoryRequirements memory_reqs; - VkDeviceMemory memory_one, memory_two; - bool pass; - VkMemoryAllocateInfo memory_info = {}; - memory_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_info.pNext = NULL; - memory_info.allocationSize = 0; - memory_info.memoryTypeIndex = 0; - vkGetImageMemoryRequirements(m_device->device(), image, &memory_reqs); - // Find an image big enough to allow sparse mapping of 2 memory regions - // Increase the image size until it is at least twice the - // size of the required alignment, to ensure we can bind both - // allocated memory blocks to the image on aligned offsets. - while (memory_reqs.size < (memory_reqs.alignment * 2)) { - vkDestroyImage(m_device->device(), image, nullptr); - image_create_info.extent.width *= 2; - image_create_info.extent.height *= 2; - err = vkCreateImage(m_device->device(), &image_create_info, nullptr, &image); - ASSERT_VK_SUCCESS(err); - vkGetImageMemoryRequirements(m_device->device(), image, &memory_reqs); - } - // Allocate 2 memory regions of minimum alignment size, bind one at 0, the other - // at the end of the first - memory_info.allocationSize = memory_reqs.alignment; - pass = m_device->phy().set_memory_type(memory_reqs.memoryTypeBits, &memory_info, 0); - ASSERT_TRUE(pass); - err = vkAllocateMemory(m_device->device(), &memory_info, NULL, &memory_one); - ASSERT_VK_SUCCESS(err); - err = vkAllocateMemory(m_device->device(), &memory_info, NULL, &memory_two); - ASSERT_VK_SUCCESS(err); - VkSparseMemoryBind binds[2]; - binds[0].flags = 0; - binds[0].memory = memory_one; - binds[0].memoryOffset = 0; - binds[0].resourceOffset = 0; - binds[0].size = memory_info.allocationSize; - binds[1].flags = 0; - binds[1].memory = memory_two; - binds[1].memoryOffset = 0; - binds[1].resourceOffset = memory_info.allocationSize; - binds[1].size = memory_info.allocationSize; - - VkSparseImageOpaqueMemoryBindInfo opaqueBindInfo; - opaqueBindInfo.image = image; - opaqueBindInfo.bindCount = 2; - opaqueBindInfo.pBinds = binds; - - VkFence fence = VK_NULL_HANDLE; - VkBindSparseInfo bindSparseInfo = {}; - bindSparseInfo.sType = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO; - bindSparseInfo.imageOpaqueBindCount = 1; - bindSparseInfo.pImageOpaqueBinds = &opaqueBindInfo; - - vkQueueBindSparse(m_device->m_queue, 1, &bindSparseInfo, fence); - vkQueueWaitIdle(m_device->m_queue); - vkDestroyImage(m_device->device(), image, NULL); - vkFreeMemory(m_device->device(), memory_one, NULL); - vkFreeMemory(m_device->device(), memory_two, NULL); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, BindSparseMetadata) { - TEST_DESCRIPTION("Bind memory for the metadata aspect of a sparse image"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - auto index = m_device->graphics_queue_node_index_; - if (!(m_device->queue_props[index].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT)) { - printf("%s Graphics queue does not have sparse binding bit.\n", kSkipPrefix); - return; - } - if (!m_device->phy().features().sparseResidencyImage2D) { - printf("%s Device does not support sparse residency for images.\n", kSkipPrefix); - return; - } - - m_errorMonitor->ExpectSuccess(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT); - - // Create a sparse image - VkImage image; - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM; - image_create_info.extent.width = 64; - image_create_info.extent.height = 64; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - image_create_info.flags = VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT; - VkResult err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - ASSERT_VK_SUCCESS(err); - - // Query image memory requirements - VkMemoryRequirements memory_reqs; - vkGetImageMemoryRequirements(m_device->device(), image, &memory_reqs); - - // Query sparse memory requirements - uint32_t sparse_reqs_count = 0; - vkGetImageSparseMemoryRequirements(m_device->device(), image, &sparse_reqs_count, nullptr); - std::vector<VkSparseImageMemoryRequirements> sparse_reqs(sparse_reqs_count); - vkGetImageSparseMemoryRequirements(m_device->device(), image, &sparse_reqs_count, sparse_reqs.data()); - - // Find requirements for metadata aspect - const VkSparseImageMemoryRequirements *metadata_reqs = nullptr; - for (auto const &aspect_sparse_reqs : sparse_reqs) { - if (aspect_sparse_reqs.formatProperties.aspectMask == VK_IMAGE_ASPECT_METADATA_BIT) { - metadata_reqs = &aspect_sparse_reqs; - } - } - - if (!metadata_reqs) { - printf("%s Sparse image does not require memory for metadata.\n", kSkipPrefix); - } else { - // Allocate memory for the metadata - VkDeviceMemory metadata_memory = VK_NULL_HANDLE; - VkMemoryAllocateInfo metadata_memory_info = {}; - metadata_memory_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - metadata_memory_info.allocationSize = metadata_reqs->imageMipTailSize; - m_device->phy().set_memory_type(memory_reqs.memoryTypeBits, &metadata_memory_info, 0); - err = vkAllocateMemory(m_device->device(), &metadata_memory_info, NULL, &metadata_memory); - ASSERT_VK_SUCCESS(err); - - // Bind metadata - VkSparseMemoryBind sparse_bind = {}; - sparse_bind.resourceOffset = metadata_reqs->imageMipTailOffset; - sparse_bind.size = metadata_reqs->imageMipTailSize; - sparse_bind.memory = metadata_memory; - sparse_bind.memoryOffset = 0; - sparse_bind.flags = VK_SPARSE_MEMORY_BIND_METADATA_BIT; - - VkSparseImageOpaqueMemoryBindInfo opaque_bind_info = {}; - opaque_bind_info.image = image; - opaque_bind_info.bindCount = 1; - opaque_bind_info.pBinds = &sparse_bind; - - VkBindSparseInfo bind_info = {}; - bind_info.sType = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO; - bind_info.imageOpaqueBindCount = 1; - bind_info.pImageOpaqueBinds = &opaque_bind_info; - - vkQueueBindSparse(m_device->m_queue, 1, &bind_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyNotFound(); - - // Cleanup - vkQueueWaitIdle(m_device->m_queue); - vkFreeMemory(m_device->device(), metadata_memory, NULL); - } - - vkDestroyImage(m_device->device(), image, NULL); -} - -TEST_F(VkPositiveLayerTest, FramebufferBindingDestroyCommandPool) { - TEST_DESCRIPTION( - "This test should pass. Create a Framebuffer and command buffer, bind them together, then destroy command pool and " - "framebuffer and verify there are no errors."); - - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - - // A renderpass with one color attachment. - VkAttachmentDescription attachment = {0, - VK_FORMAT_R8G8B8A8_UNORM, - VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_STORE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - - VkAttachmentReference att_ref = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - - VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &att_ref, nullptr, nullptr, 0, nullptr}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &attachment, 1, &subpass, 0, nullptr}; - - VkRenderPass rp; - VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - - // A compatible framebuffer. - VkImageObj image(m_device); - image.Init(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - - VkImageView view = image.targetView(VK_FORMAT_R8G8B8A8_UNORM); - - VkFramebufferCreateInfo fci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 1, &view, 32, 32, 1}; - VkFramebuffer fb; - err = vkCreateFramebuffer(m_device->device(), &fci, nullptr, &fb); - ASSERT_VK_SUCCESS(err); - - // Explicitly create a command buffer to bind the FB to so that we can then - // destroy the command pool in order to implicitly free command buffer - VkCommandPool command_pool; - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool); - - VkCommandBuffer command_buffer; - VkCommandBufferAllocateInfo command_buffer_allocate_info{}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = command_pool; - command_buffer_allocate_info.commandBufferCount = 1; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, &command_buffer); - - // Begin our cmd buffer with renderpass using our framebuffer - VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, rp, fb, {{0, 0}, {32, 32}}, 0, nullptr}; - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer, &begin_info); - - vkCmdBeginRenderPass(command_buffer, &rpbi, VK_SUBPASS_CONTENTS_INLINE); - vkCmdEndRenderPass(command_buffer); - vkEndCommandBuffer(command_buffer); - // Destroy command pool to implicitly free command buffer - vkDestroyCommandPool(m_device->device(), command_pool, NULL); - vkDestroyFramebuffer(m_device->device(), fb, nullptr); - vkDestroyRenderPass(m_device->device(), rp, nullptr); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, FramebufferCreateDepthStencilLayoutTransitionForDepthOnlyImageView) { - TEST_DESCRIPTION( - "Validate that when an imageView of a depth/stencil image is used as a depth/stencil framebuffer attachment, the " - "aspectMask is ignored and both depth and stencil image subresources are used."); - - ASSERT_NO_FATAL_FAILURE(Init()); - VkFormatProperties format_properties; - vkGetPhysicalDeviceFormatProperties(gpu(), VK_FORMAT_D32_SFLOAT_S8_UINT, &format_properties); - if (!(format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) { - printf("%s Image format does not support sampling.\n", kSkipPrefix); - return; - } - - m_errorMonitor->ExpectSuccess(); - - VkAttachmentDescription attachment = {0, - VK_FORMAT_D32_SFLOAT_S8_UINT, - VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_STORE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}; - - VkAttachmentReference att_ref = {0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}; - - VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, &att_ref, 0, nullptr}; - - VkSubpassDependency dep = {0, - 0, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_DEPENDENCY_BY_REGION_BIT}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &attachment, 1, &subpass, 1, &dep}; - - VkResult err; - VkRenderPass rp; - err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - - VkImageObj image(m_device); - image.InitNoLayout(32, 32, 1, VK_FORMAT_D32_SFLOAT_S8_UINT, - 0x26, // usage - VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(image.initialized()); - image.SetLayout(0x6, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - - VkImageViewCreateInfo ivci = { - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - nullptr, - 0, - image.handle(), - VK_IMAGE_VIEW_TYPE_2D, - VK_FORMAT_D32_SFLOAT_S8_UINT, - {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}, - {0x2, 0, 1, 0, 1}, - }; - VkImageView view; - err = vkCreateImageView(m_device->device(), &ivci, nullptr, &view); - ASSERT_VK_SUCCESS(err); - - VkFramebufferCreateInfo fci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 1, &view, 32, 32, 1}; - VkFramebuffer fb; - err = vkCreateFramebuffer(m_device->device(), &fci, nullptr, &fb); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - - VkImageMemoryBarrier imb = {}; - imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - imb.pNext = nullptr; - imb.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - imb.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - imb.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - imb.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imb.srcQueueFamilyIndex = 0; - imb.dstQueueFamilyIndex = 0; - imb.image = image.handle(); - imb.subresourceRange.aspectMask = 0x6; - imb.subresourceRange.baseMipLevel = 0; - imb.subresourceRange.levelCount = 0x1; - imb.subresourceRange.baseArrayLayer = 0; - imb.subresourceRange.layerCount = 0x1; - - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &imb); - - m_commandBuffer->end(); - m_commandBuffer->QueueCommandBuffer(false); - m_errorMonitor->VerifyNotFound(); - - vkDestroyFramebuffer(m_device->device(), fb, nullptr); - vkDestroyRenderPass(m_device->device(), rp, nullptr); - vkDestroyImageView(m_device->device(), view, nullptr); -} - -// This is a positive test. No errors should be generated. -TEST_F(VkPositiveLayerTest, BarrierLayoutToImageUsage) { - TEST_DESCRIPTION("Ensure barriers' new and old VkImageLayout are compatible with their images' VkImageUsageFlags"); - - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - auto depth_format = FindSupportedDepthStencilFormat(gpu()); - if (!depth_format) { - printf("%s No Depth + Stencil format found. Skipped.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkImageMemoryBarrier img_barrier = {}; - img_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - img_barrier.pNext = NULL; - img_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; - img_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - img_barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - img_barrier.subresourceRange.baseArrayLayer = 0; - img_barrier.subresourceRange.baseMipLevel = 0; - img_barrier.subresourceRange.layerCount = 1; - img_barrier.subresourceRange.levelCount = 1; - - { - VkImageObj img_color(m_device); - img_color.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(img_color.initialized()); - - VkImageObj img_ds1(m_device); - img_ds1.Init(128, 128, 1, depth_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(img_ds1.initialized()); - - VkImageObj img_ds2(m_device); - img_ds2.Init(128, 128, 1, depth_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(img_ds2.initialized()); - - VkImageObj img_xfer_src(m_device); - img_xfer_src.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(img_xfer_src.initialized()); - - VkImageObj img_xfer_dst(m_device); - img_xfer_dst.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(img_xfer_dst.initialized()); - - VkImageObj img_sampled(m_device); - img_sampled.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(img_sampled.initialized()); - - VkImageObj img_input(m_device); - img_input.Init(128, 128, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(img_input.initialized()); - - const struct { - VkImageObj &image_obj; - VkImageLayout old_layout; - VkImageLayout new_layout; - } buffer_layouts[] = { - // clang-format off - {img_color, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL}, - {img_ds1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL}, - {img_ds2, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL}, - {img_sampled, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL}, - {img_input, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL}, - {img_xfer_src, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL}, - {img_xfer_dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL}, - // clang-format on - }; - const uint32_t layout_count = sizeof(buffer_layouts) / sizeof(buffer_layouts[0]); - - m_commandBuffer->begin(); - for (uint32_t i = 0; i < layout_count; ++i) { - img_barrier.image = buffer_layouts[i].image_obj.handle(); - const VkImageUsageFlags usage = buffer_layouts[i].image_obj.usage(); - img_barrier.subresourceRange.aspectMask = (usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) - ? (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) - : VK_IMAGE_ASPECT_COLOR_BIT; - - img_barrier.oldLayout = buffer_layouts[i].old_layout; - img_barrier.newLayout = buffer_layouts[i].new_layout; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, - nullptr, 0, nullptr, 1, &img_barrier); - - img_barrier.oldLayout = buffer_layouts[i].new_layout; - img_barrier.newLayout = buffer_layouts[i].old_layout; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, - nullptr, 0, nullptr, 1, &img_barrier); - } - m_commandBuffer->end(); - - img_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - } - m_errorMonitor->VerifyNotFound(); -} - -// This is a positive test. No errors should be generated. -TEST_F(VkPositiveLayerTest, WaitEventThenSet) { - TEST_DESCRIPTION("Wait on a event then set it after the wait has been submitted."); - - m_errorMonitor->ExpectSuccess(); - ASSERT_NO_FATAL_FAILURE(Init()); - - VkEvent event; - VkEventCreateInfo event_create_info{}; - event_create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - vkCreateEvent(m_device->device(), &event_create_info, nullptr, &event); - - VkCommandPool command_pool; - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool); - - VkCommandBuffer command_buffer; - VkCommandBufferAllocateInfo command_buffer_allocate_info{}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = command_pool; - command_buffer_allocate_info.commandBufferCount = 1; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, &command_buffer); - - VkQueue queue = VK_NULL_HANDLE; - vkGetDeviceQueue(m_device->device(), m_device->graphics_queue_node_index_, 0, &queue); - - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer, &begin_info); - - vkCmdWaitEvents(command_buffer, 1, &event, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, - nullptr, 0, nullptr); - vkCmdResetEvent(command_buffer, event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); - vkEndCommandBuffer(command_buffer); - } - { - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer; - submit_info.signalSemaphoreCount = 0; - submit_info.pSignalSemaphores = nullptr; - vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE); - } - { vkSetEvent(m_device->device(), event); } - - vkQueueWaitIdle(queue); - - vkDestroyEvent(m_device->device(), event, nullptr); - vkFreeCommandBuffers(m_device->device(), command_pool, 1, &command_buffer); - vkDestroyCommandPool(m_device->device(), command_pool, NULL); - - m_errorMonitor->VerifyNotFound(); -} -// This is a positive test. No errors should be generated. -TEST_F(VkPositiveLayerTest, QueryAndCopySecondaryCommandBuffers) { - TEST_DESCRIPTION("Issue a query on a secondary command buffer and copy it on a primary."); - - ASSERT_NO_FATAL_FAILURE(Init()); - if ((m_device->queue_props.empty()) || (m_device->queue_props[0].queueCount < 2)) { - printf("%s Queue family needs to have multiple queues to run this test.\n", kSkipPrefix); - return; - } - - m_errorMonitor->ExpectSuccess(); - - VkQueryPool query_pool; - VkQueryPoolCreateInfo query_pool_create_info{}; - query_pool_create_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; - query_pool_create_info.queryType = VK_QUERY_TYPE_TIMESTAMP; - query_pool_create_info.queryCount = 1; - vkCreateQueryPool(m_device->device(), &query_pool_create_info, nullptr, &query_pool); - - VkCommandPoolObj command_pool(m_device, m_device->graphics_queue_node_index_, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); - VkCommandBufferObj primary_buffer(m_device, &command_pool); - VkCommandBufferObj secondary_buffer(m_device, &command_pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); - - VkQueue queue = VK_NULL_HANDLE; - vkGetDeviceQueue(m_device->device(), m_device->graphics_queue_node_index_, 1, &queue); - - uint32_t qfi = 0; - VkBufferCreateInfo buff_create_info = {}; - buff_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buff_create_info.size = 1024; - buff_create_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; - buff_create_info.queueFamilyIndexCount = 1; - buff_create_info.pQueueFamilyIndices = &qfi; - - VkResult err; - VkBuffer buffer; - err = vkCreateBuffer(m_device->device(), &buff_create_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - VkMemoryRequirements memReqs; - vkGetBufferMemoryRequirements(m_device->device(), buffer, &memReqs); - VkMemoryAllocateInfo mem_alloc = {}; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.allocationSize = memReqs.size; - mem_alloc.memoryTypeIndex = 0; - bool pass = m_device->phy().set_memory_type(memReqs.memoryTypeBits, &mem_alloc, 0); - if (!pass) { - printf("%s Failed to allocate memory.\n", kSkipPrefix); - vkDestroyBuffer(m_device->device(), buffer, NULL); - return; - } - - VkDeviceMemory mem; - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &mem); - ASSERT_VK_SUCCESS(err); - err = vkBindBufferMemory(m_device->device(), buffer, mem, 0); - ASSERT_VK_SUCCESS(err); - - VkCommandBufferInheritanceInfo hinfo = {}; - hinfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; - hinfo.renderPass = VK_NULL_HANDLE; - hinfo.subpass = 0; - hinfo.framebuffer = VK_NULL_HANDLE; - hinfo.occlusionQueryEnable = VK_FALSE; - hinfo.queryFlags = 0; - hinfo.pipelineStatistics = 0; - - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - begin_info.pInheritanceInfo = &hinfo; - secondary_buffer.begin(&begin_info); - vkCmdResetQueryPool(secondary_buffer.handle(), query_pool, 0, 1); - vkCmdWriteTimestamp(secondary_buffer.handle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, query_pool, 0); - secondary_buffer.end(); - - primary_buffer.begin(); - vkCmdExecuteCommands(primary_buffer.handle(), 1, &secondary_buffer.handle()); - vkCmdCopyQueryPoolResults(primary_buffer.handle(), query_pool, 0, 1, buffer, 0, 0, 0); - primary_buffer.end(); - } - - primary_buffer.QueueCommandBuffer(); - vkQueueWaitIdle(queue); - - vkDestroyQueryPool(m_device->device(), query_pool, nullptr); - vkDestroyBuffer(m_device->device(), buffer, NULL); - vkFreeMemory(m_device->device(), mem, NULL); - - m_errorMonitor->VerifyNotFound(); -} - -// This is a positive test. No errors should be generated. -TEST_F(VkPositiveLayerTest, QueryAndCopyMultipleCommandBuffers) { - TEST_DESCRIPTION("Issue a query and copy from it on a second command buffer."); - - ASSERT_NO_FATAL_FAILURE(Init()); - if ((m_device->queue_props.empty()) || (m_device->queue_props[0].queueCount < 2)) { - printf("%s Queue family needs to have multiple queues to run this test.\n", kSkipPrefix); - return; - } - - m_errorMonitor->ExpectSuccess(); - - VkQueryPool query_pool; - VkQueryPoolCreateInfo query_pool_create_info{}; - query_pool_create_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; - query_pool_create_info.queryType = VK_QUERY_TYPE_TIMESTAMP; - query_pool_create_info.queryCount = 1; - vkCreateQueryPool(m_device->device(), &query_pool_create_info, nullptr, &query_pool); - - VkCommandPool command_pool; - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool); - - VkCommandBuffer command_buffer[2]; - VkCommandBufferAllocateInfo command_buffer_allocate_info{}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = command_pool; - command_buffer_allocate_info.commandBufferCount = 2; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, command_buffer); - - VkQueue queue = VK_NULL_HANDLE; - vkGetDeviceQueue(m_device->device(), m_device->graphics_queue_node_index_, 1, &queue); - - uint32_t qfi = 0; - VkBufferCreateInfo buff_create_info = {}; - buff_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buff_create_info.size = 1024; - buff_create_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; - buff_create_info.queueFamilyIndexCount = 1; - buff_create_info.pQueueFamilyIndices = &qfi; - - VkResult err; - VkBuffer buffer; - err = vkCreateBuffer(m_device->device(), &buff_create_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - VkMemoryRequirements memReqs; - vkGetBufferMemoryRequirements(m_device->device(), buffer, &memReqs); - VkMemoryAllocateInfo mem_alloc = {}; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.allocationSize = memReqs.size; - mem_alloc.memoryTypeIndex = 0; - bool pass = m_device->phy().set_memory_type(memReqs.memoryTypeBits, &mem_alloc, 0); - if (!pass) { - vkDestroyBuffer(m_device->device(), buffer, NULL); - return; - } - - VkDeviceMemory mem; - err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &mem); - ASSERT_VK_SUCCESS(err); - err = vkBindBufferMemory(m_device->device(), buffer, mem, 0); - ASSERT_VK_SUCCESS(err); - - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[0], &begin_info); - - vkCmdResetQueryPool(command_buffer[0], query_pool, 0, 1); - vkCmdWriteTimestamp(command_buffer[0], VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, query_pool, 0); - - vkEndCommandBuffer(command_buffer[0]); - - vkBeginCommandBuffer(command_buffer[1], &begin_info); - - vkCmdCopyQueryPoolResults(command_buffer[1], query_pool, 0, 1, buffer, 0, 0, 0); - - vkEndCommandBuffer(command_buffer[1]); - } - { - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 2; - submit_info.pCommandBuffers = command_buffer; - submit_info.signalSemaphoreCount = 0; - submit_info.pSignalSemaphores = nullptr; - vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE); - } - - vkQueueWaitIdle(queue); - - vkDestroyQueryPool(m_device->device(), query_pool, nullptr); - vkFreeCommandBuffers(m_device->device(), command_pool, 2, command_buffer); - vkDestroyCommandPool(m_device->device(), command_pool, NULL); - vkDestroyBuffer(m_device->device(), buffer, NULL); - vkFreeMemory(m_device->device(), mem, NULL); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkLayerTest, ResetEventThenSet) { - TEST_DESCRIPTION("Reset an event then set it after the reset has been submitted."); - - ASSERT_NO_FATAL_FAILURE(Init()); - VkEvent event; - VkEventCreateInfo event_create_info{}; - event_create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - vkCreateEvent(m_device->device(), &event_create_info, nullptr, &event); - - VkCommandPool command_pool; - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool); - - VkCommandBuffer command_buffer; - VkCommandBufferAllocateInfo command_buffer_allocate_info{}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = command_pool; - command_buffer_allocate_info.commandBufferCount = 1; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, &command_buffer); - - VkQueue queue = VK_NULL_HANDLE; - vkGetDeviceQueue(m_device->device(), m_device->graphics_queue_node_index_, 0, &queue); - - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer, &begin_info); - - vkCmdResetEvent(command_buffer, event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); - vkEndCommandBuffer(command_buffer); - } - { - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer; - submit_info.signalSemaphoreCount = 0; - submit_info.pSignalSemaphores = nullptr; - vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE); - } - { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "that is already in use by a command buffer."); - vkSetEvent(m_device->device(), event); - m_errorMonitor->VerifyFound(); - } - - vkQueueWaitIdle(queue); - - vkDestroyEvent(m_device->device(), event, nullptr); - vkFreeCommandBuffers(m_device->device(), command_pool, 1, &command_buffer); - vkDestroyCommandPool(m_device->device(), command_pool, NULL); -} - -// This is a positive test. No errors should be generated. -TEST_F(VkPositiveLayerTest, TwoFencesThreeFrames) { - TEST_DESCRIPTION( - "Two command buffers with two separate fences are each run through a Submit & WaitForFences cycle 3 times. This previously " - "revealed a bug so running this positive test to prevent a regression."); - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - VkQueue queue = VK_NULL_HANDLE; - vkGetDeviceQueue(m_device->device(), m_device->graphics_queue_node_index_, 0, &queue); - - static const uint32_t NUM_OBJECTS = 2; - static const uint32_t NUM_FRAMES = 3; - VkCommandBuffer cmd_buffers[NUM_OBJECTS] = {}; - VkFence fences[NUM_OBJECTS] = {}; - - VkCommandPool cmd_pool; - VkCommandPoolCreateInfo cmd_pool_ci = {}; - cmd_pool_ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - cmd_pool_ci.queueFamilyIndex = m_device->graphics_queue_node_index_; - cmd_pool_ci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - VkResult err = vkCreateCommandPool(m_device->device(), &cmd_pool_ci, nullptr, &cmd_pool); - ASSERT_VK_SUCCESS(err); - - VkCommandBufferAllocateInfo cmd_buf_info = {}; - cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - cmd_buf_info.commandPool = cmd_pool; - cmd_buf_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - cmd_buf_info.commandBufferCount = 1; - - VkFenceCreateInfo fence_ci = {}; - fence_ci.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fence_ci.pNext = nullptr; - fence_ci.flags = 0; - - for (uint32_t i = 0; i < NUM_OBJECTS; ++i) { - err = vkAllocateCommandBuffers(m_device->device(), &cmd_buf_info, &cmd_buffers[i]); - ASSERT_VK_SUCCESS(err); - err = vkCreateFence(m_device->device(), &fence_ci, nullptr, &fences[i]); - ASSERT_VK_SUCCESS(err); - } - - for (uint32_t frame = 0; frame < NUM_FRAMES; ++frame) { - for (uint32_t obj = 0; obj < NUM_OBJECTS; ++obj) { - // Create empty cmd buffer - VkCommandBufferBeginInfo cmdBufBeginDesc = {}; - cmdBufBeginDesc.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - - err = vkBeginCommandBuffer(cmd_buffers[obj], &cmdBufBeginDesc); - ASSERT_VK_SUCCESS(err); - err = vkEndCommandBuffer(cmd_buffers[obj]); - ASSERT_VK_SUCCESS(err); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &cmd_buffers[obj]; - // Submit cmd buffer and wait for fence - err = vkQueueSubmit(queue, 1, &submit_info, fences[obj]); - ASSERT_VK_SUCCESS(err); - err = vkWaitForFences(m_device->device(), 1, &fences[obj], VK_TRUE, UINT64_MAX); - ASSERT_VK_SUCCESS(err); - err = vkResetFences(m_device->device(), 1, &fences[obj]); - ASSERT_VK_SUCCESS(err); - } - } - m_errorMonitor->VerifyNotFound(); - vkDestroyCommandPool(m_device->device(), cmd_pool, NULL); - for (uint32_t i = 0; i < NUM_OBJECTS; ++i) { - vkDestroyFence(m_device->device(), fences[i], nullptr); - } -} -// This is a positive test. No errors should be generated. -TEST_F(VkPositiveLayerTest, TwoQueueSubmitsSeparateQueuesWithSemaphoreAndOneFenceQWI) { - TEST_DESCRIPTION( - "Two command buffers, each in a separate QueueSubmit call submitted on separate queues followed by a QueueWaitIdle."); - - ASSERT_NO_FATAL_FAILURE(Init()); - if ((m_device->queue_props.empty()) || (m_device->queue_props[0].queueCount < 2)) { - printf("%s Queue family needs to have multiple queues to run this test.\n", kSkipPrefix); - return; - } - - m_errorMonitor->ExpectSuccess(); - - VkSemaphore semaphore; - VkSemaphoreCreateInfo semaphore_create_info{}; - semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - vkCreateSemaphore(m_device->device(), &semaphore_create_info, nullptr, &semaphore); - - VkCommandPool command_pool; - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool); - - VkCommandBuffer command_buffer[2]; - VkCommandBufferAllocateInfo command_buffer_allocate_info{}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = command_pool; - command_buffer_allocate_info.commandBufferCount = 2; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, command_buffer); - - VkQueue queue = VK_NULL_HANDLE; - vkGetDeviceQueue(m_device->device(), m_device->graphics_queue_node_index_, 1, &queue); - - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[0], &begin_info); - - vkCmdPipelineBarrier(command_buffer[0], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 0, nullptr); - - VkViewport viewport{}; - viewport.maxDepth = 1.0f; - viewport.minDepth = 0.0f; - viewport.width = 512; - viewport.height = 512; - viewport.x = 0; - viewport.y = 0; - vkCmdSetViewport(command_buffer[0], 0, 1, &viewport); - vkEndCommandBuffer(command_buffer[0]); - } - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[1], &begin_info); - - VkViewport viewport{}; - viewport.maxDepth = 1.0f; - viewport.minDepth = 0.0f; - viewport.width = 512; - viewport.height = 512; - viewport.x = 0; - viewport.y = 0; - vkCmdSetViewport(command_buffer[1], 0, 1, &viewport); - vkEndCommandBuffer(command_buffer[1]); - } - { - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer[0]; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &semaphore; - vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE); - } - { - VkPipelineStageFlags flags[]{VK_PIPELINE_STAGE_ALL_COMMANDS_BIT}; - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer[1]; - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &semaphore; - submit_info.pWaitDstStageMask = flags; - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - } - - vkQueueWaitIdle(m_device->m_queue); - - vkDestroySemaphore(m_device->device(), semaphore, nullptr); - vkFreeCommandBuffers(m_device->device(), command_pool, 2, &command_buffer[0]); - vkDestroyCommandPool(m_device->device(), command_pool, NULL); - - m_errorMonitor->VerifyNotFound(); -} - -// This is a positive test. No errors should be generated. -TEST_F(VkPositiveLayerTest, TwoQueueSubmitsSeparateQueuesWithSemaphoreAndOneFenceQWIFence) { - TEST_DESCRIPTION( - "Two command buffers, each in a separate QueueSubmit call submitted on separate queues, the second having a fence followed " - "by a QueueWaitIdle."); - - ASSERT_NO_FATAL_FAILURE(Init()); - if ((m_device->queue_props.empty()) || (m_device->queue_props[0].queueCount < 2)) { - printf("%s Queue family needs to have multiple queues to run this test.\n", kSkipPrefix); - return; - } - - m_errorMonitor->ExpectSuccess(); - - VkFence fence; - VkFenceCreateInfo fence_create_info{}; - fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - vkCreateFence(m_device->device(), &fence_create_info, nullptr, &fence); - - VkSemaphore semaphore; - VkSemaphoreCreateInfo semaphore_create_info{}; - semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - vkCreateSemaphore(m_device->device(), &semaphore_create_info, nullptr, &semaphore); - - VkCommandPool command_pool; - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool); - - VkCommandBuffer command_buffer[2]; - VkCommandBufferAllocateInfo command_buffer_allocate_info{}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = command_pool; - command_buffer_allocate_info.commandBufferCount = 2; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, command_buffer); - - VkQueue queue = VK_NULL_HANDLE; - vkGetDeviceQueue(m_device->device(), m_device->graphics_queue_node_index_, 1, &queue); - - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[0], &begin_info); - - vkCmdPipelineBarrier(command_buffer[0], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 0, nullptr); - - VkViewport viewport{}; - viewport.maxDepth = 1.0f; - viewport.minDepth = 0.0f; - viewport.width = 512; - viewport.height = 512; - viewport.x = 0; - viewport.y = 0; - vkCmdSetViewport(command_buffer[0], 0, 1, &viewport); - vkEndCommandBuffer(command_buffer[0]); - } - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[1], &begin_info); - - VkViewport viewport{}; - viewport.maxDepth = 1.0f; - viewport.minDepth = 0.0f; - viewport.width = 512; - viewport.height = 512; - viewport.x = 0; - viewport.y = 0; - vkCmdSetViewport(command_buffer[1], 0, 1, &viewport); - vkEndCommandBuffer(command_buffer[1]); - } - { - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer[0]; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &semaphore; - vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE); - } - { - VkPipelineStageFlags flags[]{VK_PIPELINE_STAGE_ALL_COMMANDS_BIT}; - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer[1]; - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &semaphore; - submit_info.pWaitDstStageMask = flags; - vkQueueSubmit(m_device->m_queue, 1, &submit_info, fence); - } - - vkQueueWaitIdle(m_device->m_queue); - - vkDestroyFence(m_device->device(), fence, nullptr); - vkDestroySemaphore(m_device->device(), semaphore, nullptr); - vkFreeCommandBuffers(m_device->device(), command_pool, 2, &command_buffer[0]); - vkDestroyCommandPool(m_device->device(), command_pool, NULL); - - m_errorMonitor->VerifyNotFound(); -} - -// This is a positive test. No errors should be generated. -TEST_F(VkPositiveLayerTest, TwoQueueSubmitsSeparateQueuesWithSemaphoreAndOneFenceTwoWFF) { - TEST_DESCRIPTION( - "Two command buffers, each in a separate QueueSubmit call submitted on separate queues, the second having a fence followed " - "by two consecutive WaitForFences calls on the same fence."); - - ASSERT_NO_FATAL_FAILURE(Init()); - if ((m_device->queue_props.empty()) || (m_device->queue_props[0].queueCount < 2)) { - printf("%s Queue family needs to have multiple queues to run this test.\n", kSkipPrefix); - return; - } - - m_errorMonitor->ExpectSuccess(); - - VkFence fence; - VkFenceCreateInfo fence_create_info{}; - fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - vkCreateFence(m_device->device(), &fence_create_info, nullptr, &fence); - - VkSemaphore semaphore; - VkSemaphoreCreateInfo semaphore_create_info{}; - semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - vkCreateSemaphore(m_device->device(), &semaphore_create_info, nullptr, &semaphore); - - VkCommandPool command_pool; - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool); - - VkCommandBuffer command_buffer[2]; - VkCommandBufferAllocateInfo command_buffer_allocate_info{}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = command_pool; - command_buffer_allocate_info.commandBufferCount = 2; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, command_buffer); - - VkQueue queue = VK_NULL_HANDLE; - vkGetDeviceQueue(m_device->device(), m_device->graphics_queue_node_index_, 1, &queue); - - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[0], &begin_info); - - vkCmdPipelineBarrier(command_buffer[0], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 0, nullptr); - - VkViewport viewport{}; - viewport.maxDepth = 1.0f; - viewport.minDepth = 0.0f; - viewport.width = 512; - viewport.height = 512; - viewport.x = 0; - viewport.y = 0; - vkCmdSetViewport(command_buffer[0], 0, 1, &viewport); - vkEndCommandBuffer(command_buffer[0]); - } - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[1], &begin_info); - - VkViewport viewport{}; - viewport.maxDepth = 1.0f; - viewport.minDepth = 0.0f; - viewport.width = 512; - viewport.height = 512; - viewport.x = 0; - viewport.y = 0; - vkCmdSetViewport(command_buffer[1], 0, 1, &viewport); - vkEndCommandBuffer(command_buffer[1]); - } - { - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer[0]; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &semaphore; - vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE); - } - { - VkPipelineStageFlags flags[]{VK_PIPELINE_STAGE_ALL_COMMANDS_BIT}; - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer[1]; - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &semaphore; - submit_info.pWaitDstStageMask = flags; - vkQueueSubmit(m_device->m_queue, 1, &submit_info, fence); - } - - vkWaitForFences(m_device->device(), 1, &fence, VK_TRUE, UINT64_MAX); - vkWaitForFences(m_device->device(), 1, &fence, VK_TRUE, UINT64_MAX); - - vkDestroyFence(m_device->device(), fence, nullptr); - vkDestroySemaphore(m_device->device(), semaphore, nullptr); - vkFreeCommandBuffers(m_device->device(), command_pool, 2, &command_buffer[0]); - vkDestroyCommandPool(m_device->device(), command_pool, NULL); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, TwoQueuesEnsureCorrectRetirementWithWorkStolen) { - ASSERT_NO_FATAL_FAILURE(Init()); - if ((m_device->queue_props.empty()) || (m_device->queue_props[0].queueCount < 2)) { - printf("%s Test requires two queues, skipping\n", kSkipPrefix); - return; - } - - VkResult err; - - m_errorMonitor->ExpectSuccess(); - - VkQueue q0 = m_device->m_queue; - VkQueue q1 = nullptr; - vkGetDeviceQueue(m_device->device(), m_device->graphics_queue_node_index_, 1, &q1); - ASSERT_NE(q1, nullptr); - - // An (empty) command buffer. We must have work in the first submission -- - // the layer treats unfenced work differently from fenced work. - VkCommandPoolCreateInfo cpci = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, 0}; - VkCommandPool pool; - err = vkCreateCommandPool(m_device->device(), &cpci, nullptr, &pool); - ASSERT_VK_SUCCESS(err); - VkCommandBufferAllocateInfo cbai = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, pool, - VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1}; - VkCommandBuffer cb; - err = vkAllocateCommandBuffers(m_device->device(), &cbai, &cb); - ASSERT_VK_SUCCESS(err); - VkCommandBufferBeginInfo cbbi = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, 0, nullptr}; - err = vkBeginCommandBuffer(cb, &cbbi); - ASSERT_VK_SUCCESS(err); - err = vkEndCommandBuffer(cb); - ASSERT_VK_SUCCESS(err); - - // A semaphore - VkSemaphoreCreateInfo sci = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, nullptr, 0}; - VkSemaphore s; - err = vkCreateSemaphore(m_device->device(), &sci, nullptr, &s); - ASSERT_VK_SUCCESS(err); - - // First submission, to q0 - VkSubmitInfo s0 = {VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, 0, nullptr, nullptr, 1, &cb, 1, &s}; - - err = vkQueueSubmit(q0, 1, &s0, VK_NULL_HANDLE); - ASSERT_VK_SUCCESS(err); - - // Second submission, to q1, waiting on s - VkFlags waitmask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; // doesn't really matter what this value is. - VkSubmitInfo s1 = {VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, 1, &s, &waitmask, 0, nullptr, 0, nullptr}; - - err = vkQueueSubmit(q1, 1, &s1, VK_NULL_HANDLE); - ASSERT_VK_SUCCESS(err); - - // Wait for q0 idle - err = vkQueueWaitIdle(q0); - ASSERT_VK_SUCCESS(err); - - // Command buffer should have been completed (it was on q0); reset the pool. - vkFreeCommandBuffers(m_device->device(), pool, 1, &cb); - - m_errorMonitor->VerifyNotFound(); - - // Force device completely idle and clean up resources - vkDeviceWaitIdle(m_device->device()); - vkDestroyCommandPool(m_device->device(), pool, nullptr); - vkDestroySemaphore(m_device->device(), s, nullptr); -} - -// This is a positive test. No errors should be generated. -TEST_F(VkPositiveLayerTest, TwoQueueSubmitsSeparateQueuesWithSemaphoreAndOneFence) { - TEST_DESCRIPTION( - "Two command buffers, each in a separate QueueSubmit call submitted on separate queues, the second having a fence, " - "followed by a WaitForFences call."); - - ASSERT_NO_FATAL_FAILURE(Init()); - if ((m_device->queue_props.empty()) || (m_device->queue_props[0].queueCount < 2)) { - printf("%s Queue family needs to have multiple queues to run this test.\n", kSkipPrefix); - return; - } - - m_errorMonitor->ExpectSuccess(); - - VkFence fence; - VkFenceCreateInfo fence_create_info{}; - fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - vkCreateFence(m_device->device(), &fence_create_info, nullptr, &fence); - - VkSemaphore semaphore; - VkSemaphoreCreateInfo semaphore_create_info{}; - semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - vkCreateSemaphore(m_device->device(), &semaphore_create_info, nullptr, &semaphore); - - VkCommandPool command_pool; - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool); - - VkCommandBuffer command_buffer[2]; - VkCommandBufferAllocateInfo command_buffer_allocate_info{}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = command_pool; - command_buffer_allocate_info.commandBufferCount = 2; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, command_buffer); - - VkQueue queue = VK_NULL_HANDLE; - vkGetDeviceQueue(m_device->device(), m_device->graphics_queue_node_index_, 1, &queue); - - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[0], &begin_info); - - vkCmdPipelineBarrier(command_buffer[0], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 0, nullptr); - - VkViewport viewport{}; - viewport.maxDepth = 1.0f; - viewport.minDepth = 0.0f; - viewport.width = 512; - viewport.height = 512; - viewport.x = 0; - viewport.y = 0; - vkCmdSetViewport(command_buffer[0], 0, 1, &viewport); - vkEndCommandBuffer(command_buffer[0]); - } - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[1], &begin_info); - - VkViewport viewport{}; - viewport.maxDepth = 1.0f; - viewport.minDepth = 0.0f; - viewport.width = 512; - viewport.height = 512; - viewport.x = 0; - viewport.y = 0; - vkCmdSetViewport(command_buffer[1], 0, 1, &viewport); - vkEndCommandBuffer(command_buffer[1]); - } - { - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer[0]; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &semaphore; - vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE); - } - { - VkPipelineStageFlags flags[]{VK_PIPELINE_STAGE_ALL_COMMANDS_BIT}; - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer[1]; - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &semaphore; - submit_info.pWaitDstStageMask = flags; - vkQueueSubmit(m_device->m_queue, 1, &submit_info, fence); - } - - vkWaitForFences(m_device->device(), 1, &fence, VK_TRUE, UINT64_MAX); - - vkDestroyFence(m_device->device(), fence, nullptr); - vkDestroySemaphore(m_device->device(), semaphore, nullptr); - vkFreeCommandBuffers(m_device->device(), command_pool, 2, &command_buffer[0]); - vkDestroyCommandPool(m_device->device(), command_pool, NULL); - - m_errorMonitor->VerifyNotFound(); -} - -// This is a positive test. No errors should be generated. -TEST_F(VkPositiveLayerTest, TwoQueueSubmitsOneQueueWithSemaphoreAndOneFence) { - TEST_DESCRIPTION( - "Two command buffers, each in a separate QueueSubmit call on the same queue, sharing a signal/wait semaphore, the second " - "having a fence, followed by a WaitForFences call."); - - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - VkFence fence; - VkFenceCreateInfo fence_create_info{}; - fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - vkCreateFence(m_device->device(), &fence_create_info, nullptr, &fence); - - VkSemaphore semaphore; - VkSemaphoreCreateInfo semaphore_create_info{}; - semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - vkCreateSemaphore(m_device->device(), &semaphore_create_info, nullptr, &semaphore); - - VkCommandPool command_pool; - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool); - - VkCommandBuffer command_buffer[2]; - VkCommandBufferAllocateInfo command_buffer_allocate_info{}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = command_pool; - command_buffer_allocate_info.commandBufferCount = 2; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, command_buffer); - - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[0], &begin_info); - - vkCmdPipelineBarrier(command_buffer[0], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 0, nullptr); - - VkViewport viewport{}; - viewport.maxDepth = 1.0f; - viewport.minDepth = 0.0f; - viewport.width = 512; - viewport.height = 512; - viewport.x = 0; - viewport.y = 0; - vkCmdSetViewport(command_buffer[0], 0, 1, &viewport); - vkEndCommandBuffer(command_buffer[0]); - } - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[1], &begin_info); - - VkViewport viewport{}; - viewport.maxDepth = 1.0f; - viewport.minDepth = 0.0f; - viewport.width = 512; - viewport.height = 512; - viewport.x = 0; - viewport.y = 0; - vkCmdSetViewport(command_buffer[1], 0, 1, &viewport); - vkEndCommandBuffer(command_buffer[1]); - } - { - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer[0]; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &semaphore; - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - } - { - VkPipelineStageFlags flags[]{VK_PIPELINE_STAGE_ALL_COMMANDS_BIT}; - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer[1]; - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &semaphore; - submit_info.pWaitDstStageMask = flags; - vkQueueSubmit(m_device->m_queue, 1, &submit_info, fence); - } - - vkWaitForFences(m_device->device(), 1, &fence, VK_TRUE, UINT64_MAX); - - vkDestroyFence(m_device->device(), fence, nullptr); - vkDestroySemaphore(m_device->device(), semaphore, nullptr); - vkFreeCommandBuffers(m_device->device(), command_pool, 2, &command_buffer[0]); - vkDestroyCommandPool(m_device->device(), command_pool, NULL); - - m_errorMonitor->VerifyNotFound(); -} - -// This is a positive test. No errors should be generated. -TEST_F(VkPositiveLayerTest, TwoQueueSubmitsOneQueueNullQueueSubmitWithFence) { - TEST_DESCRIPTION( - "Two command buffers, each in a separate QueueSubmit call on the same queue, no fences, followed by a third QueueSubmit " - "with NO SubmitInfos but with a fence, followed by a WaitForFences call."); - - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - VkFence fence; - VkFenceCreateInfo fence_create_info{}; - fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - vkCreateFence(m_device->device(), &fence_create_info, nullptr, &fence); - - VkCommandPool command_pool; - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool); - - VkCommandBuffer command_buffer[2]; - VkCommandBufferAllocateInfo command_buffer_allocate_info{}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = command_pool; - command_buffer_allocate_info.commandBufferCount = 2; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, command_buffer); - - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[0], &begin_info); - - vkCmdPipelineBarrier(command_buffer[0], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 0, nullptr); - - VkViewport viewport{}; - viewport.maxDepth = 1.0f; - viewport.minDepth = 0.0f; - viewport.width = 512; - viewport.height = 512; - viewport.x = 0; - viewport.y = 0; - vkCmdSetViewport(command_buffer[0], 0, 1, &viewport); - vkEndCommandBuffer(command_buffer[0]); - } - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[1], &begin_info); - - VkViewport viewport{}; - viewport.maxDepth = 1.0f; - viewport.minDepth = 0.0f; - viewport.width = 512; - viewport.height = 512; - viewport.x = 0; - viewport.y = 0; - vkCmdSetViewport(command_buffer[1], 0, 1, &viewport); - vkEndCommandBuffer(command_buffer[1]); - } - { - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer[0]; - submit_info.signalSemaphoreCount = 0; - submit_info.pSignalSemaphores = VK_NULL_HANDLE; - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - } - { - VkPipelineStageFlags flags[]{VK_PIPELINE_STAGE_ALL_COMMANDS_BIT}; - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer[1]; - submit_info.waitSemaphoreCount = 0; - submit_info.pWaitSemaphores = VK_NULL_HANDLE; - submit_info.pWaitDstStageMask = flags; - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - } - - vkQueueSubmit(m_device->m_queue, 0, NULL, fence); - - VkResult err = vkWaitForFences(m_device->device(), 1, &fence, VK_TRUE, UINT64_MAX); - ASSERT_VK_SUCCESS(err); - - vkDestroyFence(m_device->device(), fence, nullptr); - vkFreeCommandBuffers(m_device->device(), command_pool, 2, &command_buffer[0]); - vkDestroyCommandPool(m_device->device(), command_pool, NULL); - - m_errorMonitor->VerifyNotFound(); -} - -// This is a positive test. No errors should be generated. -TEST_F(VkPositiveLayerTest, TwoQueueSubmitsOneQueueOneFence) { - TEST_DESCRIPTION( - "Two command buffers, each in a separate QueueSubmit call on the same queue, the second having a fence, followed by a " - "WaitForFences call."); - - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - VkFence fence; - VkFenceCreateInfo fence_create_info{}; - fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - vkCreateFence(m_device->device(), &fence_create_info, nullptr, &fence); - - VkCommandPool command_pool; - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool); - - VkCommandBuffer command_buffer[2]; - VkCommandBufferAllocateInfo command_buffer_allocate_info{}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = command_pool; - command_buffer_allocate_info.commandBufferCount = 2; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, command_buffer); - - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[0], &begin_info); - - vkCmdPipelineBarrier(command_buffer[0], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 0, nullptr); - - VkViewport viewport{}; - viewport.maxDepth = 1.0f; - viewport.minDepth = 0.0f; - viewport.width = 512; - viewport.height = 512; - viewport.x = 0; - viewport.y = 0; - vkCmdSetViewport(command_buffer[0], 0, 1, &viewport); - vkEndCommandBuffer(command_buffer[0]); - } - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[1], &begin_info); - - VkViewport viewport{}; - viewport.maxDepth = 1.0f; - viewport.minDepth = 0.0f; - viewport.width = 512; - viewport.height = 512; - viewport.x = 0; - viewport.y = 0; - vkCmdSetViewport(command_buffer[1], 0, 1, &viewport); - vkEndCommandBuffer(command_buffer[1]); - } - { - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer[0]; - submit_info.signalSemaphoreCount = 0; - submit_info.pSignalSemaphores = VK_NULL_HANDLE; - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - } - { - VkPipelineStageFlags flags[]{VK_PIPELINE_STAGE_ALL_COMMANDS_BIT}; - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer[1]; - submit_info.waitSemaphoreCount = 0; - submit_info.pWaitSemaphores = VK_NULL_HANDLE; - submit_info.pWaitDstStageMask = flags; - vkQueueSubmit(m_device->m_queue, 1, &submit_info, fence); - } - - vkWaitForFences(m_device->device(), 1, &fence, VK_TRUE, UINT64_MAX); - - vkDestroyFence(m_device->device(), fence, nullptr); - vkFreeCommandBuffers(m_device->device(), command_pool, 2, &command_buffer[0]); - vkDestroyCommandPool(m_device->device(), command_pool, NULL); - - m_errorMonitor->VerifyNotFound(); -} - -// This is a positive test. No errors should be generated. -TEST_F(VkPositiveLayerTest, TwoSubmitInfosWithSemaphoreOneQueueSubmitsOneFence) { - TEST_DESCRIPTION( - "Two command buffers each in a separate SubmitInfo sent in a single QueueSubmit call followed by a WaitForFences call."); - ASSERT_NO_FATAL_FAILURE(Init()); - - m_errorMonitor->ExpectSuccess(); - - VkFence fence; - VkFenceCreateInfo fence_create_info{}; - fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - vkCreateFence(m_device->device(), &fence_create_info, nullptr, &fence); - - VkSemaphore semaphore; - VkSemaphoreCreateInfo semaphore_create_info{}; - semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - vkCreateSemaphore(m_device->device(), &semaphore_create_info, nullptr, &semaphore); - - VkCommandPool command_pool; - VkCommandPoolCreateInfo pool_create_info{}; - pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool); - - VkCommandBuffer command_buffer[2]; - VkCommandBufferAllocateInfo command_buffer_allocate_info{}; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.commandPool = command_pool; - command_buffer_allocate_info.commandBufferCount = 2; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, command_buffer); - - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[0], &begin_info); - - vkCmdPipelineBarrier(command_buffer[0], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 0, nullptr); - - VkViewport viewport{}; - viewport.maxDepth = 1.0f; - viewport.minDepth = 0.0f; - viewport.width = 512; - viewport.height = 512; - viewport.x = 0; - viewport.y = 0; - vkCmdSetViewport(command_buffer[0], 0, 1, &viewport); - vkEndCommandBuffer(command_buffer[0]); - } - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkBeginCommandBuffer(command_buffer[1], &begin_info); - - VkViewport viewport{}; - viewport.maxDepth = 1.0f; - viewport.minDepth = 0.0f; - viewport.width = 512; - viewport.height = 512; - viewport.x = 0; - viewport.y = 0; - vkCmdSetViewport(command_buffer[1], 0, 1, &viewport); - vkEndCommandBuffer(command_buffer[1]); - } - { - VkSubmitInfo submit_info[2]; - VkPipelineStageFlags flags[]{VK_PIPELINE_STAGE_ALL_COMMANDS_BIT}; - - submit_info[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info[0].pNext = NULL; - submit_info[0].commandBufferCount = 1; - submit_info[0].pCommandBuffers = &command_buffer[0]; - submit_info[0].signalSemaphoreCount = 1; - submit_info[0].pSignalSemaphores = &semaphore; - submit_info[0].waitSemaphoreCount = 0; - submit_info[0].pWaitSemaphores = NULL; - submit_info[0].pWaitDstStageMask = 0; - - submit_info[1].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info[1].pNext = NULL; - submit_info[1].commandBufferCount = 1; - submit_info[1].pCommandBuffers = &command_buffer[1]; - submit_info[1].waitSemaphoreCount = 1; - submit_info[1].pWaitSemaphores = &semaphore; - submit_info[1].pWaitDstStageMask = flags; - submit_info[1].signalSemaphoreCount = 0; - submit_info[1].pSignalSemaphores = NULL; - vkQueueSubmit(m_device->m_queue, 2, &submit_info[0], fence); - } - - vkWaitForFences(m_device->device(), 1, &fence, VK_TRUE, UINT64_MAX); - - vkDestroyFence(m_device->device(), fence, nullptr); - vkFreeCommandBuffers(m_device->device(), command_pool, 2, &command_buffer[0]); - vkDestroyCommandPool(m_device->device(), command_pool, NULL); - vkDestroySemaphore(m_device->device(), semaphore, nullptr); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, CreatePipelineAttribMatrixType) { - TEST_DESCRIPTION("Test that pipeline validation accepts matrices passed as vertex attributes"); - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkVertexInputBindingDescription input_binding; - memset(&input_binding, 0, sizeof(input_binding)); - - VkVertexInputAttributeDescription input_attribs[2]; - memset(input_attribs, 0, sizeof(input_attribs)); - - for (int i = 0; i < 2; i++) { - input_attribs[i].format = VK_FORMAT_R32G32B32A32_SFLOAT; - input_attribs[i].location = i; - } - - char const *vsSource = - "#version 450\n" - "\n" - "layout(location=0) in mat2x4 x;\n" - "void main(){\n" - " gl_Position = x[0] + x[1];\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - pipe.AddVertexInputBindings(&input_binding, 1); - pipe.AddVertexInputAttribs(input_attribs, 2); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - /* expect success */ - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, CreatePipelineAttribArrayType) { - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkVertexInputBindingDescription input_binding; - memset(&input_binding, 0, sizeof(input_binding)); - - VkVertexInputAttributeDescription input_attribs[2]; - memset(input_attribs, 0, sizeof(input_attribs)); - - for (int i = 0; i < 2; i++) { - input_attribs[i].format = VK_FORMAT_R32G32B32A32_SFLOAT; - input_attribs[i].location = i; - } - - char const *vsSource = - "#version 450\n" - "\n" - "layout(location=0) in vec4 x[2];\n" - "void main(){\n" - " gl_Position = x[0] + x[1];\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - pipe.AddVertexInputBindings(&input_binding, 1); - pipe.AddVertexInputAttribs(input_attribs, 2); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, CreatePipelineAttribComponents) { - TEST_DESCRIPTION( - "Test that pipeline validation accepts consuming a vertex attribute through multiple vertex shader inputs, each consuming " - "a different subset of the components, and that fragment shader-attachment validation tolerates multiple duplicate " - "location outputs"); - m_errorMonitor->ExpectSuccess(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkVertexInputBindingDescription input_binding; - memset(&input_binding, 0, sizeof(input_binding)); - - VkVertexInputAttributeDescription input_attribs[3]; - memset(input_attribs, 0, sizeof(input_attribs)); - - for (int i = 0; i < 3; i++) { - input_attribs[i].format = VK_FORMAT_R32G32B32A32_SFLOAT; - input_attribs[i].location = i; - } - - char const *vsSource = - "#version 450\n" - "\n" - "layout(location=0) in vec4 x;\n" - "layout(location=1) in vec3 y1;\n" - "layout(location=1, component=3) in float y2;\n" - "layout(location=2) in vec4 z;\n" - "void main(){\n" - " gl_Position = x + vec4(y1, y2) + z;\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0, component=0) out float color0;\n" - "layout(location=0, component=1) out float color1;\n" - "layout(location=0, component=2) out float color2;\n" - "layout(location=0, component=3) out float color3;\n" - "layout(location=1, component=0) out vec2 second_color0;\n" - "layout(location=1, component=2) out vec2 second_color1;\n" - "void main(){\n" - " color0 = float(1);\n" - " second_color0 = vec2(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - // Create a renderPass with two color attachments - VkAttachmentReference attachments[2] = {}; - attachments[0].layout = VK_IMAGE_LAYOUT_GENERAL; - attachments[1].attachment = 1; - attachments[1].layout = VK_IMAGE_LAYOUT_GENERAL; - - VkSubpassDescription subpass = {}; - subpass.pColorAttachments = attachments; - subpass.colorAttachmentCount = 2; - - VkRenderPassCreateInfo rpci = {}; - rpci.subpassCount = 1; - rpci.pSubpasses = &subpass; - rpci.attachmentCount = 2; - - VkAttachmentDescription attach_desc[2] = {}; - attach_desc[0].format = VK_FORMAT_B8G8R8A8_UNORM; - attach_desc[0].samples = VK_SAMPLE_COUNT_1_BIT; - attach_desc[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attach_desc[0].finalLayout = VK_IMAGE_LAYOUT_GENERAL; - attach_desc[0].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attach_desc[1].format = VK_FORMAT_B8G8R8A8_UNORM; - attach_desc[1].samples = VK_SAMPLE_COUNT_1_BIT; - attach_desc[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attach_desc[1].finalLayout = VK_IMAGE_LAYOUT_GENERAL; - attach_desc[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - - rpci.pAttachments = attach_desc; - rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - - VkRenderPass renderpass; - vkCreateRenderPass(m_device->device(), &rpci, NULL, &renderpass); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkPipelineColorBlendAttachmentState att_state1 = {}; - att_state1.dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR; - att_state1.blendEnable = VK_FALSE; - - pipe.AddColorAttachment(0, att_state1); - pipe.AddColorAttachment(1, att_state1); - pipe.AddVertexInputBindings(&input_binding, 1); - pipe.AddVertexInputAttribs(input_attribs, 3); - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderpass); - vkDestroyRenderPass(m_device->device(), renderpass, nullptr); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, CreatePipelineSimplePositive) { - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "void main(){\n" - " gl_Position = vec4(0);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, CreatePipelineRelaxedTypeMatch) { - TEST_DESCRIPTION( - "Test that pipeline validation accepts the relaxed type matching rules set out in 14.1.3: fundamental type must match, and " - "producer side must have at least as many components"); - m_errorMonitor->ExpectSuccess(); - - // VK 1.0.8 Specification, 14.1.3 "Additionally,..." block - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - char const *vsSource = - "#version 450\n" - "layout(location=0) out vec3 x;\n" - "layout(location=1) out ivec3 y;\n" - "layout(location=2) out vec3 z;\n" - "void main(){\n" - " gl_Position = vec4(0);\n" - " x = vec3(0); y = ivec3(0); z = vec3(0);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "layout(location=0) in float x;\n" - "layout(location=1) flat in int y;\n" - "layout(location=2) in vec2 z;\n" - "void main(){\n" - " color = vec4(1 + x + y + z.x);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - VkResult err = VK_SUCCESS; - err = pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, CreatePipelineTessPerVertex) { - TEST_DESCRIPTION("Test that pipeline validation accepts per-vertex variables passed between the TCS and TES stages"); - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - if (!m_device->phy().features().tessellationShader) { - printf("%s Device does not support tessellation shaders; skipped.\n", kSkipPrefix); - return; - } - - char const *vsSource = - "#version 450\n" - "void main(){}\n"; - char const *tcsSource = - "#version 450\n" - "layout(location=0) out int x[];\n" - "layout(vertices=3) out;\n" - "void main(){\n" - " gl_TessLevelOuter[0] = gl_TessLevelOuter[1] = gl_TessLevelOuter[2] = 1;\n" - " gl_TessLevelInner[0] = 1;\n" - " x[gl_InvocationID] = gl_InvocationID;\n" - "}\n"; - char const *tesSource = - "#version 450\n" - "layout(triangles, equal_spacing, cw) in;\n" - "layout(location=0) in int x[];\n" - "void main(){\n" - " gl_Position.xyz = gl_TessCoord;\n" - " gl_Position.w = x[0] + x[1] + x[2];\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj tcs(m_device, tcsSource, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, this); - VkShaderObj tes(m_device, tesSource, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineInputAssemblyStateCreateInfo iasci{VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, nullptr, 0, - VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, VK_FALSE}; - - VkPipelineTessellationStateCreateInfo tsci{VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, nullptr, 0, 3}; - - VkPipelineObj pipe(m_device); - pipe.SetInputAssembly(&iasci); - pipe.SetTessellation(&tsci); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&tcs); - pipe.AddShader(&tes); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, CreatePipelineGeometryInputBlockPositive) { - TEST_DESCRIPTION( - "Test that pipeline validation accepts a user-defined interface block passed into the geometry shader. This is interesting " - "because the 'extra' array level is not present on the member type, but on the block instance."); - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - if (!m_device->phy().features().geometryShader) { - printf("%s Device does not support geometry shaders; skipped.\n", kSkipPrefix); - return; - } - - char const *vsSource = - "#version 450\n" - "layout(location=0) out VertexData { vec4 x; } vs_out;\n" - "void main(){\n" - " vs_out.x = vec4(1);\n" - "}\n"; - char const *gsSource = - "#version 450\n" - "layout(triangles) in;\n" - "layout(triangle_strip, max_vertices=3) out;\n" - "layout(location=0) in VertexData { vec4 x; } gs_in[];\n" - "void main() {\n" - " gl_Position = gs_in[0].x;\n" - " EmitVertex();\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj gs(m_device, gsSource, VK_SHADER_STAGE_GEOMETRY_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&gs); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, CreatePipeline64BitAttributesPositive) { - TEST_DESCRIPTION( - "Test that pipeline validation accepts basic use of 64bit vertex attributes. This is interesting because they consume " - "multiple locations."); - m_errorMonitor->ExpectSuccess(); - - if (!EnableDeviceProfileLayer()) { - printf("%s Failed to enable device profile layer.\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - ASSERT_NO_FATAL_FAILURE(InitState()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - if (!m_device->phy().features().shaderFloat64) { - printf("%s Device does not support 64bit vertex attributes; skipped.\n", kSkipPrefix); - return; - } - // Set 64bit format to support VTX Buffer feature - PFN_vkSetPhysicalDeviceFormatPropertiesEXT fpvkSetPhysicalDeviceFormatPropertiesEXT = nullptr; - PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT = nullptr; - - // Load required functions - if (!LoadDeviceProfileLayer(fpvkSetPhysicalDeviceFormatPropertiesEXT, fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT)) { - return; - } - VkFormatProperties format_props; - fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT(gpu(), VK_FORMAT_R64G64B64A64_SFLOAT, &format_props); - format_props.bufferFeatures |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT; - fpvkSetPhysicalDeviceFormatPropertiesEXT(gpu(), VK_FORMAT_R64G64B64A64_SFLOAT, format_props); - - VkVertexInputBindingDescription input_bindings[1]; - memset(input_bindings, 0, sizeof(input_bindings)); - - VkVertexInputAttributeDescription input_attribs[4]; - memset(input_attribs, 0, sizeof(input_attribs)); - input_attribs[0].location = 0; - input_attribs[0].offset = 0; - input_attribs[0].format = VK_FORMAT_R64G64B64A64_SFLOAT; - input_attribs[1].location = 2; - input_attribs[1].offset = 32; - input_attribs[1].format = VK_FORMAT_R64G64B64A64_SFLOAT; - input_attribs[2].location = 4; - input_attribs[2].offset = 64; - input_attribs[2].format = VK_FORMAT_R64G64B64A64_SFLOAT; - input_attribs[3].location = 6; - input_attribs[3].offset = 96; - input_attribs[3].format = VK_FORMAT_R64G64B64A64_SFLOAT; - - char const *vsSource = - "#version 450\n" - "\n" - "layout(location=0) in dmat4 x;\n" - "void main(){\n" - " gl_Position = vec4(x[0][0]);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - - pipe.AddVertexInputBindings(input_bindings, 1); - pipe.AddVertexInputAttribs(input_attribs, 4); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, CreatePipelineInputAttachmentPositive) { - TEST_DESCRIPTION("Positive test for a correctly matched input attachment"); - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(input_attachment_index=0, set=0, binding=0) uniform subpassInput x;\n" - "layout(location=0) out vec4 color;\n" - "void main() {\n" - " color = subpassLoad(x);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetLayoutBinding dslb = {0, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}; - const VkDescriptorSetLayoutObj dsl(m_device, {dslb}); - const VkPipelineLayoutObj pl(m_device, {&dsl}); - - VkAttachmentDescription descs[2] = { - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, - VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, - VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL}, - }; - VkAttachmentReference color = { - 0, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - }; - VkAttachmentReference input = { - 1, - VK_IMAGE_LAYOUT_GENERAL, - }; - - VkSubpassDescription sd = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &input, 1, &color, nullptr, nullptr, 0, nullptr}; - - VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 2, descs, 1, &sd, 0, nullptr}; - VkRenderPass rp; - VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - - // should be OK. would go wrong here if it's going to... - pipe.CreateVKPipeline(pl.handle(), rp); - - m_errorMonitor->VerifyNotFound(); - - vkDestroyRenderPass(m_device->device(), rp, nullptr); -} - -TEST_F(VkPositiveLayerTest, CreateComputePipelineMissingDescriptorUnusedPositive) { - TEST_DESCRIPTION( - "Test that pipeline validation accepts a compute pipeline which declares a descriptor-backed resource which is not " - "provided, but the shader does not statically use it. This is interesting because it requires compute pipelines to have a " - "proper descriptor use walk, which they didn't for some time."); - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - - char const *csSource = - "#version 450\n" - "\n" - "layout(local_size_x=1) in;\n" - "layout(set=0, binding=0) buffer block { vec4 x; };\n" - "void main(){\n" - " // x is not used.\n" - "}\n"; - - VkShaderObj cs(m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT, this); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - VkComputePipelineCreateInfo cpci = {VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - nullptr, - 0, - {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0, - VK_SHADER_STAGE_COMPUTE_BIT, cs.handle(), "main", nullptr}, - descriptorSet.GetPipelineLayout(), - VK_NULL_HANDLE, - -1}; - - VkPipeline pipe; - VkResult err = vkCreateComputePipelines(m_device->device(), VK_NULL_HANDLE, 1, &cpci, nullptr, &pipe); - - m_errorMonitor->VerifyNotFound(); - - if (err == VK_SUCCESS) { - vkDestroyPipeline(m_device->device(), pipe, nullptr); - } -} - -TEST_F(VkPositiveLayerTest, CreateComputePipelineCombinedImageSamplerConsumedAsSampler) { - TEST_DESCRIPTION( - "Test that pipeline validation accepts a shader consuming only the sampler portion of a combined image + sampler"); - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - - std::vector<VkDescriptorSetLayoutBinding> bindings = { - {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}, - {1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}, - {2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}, - }; - - const VkDescriptorSetLayoutObj dsl(m_device, bindings); - const VkPipelineLayoutObj pl(m_device, {&dsl}); - - char const *csSource = - "#version 450\n" - "\n" - "layout(local_size_x=1) in;\n" - "layout(set=0, binding=0) uniform sampler s;\n" - "layout(set=0, binding=1) uniform texture2D t;\n" - "layout(set=0, binding=2) buffer block { vec4 x; };\n" - "void main() {\n" - " x = texture(sampler2D(t, s), vec2(0));\n" - "}\n"; - VkShaderObj cs(m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT, this); - - VkComputePipelineCreateInfo cpci = {VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - nullptr, - 0, - {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0, - VK_SHADER_STAGE_COMPUTE_BIT, cs.handle(), "main", nullptr}, - pl.handle(), - VK_NULL_HANDLE, - -1}; - - VkPipeline pipe; - VkResult err = vkCreateComputePipelines(m_device->device(), VK_NULL_HANDLE, 1, &cpci, nullptr, &pipe); - - m_errorMonitor->VerifyNotFound(); - - if (err == VK_SUCCESS) { - vkDestroyPipeline(m_device->device(), pipe, nullptr); - } -} - -TEST_F(VkPositiveLayerTest, CreateComputePipelineCombinedImageSamplerConsumedAsImage) { - TEST_DESCRIPTION( - "Test that pipeline validation accepts a shader consuming only the image portion of a combined image + sampler"); - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - - std::vector<VkDescriptorSetLayoutBinding> bindings = { - {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}, - {1, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}, - {2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}, - }; - - const VkDescriptorSetLayoutObj dsl(m_device, bindings); - const VkPipelineLayoutObj pl(m_device, {&dsl}); - - char const *csSource = - "#version 450\n" - "\n" - "layout(local_size_x=1) in;\n" - "layout(set=0, binding=0) uniform texture2D t;\n" - "layout(set=0, binding=1) uniform sampler s;\n" - "layout(set=0, binding=2) buffer block { vec4 x; };\n" - "void main() {\n" - " x = texture(sampler2D(t, s), vec2(0));\n" - "}\n"; - VkShaderObj cs(m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT, this); - - VkComputePipelineCreateInfo cpci = {VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - nullptr, - 0, - {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0, - VK_SHADER_STAGE_COMPUTE_BIT, cs.handle(), "main", nullptr}, - pl.handle(), - VK_NULL_HANDLE, - -1}; - - VkPipeline pipe; - VkResult err = vkCreateComputePipelines(m_device->device(), VK_NULL_HANDLE, 1, &cpci, nullptr, &pipe); - - m_errorMonitor->VerifyNotFound(); - - if (err == VK_SUCCESS) { - vkDestroyPipeline(m_device->device(), pipe, nullptr); - } -} - -TEST_F(VkPositiveLayerTest, CreateComputePipelineCombinedImageSamplerConsumedAsBoth) { - TEST_DESCRIPTION( - "Test that pipeline validation accepts a shader consuming both the sampler and the image of a combined image+sampler but " - "via separate variables"); - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - - std::vector<VkDescriptorSetLayoutBinding> bindings = { - {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}, - {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}, - }; - - const VkDescriptorSetLayoutObj dsl(m_device, bindings); - const VkPipelineLayoutObj pl(m_device, {&dsl}); - - char const *csSource = - "#version 450\n" - "\n" - "layout(local_size_x=1) in;\n" - "layout(set=0, binding=0) uniform texture2D t;\n" - "layout(set=0, binding=0) uniform sampler s; // both binding 0!\n" - "layout(set=0, binding=1) buffer block { vec4 x; };\n" - "void main() {\n" - " x = texture(sampler2D(t, s), vec2(0));\n" - "}\n"; - VkShaderObj cs(m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT, this); - - VkComputePipelineCreateInfo cpci = {VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - nullptr, - 0, - {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0, - VK_SHADER_STAGE_COMPUTE_BIT, cs.handle(), "main", nullptr}, - pl.handle(), - VK_NULL_HANDLE, - -1}; - - VkPipeline pipe; - VkResult err = vkCreateComputePipelines(m_device->device(), VK_NULL_HANDLE, 1, &cpci, nullptr, &pipe); - - m_errorMonitor->VerifyNotFound(); - - if (err == VK_SUCCESS) { - vkDestroyPipeline(m_device->device(), pipe, nullptr); - } -} - -TEST_F(VkPositiveLayerTest, CreateDescriptorSetBindingWithIgnoredSamplers) { - TEST_DESCRIPTION("Test that layers conditionally do ignore the pImmutableSamplers on vkCreateDescriptorSetLayout"); - - bool prop2_found = false; - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - prop2_found = true; - } else { - printf("%s %s Extension not supported, skipping push descriptor sub-tests\n", kSkipPrefix, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - bool push_descriptor_found = false; - if (prop2_found && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - - // In addition to the extension being supported we need to have at least one available - // Some implementations report an invalid maxPushDescriptors of 0 - push_descriptor_found = GetPushDescriptorProperties(instance(), gpu()).maxPushDescriptors > 0; - } else { - printf("%s %s Extension not supported, skipping push descriptor sub-tests\n", kSkipPrefix, - VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - const uint64_t fake_address_64 = 0xCDCDCDCDCDCDCDCD; - const uint64_t fake_address_32 = 0xCDCDCDCD; - const void *fake_pointer = - sizeof(void *) == 8 ? reinterpret_cast<void *>(fake_address_64) : reinterpret_cast<void *>(fake_address_32); - const VkSampler *hopefully_undereferencable_pointer = reinterpret_cast<const VkSampler *>(fake_pointer); - - // regular descriptors - m_errorMonitor->ExpectSuccess(); - { - const VkDescriptorSetLayoutBinding non_sampler_bindings[] = { - {0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT, hopefully_undereferencable_pointer}, - {1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT, hopefully_undereferencable_pointer}, - {2, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, hopefully_undereferencable_pointer}, - {3, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, hopefully_undereferencable_pointer}, - {4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, hopefully_undereferencable_pointer}, - {5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, hopefully_undereferencable_pointer}, - {6, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_FRAGMENT_BIT, hopefully_undereferencable_pointer}, - {7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_FRAGMENT_BIT, hopefully_undereferencable_pointer}, - {8, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, VK_SHADER_STAGE_FRAGMENT_BIT, hopefully_undereferencable_pointer}, - }; - const VkDescriptorSetLayoutCreateInfo dslci = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, nullptr, 0, - static_cast<uint32_t>(size(non_sampler_bindings)), non_sampler_bindings}; - VkDescriptorSetLayout dsl; - const VkResult err = vkCreateDescriptorSetLayout(m_device->device(), &dslci, nullptr, &dsl); - ASSERT_VK_SUCCESS(err); - vkDestroyDescriptorSetLayout(m_device->device(), dsl, nullptr); - } - m_errorMonitor->VerifyNotFound(); - - if (push_descriptor_found) { - // push descriptors - m_errorMonitor->ExpectSuccess(); - { - const VkDescriptorSetLayoutBinding non_sampler_bindings[] = { - {0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT, hopefully_undereferencable_pointer}, - {1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT, hopefully_undereferencable_pointer}, - {2, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, hopefully_undereferencable_pointer}, - {3, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, hopefully_undereferencable_pointer}, - {4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, hopefully_undereferencable_pointer}, - {5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, hopefully_undereferencable_pointer}, - {6, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, VK_SHADER_STAGE_FRAGMENT_BIT, hopefully_undereferencable_pointer}, - }; - const VkDescriptorSetLayoutCreateInfo dslci = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, nullptr, - VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, - static_cast<uint32_t>(size(non_sampler_bindings)), non_sampler_bindings}; - VkDescriptorSetLayout dsl; - const VkResult err = vkCreateDescriptorSetLayout(m_device->device(), &dslci, nullptr, &dsl); - ASSERT_VK_SUCCESS(err); - vkDestroyDescriptorSetLayout(m_device->device(), dsl, nullptr); - } - m_errorMonitor->VerifyNotFound(); - } -} - -TEST_F(VkPositiveLayerTest, Maintenance1Tests) { - TEST_DESCRIPTION("Validate various special cases for the Maintenance1_KHR extension"); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - } else { - printf("%s Maintenance1 Extension not supported, skipping tests\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - m_errorMonitor->ExpectSuccess(); - - VkCommandBufferObj cmd_buf(m_device, m_commandPool); - cmd_buf.begin(); - // Set Negative height, should give error if Maintenance 1 is not enabled - VkViewport viewport = {0, 0, 16, -16, 0, 1}; - vkCmdSetViewport(cmd_buf.handle(), 0, 1, &viewport); - cmd_buf.end(); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkLayerTest, DuplicateValidPNextStructures) { - TEST_DESCRIPTION("Create a pNext chain containing valid structures, but with a duplicate structure type"); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME); - } else { - printf("%s VK_NV_dedicated_allocation extension not supported, skipping test\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - // Create two pNext structures which by themselves would be valid - VkDedicatedAllocationBufferCreateInfoNV dedicated_buffer_create_info = {}; - VkDedicatedAllocationBufferCreateInfoNV dedicated_buffer_create_info_2 = {}; - dedicated_buffer_create_info.sType = VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV; - dedicated_buffer_create_info.pNext = &dedicated_buffer_create_info_2; - dedicated_buffer_create_info.dedicatedAllocation = VK_TRUE; - - dedicated_buffer_create_info_2.sType = VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV; - dedicated_buffer_create_info_2.pNext = nullptr; - dedicated_buffer_create_info_2.dedicatedAllocation = VK_TRUE; - - uint32_t queue_family_index = 0; - VkBufferCreateInfo buffer_create_info = {}; - buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_create_info.pNext = &dedicated_buffer_create_info; - buffer_create_info.size = 1024; - buffer_create_info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - buffer_create_info.queueFamilyIndexCount = 1; - buffer_create_info.pQueueFamilyIndices = &queue_family_index; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "chain contains duplicate structure types"); - VkBuffer buffer; - vkCreateBuffer(m_device->device(), &buffer_create_info, NULL, &buffer); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, DedicatedAllocation) { - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - } else { - printf("%s Dedicated allocation extension not supported, skipping test\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkMemoryPropertyFlags mem_flags = 0; - const VkDeviceSize resource_size = 1024; - auto buffer_info = VkBufferObj::create_info(resource_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT); - VkBufferObj buffer; - buffer.init_no_mem(*m_device, buffer_info); - auto buffer_alloc_info = vk_testing::DeviceMemory::get_resource_alloc_info(*m_device, buffer.memory_requirements(), mem_flags); - auto buffer_dedicated_info = lvl_init_struct<VkMemoryDedicatedAllocateInfoKHR>(); - buffer_dedicated_info.buffer = buffer.handle(); - buffer_alloc_info.pNext = &buffer_dedicated_info; - vk_testing::DeviceMemory dedicated_buffer_memory; - dedicated_buffer_memory.init(*m_device, buffer_alloc_info); - - VkBufferObj wrong_buffer; - wrong_buffer.init_no_mem(*m_device, buffer_info); - - // Bind with wrong buffer - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindBufferMemory-memory-01508"); - vkBindBufferMemory(m_device->handle(), wrong_buffer.handle(), dedicated_buffer_memory.handle(), 0); - m_errorMonitor->VerifyFound(); - - // Bind with non-zero offset (same VUID) - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkBindBufferMemory-memory-01508"); // offset must be zero - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkBindBufferMemory-size-01037"); // offset pushes us past size - auto offset = buffer.memory_requirements().alignment; - vkBindBufferMemory(m_device->handle(), buffer.handle(), dedicated_buffer_memory.handle(), offset); - m_errorMonitor->VerifyFound(); - - // Bind correctly (depends on the "skip" above) - m_errorMonitor->ExpectSuccess(); - vkBindBufferMemory(m_device->handle(), buffer.handle(), dedicated_buffer_memory.handle(), 0); - m_errorMonitor->VerifyNotFound(); - - // And for images... - vk_testing::Image image; - vk_testing::Image wrong_image; - auto image_info = vk_testing::Image::create_info(); - image_info.extent.width = resource_size; - image_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; - image_info.format = VK_FORMAT_R8G8B8A8_UNORM; - image.init_no_mem(*m_device, image_info); - wrong_image.init_no_mem(*m_device, image_info); - - auto image_dedicated_info = lvl_init_struct<VkMemoryDedicatedAllocateInfoKHR>(); - image_dedicated_info.image = image.handle(); - auto image_alloc_info = vk_testing::DeviceMemory::get_resource_alloc_info(*m_device, image.memory_requirements(), mem_flags); - image_alloc_info.pNext = &image_dedicated_info; - vk_testing::DeviceMemory dedicated_image_memory; - dedicated_image_memory.init(*m_device, image_alloc_info); - - // Bind with wrong image - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindImageMemory-memory-01509"); - vkBindImageMemory(m_device->handle(), wrong_image.handle(), dedicated_image_memory.handle(), 0); - m_errorMonitor->VerifyFound(); - - // Bind with non-zero offset (same VUID) - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkBindImageMemory-memory-01509"); // offset must be zero - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkBindImageMemory-size-01049"); // offset pushes us past size - auto image_offset = image.memory_requirements().alignment; - vkBindImageMemory(m_device->handle(), image.handle(), dedicated_image_memory.handle(), image_offset); - m_errorMonitor->VerifyFound(); - - // Bind correctly (depends on the "skip" above) - m_errorMonitor->ExpectSuccess(); - vkBindImageMemory(m_device->handle(), image.handle(), dedicated_image_memory.handle(), 0); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, ValidStructPNext) { - TEST_DESCRIPTION("Verify that a valid pNext value is handled correctly"); - - // Positive test to check parameter_validation and unique_objects support for NV_dedicated_allocation - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME); - } else { - printf("%s VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME Extension not supported, skipping test\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - m_errorMonitor->ExpectSuccess(); - - VkDedicatedAllocationBufferCreateInfoNV dedicated_buffer_create_info = {}; - dedicated_buffer_create_info.sType = VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV; - dedicated_buffer_create_info.pNext = nullptr; - dedicated_buffer_create_info.dedicatedAllocation = VK_TRUE; - - uint32_t queue_family_index = 0; - VkBufferCreateInfo buffer_create_info = {}; - buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_create_info.pNext = &dedicated_buffer_create_info; - buffer_create_info.size = 1024; - buffer_create_info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - buffer_create_info.queueFamilyIndexCount = 1; - buffer_create_info.pQueueFamilyIndices = &queue_family_index; - - VkBuffer buffer; - VkResult err = vkCreateBuffer(m_device->device(), &buffer_create_info, NULL, &buffer); - ASSERT_VK_SUCCESS(err); - - VkMemoryRequirements memory_reqs; - vkGetBufferMemoryRequirements(m_device->device(), buffer, &memory_reqs); - - VkDedicatedAllocationMemoryAllocateInfoNV dedicated_memory_info = {}; - dedicated_memory_info.sType = VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV; - dedicated_memory_info.pNext = nullptr; - dedicated_memory_info.buffer = buffer; - dedicated_memory_info.image = VK_NULL_HANDLE; - - VkMemoryAllocateInfo memory_info = {}; - memory_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_info.pNext = &dedicated_memory_info; - memory_info.allocationSize = memory_reqs.size; - - bool pass; - pass = m_device->phy().set_memory_type(memory_reqs.memoryTypeBits, &memory_info, 0); - ASSERT_TRUE(pass); - - VkDeviceMemory buffer_memory; - err = vkAllocateMemory(m_device->device(), &memory_info, NULL, &buffer_memory); - ASSERT_VK_SUCCESS(err); - - err = vkBindBufferMemory(m_device->device(), buffer, buffer_memory, 0); - ASSERT_VK_SUCCESS(err); - - vkDestroyBuffer(m_device->device(), buffer, NULL); - vkFreeMemory(m_device->device(), buffer_memory, NULL); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, PSOPolygonModeValid) { - TEST_DESCRIPTION("Verify that using a solid polygon fill mode works correctly."); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - std::vector<const char *> device_extension_names; - auto features = m_device->phy().features(); - // Artificially disable support for non-solid fill modes - features.fillModeNonSolid = false; - // The sacrificial device object - VkDeviceObj test_device(0, gpu(), device_extension_names, &features); - - VkRenderpassObj render_pass(&test_device); - - const VkPipelineLayoutObj pipeline_layout(&test_device); - - VkPipelineRasterizationStateCreateInfo rs_ci = {}; - rs_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rs_ci.pNext = nullptr; - rs_ci.lineWidth = 1.0f; - rs_ci.rasterizerDiscardEnable = false; - - VkShaderObj vs(&test_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(&test_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - // Set polygonMode=FILL. No error is expected - m_errorMonitor->ExpectSuccess(); - { - VkPipelineObj pipe(&test_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - // Set polygonMode to a good value - rs_ci.polygonMode = VK_POLYGON_MODE_FILL; - pipe.SetRasterization(&rs_ci); - pipe.CreateVKPipeline(pipeline_layout.handle(), render_pass.handle()); - } - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, LongSemaphoreChain) { - m_errorMonitor->ExpectSuccess(); - - ASSERT_NO_FATAL_FAILURE(Init()); - VkResult err; - - std::vector<VkSemaphore> semaphores; - - const int chainLength = 32768; - VkPipelineStageFlags flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - - for (int i = 0; i < chainLength; i++) { - VkSemaphoreCreateInfo sci = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, nullptr, 0}; - VkSemaphore semaphore; - err = vkCreateSemaphore(m_device->device(), &sci, nullptr, &semaphore); - ASSERT_VK_SUCCESS(err); - - semaphores.push_back(semaphore); - - VkSubmitInfo si = {VK_STRUCTURE_TYPE_SUBMIT_INFO, - nullptr, - semaphores.size() > 1 ? 1u : 0u, - semaphores.size() > 1 ? &semaphores[semaphores.size() - 2] : nullptr, - &flags, - 0, - nullptr, - 1, - &semaphores[semaphores.size() - 1]}; - err = vkQueueSubmit(m_device->m_queue, 1, &si, VK_NULL_HANDLE); - ASSERT_VK_SUCCESS(err); - } - - VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, 0}; - VkFence fence; - err = vkCreateFence(m_device->device(), &fci, nullptr, &fence); - ASSERT_VK_SUCCESS(err); - VkSubmitInfo si = {VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, 1, &semaphores.back(), &flags, 0, nullptr, 0, nullptr}; - err = vkQueueSubmit(m_device->m_queue, 1, &si, fence); - ASSERT_VK_SUCCESS(err); - - vkWaitForFences(m_device->device(), 1, &fence, VK_TRUE, UINT64_MAX); - - for (auto semaphore : semaphores) vkDestroySemaphore(m_device->device(), semaphore, nullptr); - - vkDestroyFence(m_device->device(), fence, nullptr); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, ExternalSemaphore) { -#ifdef _WIN32 - const auto extension_name = VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME; - const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR; -#else - const auto extension_name = VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME; - const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; -#endif - // Check for external semaphore instance extensions - if (InstanceExtensionSupported(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME); - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s External semaphore extension not supported, skipping test\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - // Check for external semaphore device extensions - if (DeviceExtensionSupported(gpu(), nullptr, extension_name)) { - m_device_extension_names.push_back(extension_name); - m_device_extension_names.push_back(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME); - } else { - printf("%s External semaphore extension not supported, skipping test\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - // Check for external semaphore import and export capability - VkPhysicalDeviceExternalSemaphoreInfoKHR esi = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR, nullptr, - handle_type}; - VkExternalSemaphorePropertiesKHR esp = {VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR, nullptr}; - auto vkGetPhysicalDeviceExternalSemaphorePropertiesKHR = - (PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)vkGetInstanceProcAddr( - instance(), "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR"); - vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(gpu(), &esi, &esp); - - if (!(esp.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR) || - !(esp.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR)) { - printf("%s External semaphore does not support importing and exporting, skipping test\n", kSkipPrefix); - return; - } - - VkResult err; - m_errorMonitor->ExpectSuccess(); - - // Create a semaphore to export payload from - VkExportSemaphoreCreateInfoKHR esci = {VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR, nullptr, handle_type}; - VkSemaphoreCreateInfo sci = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &esci, 0}; - - VkSemaphore export_semaphore; - err = vkCreateSemaphore(m_device->device(), &sci, nullptr, &export_semaphore); - ASSERT_VK_SUCCESS(err); - - // Create a semaphore to import payload into - sci.pNext = nullptr; - VkSemaphore import_semaphore; - err = vkCreateSemaphore(m_device->device(), &sci, nullptr, &import_semaphore); - ASSERT_VK_SUCCESS(err); - -#ifdef _WIN32 - // Export semaphore payload to an opaque handle - HANDLE handle = nullptr; - VkSemaphoreGetWin32HandleInfoKHR ghi = {VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR, nullptr, export_semaphore, - handle_type}; - auto vkGetSemaphoreWin32HandleKHR = - (PFN_vkGetSemaphoreWin32HandleKHR)vkGetDeviceProcAddr(m_device->device(), "vkGetSemaphoreWin32HandleKHR"); - err = vkGetSemaphoreWin32HandleKHR(m_device->device(), &ghi, &handle); - ASSERT_VK_SUCCESS(err); - - // Import opaque handle exported above - VkImportSemaphoreWin32HandleInfoKHR ihi = { - VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR, nullptr, import_semaphore, 0, handle_type, handle, nullptr}; - auto vkImportSemaphoreWin32HandleKHR = - (PFN_vkImportSemaphoreWin32HandleKHR)vkGetDeviceProcAddr(m_device->device(), "vkImportSemaphoreWin32HandleKHR"); - err = vkImportSemaphoreWin32HandleKHR(m_device->device(), &ihi); - ASSERT_VK_SUCCESS(err); -#else - // Export semaphore payload to an opaque handle - int fd = 0; - VkSemaphoreGetFdInfoKHR ghi = {VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, nullptr, export_semaphore, handle_type}; - auto vkGetSemaphoreFdKHR = (PFN_vkGetSemaphoreFdKHR)vkGetDeviceProcAddr(m_device->device(), "vkGetSemaphoreFdKHR"); - err = vkGetSemaphoreFdKHR(m_device->device(), &ghi, &fd); - ASSERT_VK_SUCCESS(err); - - // Import opaque handle exported above - VkImportSemaphoreFdInfoKHR ihi = { - VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, nullptr, import_semaphore, 0, handle_type, fd}; - auto vkImportSemaphoreFdKHR = (PFN_vkImportSemaphoreFdKHR)vkGetDeviceProcAddr(m_device->device(), "vkImportSemaphoreFdKHR"); - err = vkImportSemaphoreFdKHR(m_device->device(), &ihi); - ASSERT_VK_SUCCESS(err); -#endif - - // Signal the exported semaphore and wait on the imported semaphore - VkPipelineStageFlags flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - VkSubmitInfo si[] = { - {VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, 0, nullptr, &flags, 0, nullptr, 1, &export_semaphore}, - {VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, 1, &import_semaphore, &flags, 0, nullptr, 0, nullptr}, - {VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, 0, nullptr, &flags, 0, nullptr, 1, &export_semaphore}, - {VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, 1, &import_semaphore, &flags, 0, nullptr, 0, nullptr}, - }; - err = vkQueueSubmit(m_device->m_queue, 4, si, VK_NULL_HANDLE); - ASSERT_VK_SUCCESS(err); - - if (m_device->phy().features().sparseBinding) { - // Signal the imported semaphore and wait on the exported semaphore - VkBindSparseInfo bi[] = { - {VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 1, &import_semaphore}, - {VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, nullptr, 1, &export_semaphore, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr}, - {VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 1, &import_semaphore}, - {VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, nullptr, 1, &export_semaphore, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr}, - }; - err = vkQueueBindSparse(m_device->m_queue, 4, bi, VK_NULL_HANDLE); - ASSERT_VK_SUCCESS(err); - } - - // Cleanup - err = vkQueueWaitIdle(m_device->m_queue); - ASSERT_VK_SUCCESS(err); - vkDestroySemaphore(m_device->device(), export_semaphore, nullptr); - vkDestroySemaphore(m_device->device(), import_semaphore, nullptr); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, ExternalFence) { -#ifdef _WIN32 - const auto extension_name = VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME; - const auto handle_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR; -#else - const auto extension_name = VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME; - const auto handle_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; -#endif - // Check for external fence instance extensions - if (InstanceExtensionSupported(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME); - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s External fence extension not supported, skipping test\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - // Check for external fence device extensions - if (DeviceExtensionSupported(gpu(), nullptr, extension_name)) { - m_device_extension_names.push_back(extension_name); - m_device_extension_names.push_back(VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME); - } else { - printf("%s External fence extension not supported, skipping test\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - // Check for external fence import and export capability - VkPhysicalDeviceExternalFenceInfoKHR efi = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR, nullptr, handle_type}; - VkExternalFencePropertiesKHR efp = {VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR, nullptr}; - auto vkGetPhysicalDeviceExternalFencePropertiesKHR = (PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)vkGetInstanceProcAddr( - instance(), "vkGetPhysicalDeviceExternalFencePropertiesKHR"); - vkGetPhysicalDeviceExternalFencePropertiesKHR(gpu(), &efi, &efp); - - if (!(efp.externalFenceFeatures & VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR) || - !(efp.externalFenceFeatures & VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR)) { - printf("%s External fence does not support importing and exporting, skipping test\n", kSkipPrefix); - return; - } - - VkResult err; - m_errorMonitor->ExpectSuccess(); - - // Create a fence to export payload from - VkFence export_fence; - { - VkExportFenceCreateInfoKHR efci = {VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR, nullptr, handle_type}; - VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, &efci, 0}; - err = vkCreateFence(m_device->device(), &fci, nullptr, &export_fence); - ASSERT_VK_SUCCESS(err); - } - - // Create a fence to import payload into - VkFence import_fence; - { - VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, 0}; - err = vkCreateFence(m_device->device(), &fci, nullptr, &import_fence); - ASSERT_VK_SUCCESS(err); - } - -#ifdef _WIN32 - // Export fence payload to an opaque handle - HANDLE handle = nullptr; - { - VkFenceGetWin32HandleInfoKHR ghi = {VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR, nullptr, export_fence, handle_type}; - auto vkGetFenceWin32HandleKHR = - (PFN_vkGetFenceWin32HandleKHR)vkGetDeviceProcAddr(m_device->device(), "vkGetFenceWin32HandleKHR"); - err = vkGetFenceWin32HandleKHR(m_device->device(), &ghi, &handle); - ASSERT_VK_SUCCESS(err); - } - - // Import opaque handle exported above - { - VkImportFenceWin32HandleInfoKHR ifi = { - VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR, nullptr, import_fence, 0, handle_type, handle, nullptr}; - auto vkImportFenceWin32HandleKHR = - (PFN_vkImportFenceWin32HandleKHR)vkGetDeviceProcAddr(m_device->device(), "vkImportFenceWin32HandleKHR"); - err = vkImportFenceWin32HandleKHR(m_device->device(), &ifi); - ASSERT_VK_SUCCESS(err); - } -#else - // Export fence payload to an opaque handle - int fd = 0; - { - VkFenceGetFdInfoKHR gfi = {VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR, nullptr, export_fence, handle_type}; - auto vkGetFenceFdKHR = (PFN_vkGetFenceFdKHR)vkGetDeviceProcAddr(m_device->device(), "vkGetFenceFdKHR"); - err = vkGetFenceFdKHR(m_device->device(), &gfi, &fd); - ASSERT_VK_SUCCESS(err); - } - - // Import opaque handle exported above - { - VkImportFenceFdInfoKHR ifi = {VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR, nullptr, import_fence, 0, handle_type, fd}; - auto vkImportFenceFdKHR = (PFN_vkImportFenceFdKHR)vkGetDeviceProcAddr(m_device->device(), "vkImportFenceFdKHR"); - err = vkImportFenceFdKHR(m_device->device(), &ifi); - ASSERT_VK_SUCCESS(err); - } -#endif - - // Signal the exported fence and wait on the imported fence - vkQueueSubmit(m_device->m_queue, 0, nullptr, export_fence); - vkWaitForFences(m_device->device(), 1, &import_fence, VK_TRUE, 1000000000); - vkResetFences(m_device->device(), 1, &import_fence); - vkQueueSubmit(m_device->m_queue, 0, nullptr, export_fence); - vkWaitForFences(m_device->device(), 1, &import_fence, VK_TRUE, 1000000000); - vkResetFences(m_device->device(), 1, &import_fence); - - // Signal the imported fence and wait on the exported fence - vkQueueSubmit(m_device->m_queue, 0, nullptr, import_fence); - vkWaitForFences(m_device->device(), 1, &export_fence, VK_TRUE, 1000000000); - vkResetFences(m_device->device(), 1, &export_fence); - vkQueueSubmit(m_device->m_queue, 0, nullptr, import_fence); - vkWaitForFences(m_device->device(), 1, &export_fence, VK_TRUE, 1000000000); - vkResetFences(m_device->device(), 1, &export_fence); - - // Cleanup - err = vkQueueWaitIdle(m_device->m_queue); - ASSERT_VK_SUCCESS(err); - vkDestroyFence(m_device->device(), export_fence, nullptr); - vkDestroyFence(m_device->device(), import_fence, nullptr); - - m_errorMonitor->VerifyNotFound(); -} - -extern "C" void *ReleaseNullFence(void *arg) { - struct thread_data_struct *data = (struct thread_data_struct *)arg; - - for (int i = 0; i < 40000; i++) { - vkDestroyFence(data->device, VK_NULL_HANDLE, NULL); - if (data->bailout) { - break; - } - } - return NULL; -} - -TEST_F(VkPositiveLayerTest, ThreadNullFenceCollision) { - test_platform_thread thread; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "THREADING ERROR"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - struct thread_data_struct data; - data.device = m_device->device(); - data.bailout = false; - m_errorMonitor->SetBailout(&data.bailout); - - // Call vkDestroyFence of VK_NULL_HANDLE repeatedly using multiple threads. - // There should be no validation error from collision of that non-object. - test_platform_thread_create(&thread, ReleaseNullFence, (void *)&data); - for (int i = 0; i < 40000; i++) { - vkDestroyFence(m_device->device(), VK_NULL_HANDLE, NULL); - } - test_platform_thread_join(thread, NULL); - - m_errorMonitor->SetBailout(NULL); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, ClearColorImageWithValidRange) { - TEST_DESCRIPTION("Record clear color with a valid VkImageSubresourceRange"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkImageObj image(m_device); - image.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(image.create_info().arrayLayers == 1); - ASSERT_TRUE(image.initialized()); - image.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - const VkClearColorValue clear_color = {{0.0f, 0.0f, 0.0f, 1.0f}}; - - m_commandBuffer->begin(); - const auto cb_handle = m_commandBuffer->handle(); - - // Try good case - { - m_errorMonitor->ExpectSuccess(); - VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - vkCmdClearColorImage(cb_handle, image.handle(), image.Layout(), &clear_color, 1, &range); - m_errorMonitor->VerifyNotFound(); - } - - // Try good case with VK_REMAINING - { - m_errorMonitor->ExpectSuccess(); - VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS}; - vkCmdClearColorImage(cb_handle, image.handle(), image.Layout(), &clear_color, 1, &range); - m_errorMonitor->VerifyNotFound(); - } -} - -TEST_F(VkPositiveLayerTest, ClearDepthStencilWithValidRange) { - TEST_DESCRIPTION("Record clear depth with a valid VkImageSubresourceRange"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - auto depth_format = FindSupportedDepthStencilFormat(gpu()); - if (!depth_format) { - printf("%s No Depth + Stencil format found. Skipped.\n", kSkipPrefix); - return; - } - - VkImageObj image(m_device); - image.Init(32, 32, 1, depth_format, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL); - ASSERT_TRUE(image.create_info().arrayLayers == 1); - ASSERT_TRUE(image.initialized()); - const VkImageAspectFlags ds_aspect = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - image.SetLayout(ds_aspect, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - const VkClearDepthStencilValue clear_value = {}; - - m_commandBuffer->begin(); - const auto cb_handle = m_commandBuffer->handle(); - - // Try good case - { - m_errorMonitor->ExpectSuccess(); - VkImageSubresourceRange range = {ds_aspect, 0, 1, 0, 1}; - vkCmdClearDepthStencilImage(cb_handle, image.handle(), image.Layout(), &clear_value, 1, &range); - m_errorMonitor->VerifyNotFound(); - } - - // Try good case with VK_REMAINING - { - m_errorMonitor->ExpectSuccess(); - VkImageSubresourceRange range = {ds_aspect, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS}; - vkCmdClearDepthStencilImage(cb_handle, image.handle(), image.Layout(), &clear_value, 1, &range); - m_errorMonitor->VerifyNotFound(); - } -} - -TEST_F(VkPositiveLayerTest, CreateGraphicsPipelineWithIgnoredPointers) { - TEST_DESCRIPTION("Create Graphics Pipeline with pointers that must be ignored by layers"); - - ASSERT_NO_FATAL_FAILURE(Init()); - - m_depth_stencil_fmt = FindSupportedDepthStencilFormat(gpu()); - ASSERT_TRUE(m_depth_stencil_fmt != 0); - - m_depthStencil->Init(m_device, static_cast<int32_t>(m_width), static_cast<int32_t>(m_height), m_depth_stencil_fmt); - - ASSERT_NO_FATAL_FAILURE(InitRenderTarget(m_depthStencil->BindInfo())); - - const uint64_t fake_address_64 = 0xCDCDCDCDCDCDCDCD; - const uint64_t fake_address_32 = 0xCDCDCDCD; - void *hopefully_undereferencable_pointer = - sizeof(void *) == 8 ? reinterpret_cast<void *>(fake_address_64) : reinterpret_cast<void *>(fake_address_32); - - VkShaderObj vs(m_device, "#version 450\nvoid main(){gl_Position = vec4(0.0, 0.0, 0.0, 1.0);}\n", VK_SHADER_STAGE_VERTEX_BIT, - this); - - const VkPipelineVertexInputStateCreateInfo pipeline_vertex_input_state_create_info{ - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - nullptr, // pNext - 0, // flags - 0, - nullptr, // bindings - 0, - nullptr // attributes - }; - - const VkPipelineInputAssemblyStateCreateInfo pipeline_input_assembly_state_create_info{ - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, - nullptr, // pNext - 0, // flags - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, - VK_FALSE // primitive restart - }; - - const VkPipelineRasterizationStateCreateInfo pipeline_rasterization_state_create_info_template{ - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - nullptr, // pNext - 0, // flags - VK_FALSE, // depthClamp - VK_FALSE, // rasterizerDiscardEnable - VK_POLYGON_MODE_FILL, - VK_CULL_MODE_NONE, - VK_FRONT_FACE_COUNTER_CLOCKWISE, - VK_FALSE, // depthBias - 0.0f, - 0.0f, - 0.0f, // depthBias params - 1.0f // lineWidth - }; - - VkPipelineLayout pipeline_layout; - { - VkPipelineLayoutCreateInfo pipeline_layout_create_info{ - VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - nullptr, // pNext - 0, // flags - 0, - nullptr, // layouts - 0, - nullptr // push constants - }; - - VkResult err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_create_info, nullptr, &pipeline_layout); - ASSERT_VK_SUCCESS(err); - } - - // try disabled rasterizer and no tessellation - { - m_errorMonitor->ExpectSuccess(); - - VkPipelineRasterizationStateCreateInfo pipeline_rasterization_state_create_info = - pipeline_rasterization_state_create_info_template; - pipeline_rasterization_state_create_info.rasterizerDiscardEnable = VK_TRUE; - - VkGraphicsPipelineCreateInfo graphics_pipeline_create_info{ - VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - nullptr, // pNext - 0, // flags - 1, // stageCount - &vs.GetStageCreateInfo(), - &pipeline_vertex_input_state_create_info, - &pipeline_input_assembly_state_create_info, - reinterpret_cast<const VkPipelineTessellationStateCreateInfo *>(hopefully_undereferencable_pointer), - reinterpret_cast<const VkPipelineViewportStateCreateInfo *>(hopefully_undereferencable_pointer), - &pipeline_rasterization_state_create_info, - reinterpret_cast<const VkPipelineMultisampleStateCreateInfo *>(hopefully_undereferencable_pointer), - reinterpret_cast<const VkPipelineDepthStencilStateCreateInfo *>(hopefully_undereferencable_pointer), - reinterpret_cast<const VkPipelineColorBlendStateCreateInfo *>(hopefully_undereferencable_pointer), - nullptr, // dynamic states - pipeline_layout, - m_renderPass, - 0, // subpass - VK_NULL_HANDLE, - 0}; - - VkPipeline pipeline; - vkCreateGraphicsPipelines(m_device->handle(), VK_NULL_HANDLE, 1, &graphics_pipeline_create_info, nullptr, &pipeline); - - m_errorMonitor->VerifyNotFound(); - - vkDestroyPipeline(m_device->handle(), pipeline, nullptr); - } - - const VkPipelineMultisampleStateCreateInfo pipeline_multisample_state_create_info{ - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - nullptr, // pNext - 0, // flags - VK_SAMPLE_COUNT_1_BIT, - VK_FALSE, // sample shading - 0.0f, // minSampleShading - nullptr, // pSampleMask - VK_FALSE, // alphaToCoverageEnable - VK_FALSE // alphaToOneEnable - }; - - // try enabled rasterizer but no subpass attachments - { - m_errorMonitor->ExpectSuccess(); - - VkPipelineRasterizationStateCreateInfo pipeline_rasterization_state_create_info = - pipeline_rasterization_state_create_info_template; - pipeline_rasterization_state_create_info.rasterizerDiscardEnable = VK_FALSE; - - VkViewport viewport = {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}; - VkRect2D scissor = {{0, 0}, {static_cast<uint32_t>(m_width), static_cast<uint32_t>(m_height)}}; - - const VkPipelineViewportStateCreateInfo pipeline_viewport_state_create_info{ - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, - nullptr, // pNext - 0, // flags - 1, - &viewport, - 1, - &scissor}; - - VkRenderPass render_pass; - { - VkSubpassDescription subpass_desc = {}; - - VkRenderPassCreateInfo render_pass_create_info{ - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - nullptr, // pNext - 0, // flags - 0, - nullptr, // attachments - 1, - &subpass_desc, - 0, - nullptr // subpass dependencies - }; - - VkResult err = vkCreateRenderPass(m_device->handle(), &render_pass_create_info, nullptr, &render_pass); - ASSERT_VK_SUCCESS(err); - } - - VkGraphicsPipelineCreateInfo graphics_pipeline_create_info{ - VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - nullptr, // pNext - 0, // flags - 1, // stageCount - &vs.GetStageCreateInfo(), - &pipeline_vertex_input_state_create_info, - &pipeline_input_assembly_state_create_info, - nullptr, - &pipeline_viewport_state_create_info, - &pipeline_rasterization_state_create_info, - &pipeline_multisample_state_create_info, - reinterpret_cast<const VkPipelineDepthStencilStateCreateInfo *>(hopefully_undereferencable_pointer), - reinterpret_cast<const VkPipelineColorBlendStateCreateInfo *>(hopefully_undereferencable_pointer), - nullptr, // dynamic states - pipeline_layout, - render_pass, - 0, // subpass - VK_NULL_HANDLE, - 0}; - - VkPipeline pipeline; - vkCreateGraphicsPipelines(m_device->handle(), VK_NULL_HANDLE, 1, &graphics_pipeline_create_info, nullptr, &pipeline); - - m_errorMonitor->VerifyNotFound(); - - vkDestroyPipeline(m_device->handle(), pipeline, nullptr); - vkDestroyRenderPass(m_device->handle(), render_pass, nullptr); - } - - // try dynamic viewport and scissor - { - m_errorMonitor->ExpectSuccess(); - - VkPipelineRasterizationStateCreateInfo pipeline_rasterization_state_create_info = - pipeline_rasterization_state_create_info_template; - pipeline_rasterization_state_create_info.rasterizerDiscardEnable = VK_FALSE; - - const VkPipelineViewportStateCreateInfo pipeline_viewport_state_create_info{ - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, - nullptr, // pNext - 0, // flags - 1, - reinterpret_cast<const VkViewport *>(hopefully_undereferencable_pointer), - 1, - reinterpret_cast<const VkRect2D *>(hopefully_undereferencable_pointer)}; - - const VkPipelineDepthStencilStateCreateInfo pipeline_depth_stencil_state_create_info{ - VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, - nullptr, // pNext - 0, // flags - }; - - const VkPipelineColorBlendAttachmentState pipeline_color_blend_attachment_state = {}; - - const VkPipelineColorBlendStateCreateInfo pipeline_color_blend_state_create_info{ - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, - nullptr, // pNext - 0, // flags - VK_FALSE, - VK_LOGIC_OP_CLEAR, - 1, - &pipeline_color_blend_attachment_state, - {0.0f, 0.0f, 0.0f, 0.0f}}; - - const VkDynamicState dynamic_states[2] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - - const VkPipelineDynamicStateCreateInfo pipeline_dynamic_state_create_info{ - VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, - nullptr, // pNext - 0, // flags - 2, dynamic_states}; - - VkGraphicsPipelineCreateInfo graphics_pipeline_create_info{VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - nullptr, // pNext - 0, // flags - 1, // stageCount - &vs.GetStageCreateInfo(), - &pipeline_vertex_input_state_create_info, - &pipeline_input_assembly_state_create_info, - nullptr, - &pipeline_viewport_state_create_info, - &pipeline_rasterization_state_create_info, - &pipeline_multisample_state_create_info, - &pipeline_depth_stencil_state_create_info, - &pipeline_color_blend_state_create_info, - &pipeline_dynamic_state_create_info, // dynamic states - pipeline_layout, - m_renderPass, - 0, // subpass - VK_NULL_HANDLE, - 0}; - - VkPipeline pipeline; - vkCreateGraphicsPipelines(m_device->handle(), VK_NULL_HANDLE, 1, &graphics_pipeline_create_info, nullptr, &pipeline); - - m_errorMonitor->VerifyNotFound(); - - vkDestroyPipeline(m_device->handle(), pipeline, nullptr); - } - - vkDestroyPipelineLayout(m_device->handle(), pipeline_layout, nullptr); -} - -TEST_F(VkPositiveLayerTest, ExternalMemory) { - TEST_DESCRIPTION("Perform a copy through a pair of buffers linked by external memory"); - -#ifdef _WIN32 - const auto ext_mem_extension_name = VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME; - const auto handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR; -#else - const auto ext_mem_extension_name = VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME; - const auto handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; -#endif - - // Check for external memory instance extensions - std::vector<const char *> reqd_instance_extensions = { - {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME}}; - for (auto extension_name : reqd_instance_extensions) { - if (InstanceExtensionSupported(extension_name)) { - m_instance_extension_names.push_back(extension_name); - } else { - printf("%s Required instance extension %s not supported, skipping test\n", kSkipPrefix, extension_name); - return; - } - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - // Check for import/export capability - VkPhysicalDeviceExternalBufferInfoKHR ebi = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR, nullptr, 0, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, handle_type}; - VkExternalBufferPropertiesKHR ebp = {VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR, nullptr, {0, 0, 0}}; - auto vkGetPhysicalDeviceExternalBufferPropertiesKHR = (PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)vkGetInstanceProcAddr( - instance(), "vkGetPhysicalDeviceExternalBufferPropertiesKHR"); - ASSERT_TRUE(vkGetPhysicalDeviceExternalBufferPropertiesKHR != nullptr); - vkGetPhysicalDeviceExternalBufferPropertiesKHR(gpu(), &ebi, &ebp); - if (!(ebp.externalMemoryProperties.compatibleHandleTypes & handle_type) || - !(ebp.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) || - !(ebp.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR)) { - printf("%s External buffer does not support importing and exporting, skipping test\n", kSkipPrefix); - return; - } - - // Check if dedicated allocation is required - bool dedicated_allocation = - ebp.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR; - if (dedicated_allocation) { - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - } else { - printf("%s Dedicated allocation extension not supported, skipping test\n", kSkipPrefix); - return; - } - } - - // Check for external memory device extensions - if (DeviceExtensionSupported(gpu(), nullptr, ext_mem_extension_name)) { - m_device_extension_names.push_back(ext_mem_extension_name); - m_device_extension_names.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME); - } else { - printf("%s External memory extension not supported, skipping test\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - m_errorMonitor->ExpectSuccess(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT); - - VkMemoryPropertyFlags mem_flags = 0; - const VkDeviceSize buffer_size = 1024; - - // Create export and import buffers - const VkExternalMemoryBufferCreateInfoKHR external_buffer_info = {VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR, - nullptr, handle_type}; - auto buffer_info = VkBufferObj::create_info(buffer_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); - buffer_info.pNext = &external_buffer_info; - VkBufferObj buffer_export; - buffer_export.init_no_mem(*m_device, buffer_info); - VkBufferObj buffer_import; - buffer_import.init_no_mem(*m_device, buffer_info); - - // Allocation info - auto alloc_info = vk_testing::DeviceMemory::get_resource_alloc_info(*m_device, buffer_export.memory_requirements(), mem_flags); - - // Add export allocation info to pNext chain - VkExportMemoryAllocateInfoKHR export_info = {VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR, nullptr, handle_type}; - alloc_info.pNext = &export_info; - - // Add dedicated allocation info to pNext chain if required - VkMemoryDedicatedAllocateInfoKHR dedicated_info = {VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, nullptr, - VK_NULL_HANDLE, buffer_export.handle()}; - if (dedicated_allocation) { - export_info.pNext = &dedicated_info; - } - - // Allocate memory to be exported - vk_testing::DeviceMemory memory_export; - memory_export.init(*m_device, alloc_info); - - // Bind exported memory - buffer_export.bind_memory(memory_export, 0); - -#ifdef _WIN32 - // Export memory to handle - auto vkGetMemoryWin32HandleKHR = (PFN_vkGetMemoryWin32HandleKHR)vkGetInstanceProcAddr(instance(), "vkGetMemoryWin32HandleKHR"); - ASSERT_TRUE(vkGetMemoryWin32HandleKHR != nullptr); - VkMemoryGetWin32HandleInfoKHR mghi = {VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR, nullptr, memory_export.handle(), - handle_type}; - HANDLE handle; - ASSERT_VK_SUCCESS(vkGetMemoryWin32HandleKHR(m_device->device(), &mghi, &handle)); - - VkImportMemoryWin32HandleInfoKHR import_info = {VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR, nullptr, handle_type, - handle}; -#else - // Export memory to fd - auto vkGetMemoryFdKHR = (PFN_vkGetMemoryFdKHR)vkGetInstanceProcAddr(instance(), "vkGetMemoryFdKHR"); - ASSERT_TRUE(vkGetMemoryFdKHR != nullptr); - VkMemoryGetFdInfoKHR mgfi = {VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, nullptr, memory_export.handle(), handle_type}; - int fd; - ASSERT_VK_SUCCESS(vkGetMemoryFdKHR(m_device->device(), &mgfi, &fd)); - - VkImportMemoryFdInfoKHR import_info = {VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, nullptr, handle_type, fd}; -#endif - - // Import memory - alloc_info = vk_testing::DeviceMemory::get_resource_alloc_info(*m_device, buffer_import.memory_requirements(), mem_flags); - alloc_info.pNext = &import_info; - vk_testing::DeviceMemory memory_import; - memory_import.init(*m_device, alloc_info); - - // Bind imported memory - buffer_import.bind_memory(memory_import, 0); - - // Create test buffers and fill input buffer - VkMemoryPropertyFlags mem_prop = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - VkBufferObj buffer_input; - buffer_input.init_as_src_and_dst(*m_device, buffer_size, mem_prop); - auto input_mem = (uint8_t *)buffer_input.memory().map(); - for (uint32_t i = 0; i < buffer_size; i++) { - input_mem[i] = (i & 0xFF); - } - buffer_input.memory().unmap(); - VkBufferObj buffer_output; - buffer_output.init_as_src_and_dst(*m_device, buffer_size, mem_prop); - - // Copy from input buffer to output buffer through the exported/imported memory - m_commandBuffer->begin(); - VkBufferCopy copy_info = {0, 0, buffer_size}; - vkCmdCopyBuffer(m_commandBuffer->handle(), buffer_input.handle(), buffer_export.handle(), 1, ©_info); - // Insert memory barrier to guarantee copy order - VkMemoryBarrier mem_barrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER, nullptr, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_TRANSFER_READ_BIT}; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, - &mem_barrier, 0, nullptr, 0, nullptr); - vkCmdCopyBuffer(m_commandBuffer->handle(), buffer_import.handle(), buffer_output.handle(), 1, ©_info); - m_commandBuffer->end(); - m_commandBuffer->QueueCommandBuffer(); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkLayerTest, AMDMixedAttachmentSamplesValidateGraphicsPipeline) { - TEST_DESCRIPTION("Verify an error message for an incorrect graphics pipeline rasterization sample count."); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME); - } else { - printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - VkRenderpassObj render_pass(m_device); - - const VkPipelineLayoutObj pipeline_layout(m_device); - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - // Set a mismatched sample count - - VkPipelineMultisampleStateCreateInfo ms_state_ci = {}; - ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT; - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.SetMSAA(&ms_state_ci); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkGraphicsPipelineCreateInfo-subpass-01505"); - - pipe.CreateVKPipeline(pipeline_layout.handle(), render_pass.handle()); - - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkPositiveLayerTest, ParameterLayerFeatures2Capture) { - TEST_DESCRIPTION("Ensure parameter_validation_layer correctly captures physical device features"); - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Did not find VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME; skipped.\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = - (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR"); - ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr); - - VkResult err; - m_errorMonitor->ExpectSuccess(); - - VkPhysicalDeviceFeatures2KHR features2; - features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; - features2.pNext = nullptr; - - vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2); - - // We're not creating a valid m_device, but the phy wrapper is useful - vk_testing::PhysicalDevice physical_device(gpu()); - vk_testing::QueueCreateInfoArray queue_info(physical_device.queue_properties()); - // Only request creation with queuefamilies that have at least one queue - std::vector<VkDeviceQueueCreateInfo> create_queue_infos; - auto qci = queue_info.data(); - for (uint32_t i = 0; i < queue_info.size(); ++i) { - if (qci[i].queueCount) { - create_queue_infos.push_back(qci[i]); - } - } - - VkDeviceCreateInfo dev_info = {}; - dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - dev_info.pNext = &features2; - dev_info.flags = 0; - dev_info.queueCreateInfoCount = create_queue_infos.size(); - dev_info.pQueueCreateInfos = create_queue_infos.data(); - dev_info.enabledLayerCount = 0; - dev_info.ppEnabledLayerNames = nullptr; - dev_info.enabledExtensionCount = 0; - dev_info.ppEnabledExtensionNames = nullptr; - dev_info.pEnabledFeatures = nullptr; - - VkDevice device; - err = vkCreateDevice(gpu(), &dev_info, nullptr, &device); - ASSERT_VK_SUCCESS(err); - - if (features2.features.samplerAnisotropy) { - // Test that the parameter layer is caching the features correctly using CreateSampler - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - // If the features were not captured correctly, this should cause an error - sampler_ci.anisotropyEnable = VK_TRUE; - sampler_ci.maxAnisotropy = physical_device.properties().limits.maxSamplerAnisotropy; - - VkSampler sampler = VK_NULL_HANDLE; - err = vkCreateSampler(device, &sampler_ci, nullptr, &sampler); - ASSERT_VK_SUCCESS(err); - vkDestroySampler(device, sampler, nullptr); - } else { - printf("%s Feature samplerAnisotropy not enabled; parameter_layer check skipped.\n", kSkipPrefix); - } - - // Verify the core validation layer has captured the physical device features by creating a a query pool. - if (features2.features.pipelineStatisticsQuery) { - VkQueryPool query_pool; - VkQueryPoolCreateInfo qpci{}; - qpci.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; - qpci.queryType = VK_QUERY_TYPE_PIPELINE_STATISTICS; - qpci.queryCount = 1; - err = vkCreateQueryPool(device, &qpci, nullptr, &query_pool); - ASSERT_VK_SUCCESS(err); - - vkDestroyQueryPool(device, query_pool, nullptr); - } else { - printf("%s Feature pipelineStatisticsQuery not enabled; core_validation_layer check skipped.\n", kSkipPrefix); - } - - vkDestroyDevice(device, nullptr); - - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, GetMemoryRequirements2) { - TEST_DESCRIPTION( - "Get memory requirements with VK_KHR_get_memory_requirements2 instead of core entry points and verify layers do not emit " - "errors when objects are bound and used"); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - // Check for VK_KHR_get_memory_requirementes2 extensions - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - } else { - printf("%s %s not supported, skipping test\n", kSkipPrefix, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - - m_errorMonitor->ExpectSuccess(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT); - - // Create a test buffer - VkBufferObj buffer; - buffer.init_no_mem(*m_device, - VkBufferObj::create_info(1024, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)); - - // Use extension to get buffer memory requirements - auto vkGetBufferMemoryRequirements2KHR = reinterpret_cast<PFN_vkGetBufferMemoryRequirements2KHR>( - vkGetDeviceProcAddr(m_device->device(), "vkGetBufferMemoryRequirements2KHR")); - ASSERT_TRUE(vkGetBufferMemoryRequirements2KHR != nullptr); - VkBufferMemoryRequirementsInfo2KHR buffer_info = {VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR, nullptr, - buffer.handle()}; - VkMemoryRequirements2KHR buffer_reqs = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR}; - vkGetBufferMemoryRequirements2KHR(m_device->device(), &buffer_info, &buffer_reqs); - - // Allocate and bind buffer memory - vk_testing::DeviceMemory buffer_memory; - buffer_memory.init(*m_device, vk_testing::DeviceMemory::get_resource_alloc_info(*m_device, buffer_reqs.memoryRequirements, 0)); - vkBindBufferMemory(m_device->device(), buffer.handle(), buffer_memory.handle(), 0); - - // Create a test image - auto image_ci = vk_testing::Image::create_info(); - image_ci.imageType = VK_IMAGE_TYPE_2D; - image_ci.extent.width = 32; - image_ci.extent.height = 32; - image_ci.format = VK_FORMAT_R8G8B8A8_UNORM; - image_ci.tiling = VK_IMAGE_TILING_OPTIMAL; - image_ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; - vk_testing::Image image; - image.init_no_mem(*m_device, image_ci); - - // Use extension to get image memory requirements - auto vkGetImageMemoryRequirements2KHR = reinterpret_cast<PFN_vkGetImageMemoryRequirements2KHR>( - vkGetDeviceProcAddr(m_device->device(), "vkGetImageMemoryRequirements2KHR")); - ASSERT_TRUE(vkGetImageMemoryRequirements2KHR != nullptr); - VkImageMemoryRequirementsInfo2KHR image_info = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR, nullptr, - image.handle()}; - VkMemoryRequirements2KHR image_reqs = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR}; - vkGetImageMemoryRequirements2KHR(m_device->device(), &image_info, &image_reqs); - - // Allocate and bind image memory - vk_testing::DeviceMemory image_memory; - image_memory.init(*m_device, vk_testing::DeviceMemory::get_resource_alloc_info(*m_device, image_reqs.memoryRequirements, 0)); - vkBindImageMemory(m_device->device(), image.handle(), image_memory.handle(), 0); - - // Now execute arbitrary commands that use the test buffer and image - m_commandBuffer->begin(); - - // Fill buffer with 0 - vkCmdFillBuffer(m_commandBuffer->handle(), buffer.handle(), 0, VK_WHOLE_SIZE, 0); - - // Transition and clear image - const auto subresource_range = image.subresource_range(VK_IMAGE_ASPECT_COLOR_BIT); - const auto barrier = image.image_memory_barrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_GENERAL, subresource_range); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 1, &barrier); - const VkClearColorValue color = {}; - vkCmdClearColorImage(m_commandBuffer->handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, &color, 1, &subresource_range); - - // Submit and verify no validation errors - m_commandBuffer->end(); - m_commandBuffer->QueueCommandBuffer(); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, BindMemory2) { - TEST_DESCRIPTION( - "Bind memory with VK_KHR_bind_memory2 instead of core entry points and verify layers do not emit errors when objects are " - "used"); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - // Check for VK_KHR_get_memory_requirementes2 extensions - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - } else { - printf("%s %s not supported, skipping test\n", kSkipPrefix, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - - m_errorMonitor->ExpectSuccess(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT); - - // Create a test buffer - VkBufferObj buffer; - buffer.init_no_mem(*m_device, VkBufferObj::create_info(1024, VK_BUFFER_USAGE_TRANSFER_DST_BIT)); - - // Allocate buffer memory - vk_testing::DeviceMemory buffer_memory; - buffer_memory.init(*m_device, vk_testing::DeviceMemory::get_resource_alloc_info(*m_device, buffer.memory_requirements(), 0)); - - // Bind buffer memory with extension - auto vkBindBufferMemory2KHR = - reinterpret_cast<PFN_vkBindBufferMemory2KHR>(vkGetDeviceProcAddr(m_device->device(), "vkBindBufferMemory2KHR")); - ASSERT_TRUE(vkBindBufferMemory2KHR != nullptr); - VkBindBufferMemoryInfoKHR buffer_bind_info = {VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR, nullptr, buffer.handle(), - buffer_memory.handle(), 0}; - vkBindBufferMemory2KHR(m_device->device(), 1, &buffer_bind_info); - - // Create a test image - auto image_ci = vk_testing::Image::create_info(); - image_ci.imageType = VK_IMAGE_TYPE_2D; - image_ci.extent.width = 32; - image_ci.extent.height = 32; - image_ci.format = VK_FORMAT_R8G8B8A8_UNORM; - image_ci.tiling = VK_IMAGE_TILING_OPTIMAL; - image_ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; - vk_testing::Image image; - image.init_no_mem(*m_device, image_ci); - - // Allocate image memory - vk_testing::DeviceMemory image_memory; - image_memory.init(*m_device, vk_testing::DeviceMemory::get_resource_alloc_info(*m_device, image.memory_requirements(), 0)); - - // Bind image memory with extension - auto vkBindImageMemory2KHR = - reinterpret_cast<PFN_vkBindImageMemory2KHR>(vkGetDeviceProcAddr(m_device->device(), "vkBindImageMemory2KHR")); - ASSERT_TRUE(vkBindImageMemory2KHR != nullptr); - VkBindImageMemoryInfoKHR image_bind_info = {VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR, nullptr, image.handle(), - image_memory.handle(), 0}; - vkBindImageMemory2KHR(m_device->device(), 1, &image_bind_info); - - // Now execute arbitrary commands that use the test buffer and image - m_commandBuffer->begin(); - - // Fill buffer with 0 - vkCmdFillBuffer(m_commandBuffer->handle(), buffer.handle(), 0, VK_WHOLE_SIZE, 0); - - // Transition and clear image - const auto subresource_range = image.subresource_range(VK_IMAGE_ASPECT_COLOR_BIT); - const auto barrier = image.image_memory_barrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_GENERAL, subresource_range); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 0, nullptr, 1, &barrier); - const VkClearColorValue color = {}; - vkCmdClearColorImage(m_commandBuffer->handle(), image.handle(), VK_IMAGE_LAYOUT_GENERAL, &color, 1, &subresource_range); - - // Submit and verify no validation errors - m_commandBuffer->end(); - m_commandBuffer->QueueCommandBuffer(); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, CreatePipeineWithTessellationDomainOrigin) { - TEST_DESCRIPTION( - "Test CreatePipeline when VkPipelineTessellationStateCreateInfo.pNext include " - "VkPipelineTessellationDomainOriginStateCreateInfo"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - if (!m_device->phy().features().tessellationShader) { - printf("%s Device does not support tessellation shaders; skipped.\n", kSkipPrefix); - return; - } - - char const *vsSource = - "#version 450\n" - "void main(){}\n"; - char const *tcsSource = - "#version 450\n" - "layout(location=0) out int x[];\n" - "layout(vertices=3) out;\n" - "void main(){\n" - " gl_TessLevelOuter[0] = gl_TessLevelOuter[1] = gl_TessLevelOuter[2] = 1;\n" - " gl_TessLevelInner[0] = 1;\n" - " x[gl_InvocationID] = gl_InvocationID;\n" - "}\n"; - char const *tesSource = - "#version 450\n" - "layout(triangles, equal_spacing, cw) in;\n" - "layout(location=0) in int x[];\n" - "void main(){\n" - " gl_Position.xyz = gl_TessCoord;\n" - " gl_Position.w = x[0] + x[1] + x[2];\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "layout(location=0) out vec4 color;\n" - "void main(){\n" - " color = vec4(1);\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj tcs(m_device, tcsSource, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, this); - VkShaderObj tes(m_device, tesSource, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineInputAssemblyStateCreateInfo iasci{VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, nullptr, 0, - VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, VK_FALSE}; - - VkPipelineTessellationDomainOriginStateCreateInfo tessellationDomainOriginStateInfo = { - VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO, VK_NULL_HANDLE, - VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT}; - - VkPipelineTessellationStateCreateInfo tsci{VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, - &tessellationDomainOriginStateInfo, 0, 3}; - - VkPipelineObj pipe(m_device); - pipe.SetInputAssembly(&iasci); - pipe.SetTessellation(&tsci); - pipe.AddDefaultColorAttachment(); - pipe.AddShader(&vs); - pipe.AddShader(&tcs); - pipe.AddShader(&tes); - pipe.AddShader(&fs); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - m_errorMonitor->ExpectSuccess(); - pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, MultiplaneImageCopyBufferToImage) { - TEST_DESCRIPTION("Positive test of multiplane copy buffer to image"); - // Enable KHR multiplane req'd extensions - bool mp_extensions = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION); - if (mp_extensions) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - SetTargetApiVersion(VK_API_VERSION_1_1); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - if (mp_extensions) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - } else { - printf("%s test requires KHR multiplane extensions, not available. Skipping.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkImageCreateInfo ci = {}; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_2D; - ci.format = VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR; // All planes of equal extent - ci.tiling = VK_IMAGE_TILING_OPTIMAL; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - ci.extent = {16, 16, 1}; - ci.mipLevels = 1; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkFormatFeatureFlags features = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT; - bool supported = ImageFormatAndFeaturesSupported(instance(), gpu(), ci, features); - if (!supported) { - printf("%s Multiplane image format not supported. Skipping test.\n", kSkipPrefix); - return; // Assume there's low ROI on searching for different mp formats - } - - VkImageObj image(m_device); - image.init(&ci); - - m_commandBuffer->reset(); - m_errorMonitor->ExpectSuccess(); - m_commandBuffer->begin(); - image.ImageMemoryBarrier(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - std::array<VkImageAspectFlagBits, 3> aspects = {VK_IMAGE_ASPECT_PLANE_0_BIT, VK_IMAGE_ASPECT_PLANE_1_BIT, - VK_IMAGE_ASPECT_PLANE_2_BIT}; - std::array<VkBufferObj, 3> buffers; - VkMemoryPropertyFlags reqs = 0; - - VkBufferImageCopy copy = {}; - copy.imageSubresource.layerCount = 1; - copy.imageExtent.depth = 1; - copy.imageExtent.height = 16; - copy.imageExtent.width = 16; - - for (size_t i = 0; i < aspects.size(); ++i) { - buffers[i].init_as_src(*m_device, (VkDeviceSize)16 * 16 * 1, reqs); - copy.imageSubresource.aspectMask = aspects[i]; - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffers[i].handle(), image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, ©); - } - m_commandBuffer->end(); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkPositiveLayerTest, MultiplaneImageTests) { - TEST_DESCRIPTION("Positive test of multiplane image operations"); - - // Enable KHR multiplane req'd extensions - bool mp_extensions = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION); - if (mp_extensions) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - SetTargetApiVersion(VK_API_VERSION_1_1); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - if (mp_extensions) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - } else { - printf("%s test requires KHR multiplane extensions, not available. Skipping.\n", kSkipPrefix); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkImageCreateInfo ci = {}; - ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ci.pNext = NULL; - ci.flags = 0; - ci.imageType = VK_IMAGE_TYPE_2D; - ci.format = VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR; // All planes of equal extent - ci.tiling = VK_IMAGE_TILING_OPTIMAL; - ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - ci.extent = {128, 128, 1}; - ci.mipLevels = 1; - ci.arrayLayers = 1; - ci.samples = VK_SAMPLE_COUNT_1_BIT; - ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - // Verify format - VkFormatFeatureFlags features = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT; - bool supported = ImageFormatAndFeaturesSupported(instance(), gpu(), ci, features); - if (!supported) { - printf("%s Multiplane image format not supported. Skipping test.\n", kSkipPrefix); - return; // Assume there's low ROI on searching for different mp formats - } - - VkImage image; - ASSERT_VK_SUCCESS(vkCreateImage(device(), &ci, NULL, &image)); - - // Allocate & bind memory - VkPhysicalDeviceMemoryProperties phys_mem_props; - vkGetPhysicalDeviceMemoryProperties(gpu(), &phys_mem_props); - VkMemoryRequirements mem_reqs; - vkGetImageMemoryRequirements(device(), image, &mem_reqs); - VkDeviceMemory mem_obj = VK_NULL_HANDLE; - VkMemoryPropertyFlagBits mem_props = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - for (uint32_t type = 0; type < phys_mem_props.memoryTypeCount; type++) { - if ((mem_reqs.memoryTypeBits & (1 << type)) && - ((phys_mem_props.memoryTypes[type].propertyFlags & mem_props) == mem_props)) { - VkMemoryAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.allocationSize = mem_reqs.size; - alloc_info.memoryTypeIndex = type; - ASSERT_VK_SUCCESS(vkAllocateMemory(device(), &alloc_info, NULL, &mem_obj)); - break; - } - } - - if (VK_NULL_HANDLE == mem_obj) { - printf("%s Unable to allocate image memory. Skipping test.\n", kSkipPrefix); - vkDestroyImage(device(), image, NULL); - return; - } - ASSERT_VK_SUCCESS(vkBindImageMemory(device(), image, mem_obj, 0)); - - // Copy plane 0 to plane 2 - VkImageCopy copyRegion = {}; - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT_KHR; - copyRegion.srcSubresource.mipLevel = 0; - copyRegion.srcSubresource.baseArrayLayer = 0; - copyRegion.srcSubresource.layerCount = 1; - copyRegion.srcOffset = {0, 0, 0}; - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR; - copyRegion.dstSubresource.mipLevel = 0; - copyRegion.dstSubresource.baseArrayLayer = 0; - copyRegion.dstSubresource.layerCount = 1; - copyRegion.dstOffset = {0, 0, 0}; - copyRegion.extent.width = 128; - copyRegion.extent.height = 128; - copyRegion.extent.depth = 1; - - m_errorMonitor->ExpectSuccess(); - m_commandBuffer->begin(); - m_commandBuffer->CopyImage(image, VK_IMAGE_LAYOUT_GENERAL, image, VK_IMAGE_LAYOUT_GENERAL, 1, ©Region); - m_commandBuffer->end(); - m_errorMonitor->VerifyNotFound(); - - vkFreeMemory(device(), mem_obj, NULL); - vkDestroyImage(device(), image, NULL); - - // Repeat bind test on a DISJOINT multi-planar image, with per-plane memory objects, using API2 variants - // - features |= VK_FORMAT_FEATURE_DISJOINT_BIT; - ci.flags = VK_IMAGE_CREATE_DISJOINT_BIT; - if (ImageFormatAndFeaturesSupported(instance(), gpu(), ci, features)) { - ASSERT_VK_SUCCESS(vkCreateImage(device(), &ci, NULL, &image)); - - // Allocate & bind memory - VkPhysicalDeviceMemoryProperties2 phys_mem_props2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2}; - vkGetPhysicalDeviceMemoryProperties2(gpu(), &phys_mem_props2); - VkImagePlaneMemoryRequirementsInfo image_plane_req = {VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO}; - VkImageMemoryRequirementsInfo2 mem_req_info2 = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2}; - mem_req_info2.pNext = &image_plane_req; - mem_req_info2.image = image; - VkMemoryRequirements2 mem_reqs2 = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2}; - - VkDeviceMemory p0_mem, p1_mem, p2_mem; - mem_props = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - VkMemoryAllocateInfo alloc_info = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO}; - - // Plane 0 - image_plane_req.planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT; - vkGetImageMemoryRequirements2(device(), &mem_req_info2, &mem_reqs2); - uint32_t mem_type = 0; - for (mem_type = 0; mem_type < phys_mem_props2.memoryProperties.memoryTypeCount; mem_type++) { - if ((mem_reqs2.memoryRequirements.memoryTypeBits & (1 << mem_type)) && - ((phys_mem_props2.memoryProperties.memoryTypes[mem_type].propertyFlags & mem_props) == mem_props)) { - alloc_info.memoryTypeIndex = mem_type; - break; - } - } - alloc_info.allocationSize = mem_reqs2.memoryRequirements.size; - ASSERT_VK_SUCCESS(vkAllocateMemory(device(), &alloc_info, NULL, &p0_mem)); - - // Plane 1 & 2 use same memory type - image_plane_req.planeAspect = VK_IMAGE_ASPECT_PLANE_1_BIT; - vkGetImageMemoryRequirements2(device(), &mem_req_info2, &mem_reqs2); - alloc_info.allocationSize = mem_reqs2.memoryRequirements.size; - ASSERT_VK_SUCCESS(vkAllocateMemory(device(), &alloc_info, NULL, &p1_mem)); - - image_plane_req.planeAspect = VK_IMAGE_ASPECT_PLANE_2_BIT; - vkGetImageMemoryRequirements2(device(), &mem_req_info2, &mem_reqs2); - alloc_info.allocationSize = mem_reqs2.memoryRequirements.size; - ASSERT_VK_SUCCESS(vkAllocateMemory(device(), &alloc_info, NULL, &p2_mem)); - - // Set up 3-plane binding - VkBindImageMemoryInfo bind_info[3]; - for (int plane = 0; plane < 3; plane++) { - bind_info[plane].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; - bind_info[plane].pNext = nullptr; - bind_info[plane].image = image; - bind_info[plane].memoryOffset = 0; - } - bind_info[0].memory = p0_mem; - bind_info[1].memory = p1_mem; - bind_info[2].memory = p2_mem; - - m_errorMonitor->ExpectSuccess(); - vkBindImageMemory2(device(), 3, bind_info); - m_errorMonitor->VerifyNotFound(); - - vkFreeMemory(device(), p0_mem, NULL); - vkFreeMemory(device(), p1_mem, NULL); - vkFreeMemory(device(), p2_mem, NULL); - vkDestroyImage(device(), image, NULL); - } - - // Test that changing the layout of ASPECT_COLOR also changes the layout of the individual planes - VkBufferObj buffer; - VkMemoryPropertyFlags reqs = 0; - buffer.init_as_src(*m_device, (VkDeviceSize)128 * 128 * 3, reqs); - VkImageObj mpimage(m_device); - mpimage.Init(256, 256, 1, VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - VK_IMAGE_TILING_OPTIMAL, 0); - VkBufferImageCopy copy_region = {}; - copy_region.bufferRowLength = 128; - copy_region.bufferImageHeight = 128; - copy_region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT_KHR; - copy_region.imageSubresource.layerCount = 1; - copy_region.imageExtent.height = 64; - copy_region.imageExtent.width = 64; - copy_region.imageExtent.depth = 1; - - vkResetCommandBuffer(m_commandBuffer->handle(), 0); - m_commandBuffer->begin(); - mpimage.ImageMemoryBarrier(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer.handle(), mpimage.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, - ©_region); - m_commandBuffer->end(); - m_commandBuffer->QueueCommandBuffer(false); - m_errorMonitor->VerifyNotFound(); - - // Test to verify that views of multiplanar images have layouts tracked correctly - // by changing the image's layout then using a view of that image - VkImageView view; - VkImageViewCreateInfo ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.image = mpimage.handle(); - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.format = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR; - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - ivci.subresourceRange.levelCount = 1; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - vkCreateImageView(m_device->device(), &ivci, nullptr, &view); - - OneOffDescriptorSet ds(m_device, { - {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}, - }); - - VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(); - VkSampler sampler; - - VkResult err; - err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler); - ASSERT_VK_SUCCESS(err); - - const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_}); - - VkDescriptorImageInfo image_info{}; - image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - image_info.imageView = view; - image_info.sampler = sampler; - - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = ds.set_; - descriptor_write.dstBinding = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_write.pImageInfo = &image_info; - - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - - char const *vsSource = - "#version 450\n" - "\n" - "void main(){\n" - " gl_Position = vec4(1);\n" - "}\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(set=0, binding=0) uniform sampler2D s;\n" - "layout(location=0) out vec4 x;\n" - "void main(){\n" - " x = texture(s, vec2(1));\n" - "}\n"; - - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass()); - - m_errorMonitor->ExpectSuccess(); - m_commandBuffer->begin(); - VkImageMemoryBarrier img_barrier = {}; - img_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - img_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - img_barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - img_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - img_barrier.image = mpimage.handle(); - img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - img_barrier.subresourceRange.baseArrayLayer = 0; - img_barrier.subresourceRange.baseMipLevel = 0; - img_barrier.subresourceRange.layerCount = 1; - img_barrier.subresourceRange.levelCount = 1; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, &ds.set_, 0, - nullptr); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - - m_commandBuffer->Draw(1, 0, 0, 0); - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &m_commandBuffer->handle(); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyNotFound(); - - vkQueueWaitIdle(m_device->m_queue); - vkDestroyImageView(m_device->device(), view, NULL); - vkDestroySampler(m_device->device(), sampler, nullptr); -} - -TEST_F(VkPositiveLayerTest, ApiVersionZero) { - TEST_DESCRIPTION("Check that apiVersion = 0 is valid."); - m_errorMonitor->ExpectSuccess(); - app_info.apiVersion = 0U; - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - m_errorMonitor->VerifyNotFound(); -} - -TEST_F(VkLayerTest, DrawIndirect) { - TEST_DESCRIPTION("Test covered valid usage for vkCmdDrawIndirect"); - - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkMemoryRequirements memory_requirements; - VkMemoryAllocateInfo memory_allocate_info = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO}; - - char const *vsSource = - "#version 450\n" - "\n" - "void main() { gl_Position = vec4(0); }\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main() {\n" - " color = vec4(1, 0, 0, 1);\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - - VkDescriptorSetObj descriptor_set(m_device); - descriptor_set.AppendDummy(); - descriptor_set.CreateVKDescriptorSet(m_commandBuffer); - - VkResult err = pipe.CreateVKPipeline(descriptor_set.GetPipelineLayout(), renderPass()); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - m_commandBuffer->BindDescriptorSet(descriptor_set); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - - VkBufferCreateInfo buffer_create_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; - buffer_create_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - buffer_create_info.size = sizeof(VkDrawIndirectCommand); - VkBuffer draw_buffer; - vkCreateBuffer(m_device->device(), &buffer_create_info, nullptr, &draw_buffer); - - vkGetBufferMemoryRequirements(m_device->device(), draw_buffer, &memory_requirements); - memory_allocate_info.allocationSize = memory_requirements.size; - m_device->phy().set_memory_type(memory_requirements.memoryTypeBits, &memory_allocate_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - VkDeviceMemory draw_buffer_memory; - vkAllocateMemory(m_device->device(), &memory_allocate_info, NULL, &draw_buffer_memory); - vkBindBufferMemory(m_device->device(), draw_buffer, draw_buffer_memory, 0); - - // VUID-vkCmdDrawIndirect-buffer-02709 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndirect-buffer-02709"); - vkCmdDrawIndirect(m_commandBuffer->handle(), draw_buffer, 0, 1, sizeof(VkDrawIndirectCommand)); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - - vkDestroyBuffer(m_device->device(), draw_buffer, 0); - vkFreeMemory(m_device->device(), draw_buffer_memory, 0); -} - -TEST_F(VkLayerTest, DrawIndirectCountKHR) { - TEST_DESCRIPTION("Test covered valid usage for vkCmdDrawIndirectCountKHR"); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME); - } else { - printf(" VK_KHR_draw_indirect_count Extension not supported, skipping test\n"); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkMemoryRequirements memory_requirements; - VkMemoryAllocateInfo memory_allocate_info = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO}; - - auto vkCmdDrawIndirectCountKHR = - (PFN_vkCmdDrawIndirectCountKHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdDrawIndirectCountKHR"); - - char const *vsSource = - "#version 450\n" - "\n" - "void main() { gl_Position = vec4(0); }\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main() {\n" - " color = vec4(1, 0, 0, 1);\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - - VkDescriptorSetObj descriptor_set(m_device); - descriptor_set.AppendDummy(); - descriptor_set.CreateVKDescriptorSet(m_commandBuffer); - - VkResult err = pipe.CreateVKPipeline(descriptor_set.GetPipelineLayout(), renderPass()); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - m_commandBuffer->BindDescriptorSet(descriptor_set); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - - VkBufferCreateInfo buffer_create_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; - buffer_create_info.size = sizeof(VkDrawIndirectCommand); - buffer_create_info.usage = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; - VkBuffer draw_buffer; - vkCreateBuffer(m_device->device(), &buffer_create_info, nullptr, &draw_buffer); - - VkBufferCreateInfo count_buffer_create_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; - count_buffer_create_info.size = sizeof(uint32_t); - count_buffer_create_info.usage = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; - VkBuffer count_buffer; - vkCreateBuffer(m_device->device(), &count_buffer_create_info, nullptr, &count_buffer); - vkGetBufferMemoryRequirements(m_device->device(), count_buffer, &memory_requirements); - memory_allocate_info.allocationSize = memory_requirements.size; - m_device->phy().set_memory_type(memory_requirements.memoryTypeBits, &memory_allocate_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - VkDeviceMemory count_buffer_memory; - vkAllocateMemory(m_device->device(), &memory_allocate_info, NULL, &count_buffer_memory); - vkBindBufferMemory(m_device->device(), count_buffer, count_buffer_memory, 0); - - // VUID-vkCmdDrawIndirectCountKHR-buffer-02708 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndirectCountKHR-buffer-02708"); - vkCmdDrawIndirectCountKHR(m_commandBuffer->handle(), draw_buffer, 0, count_buffer, 0, 1, sizeof(VkDrawIndirectCommand)); - m_errorMonitor->VerifyFound(); - - vkGetBufferMemoryRequirements(m_device->device(), draw_buffer, &memory_requirements); - memory_allocate_info.allocationSize = memory_requirements.size; - m_device->phy().set_memory_type(memory_requirements.memoryTypeBits, &memory_allocate_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - VkDeviceMemory draw_buffer_memory; - vkAllocateMemory(m_device->device(), &memory_allocate_info, NULL, &draw_buffer_memory); - vkBindBufferMemory(m_device->device(), draw_buffer, draw_buffer_memory, 0); - - VkBuffer count_buffer_unbound; - vkCreateBuffer(m_device->device(), &count_buffer_create_info, nullptr, &count_buffer_unbound); - - // VUID-vkCmdDrawIndirectCountKHR-countBuffer-02714 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndirectCountKHR-countBuffer-02714"); - vkCmdDrawIndirectCountKHR(m_commandBuffer->handle(), draw_buffer, 0, count_buffer_unbound, 0, 1, sizeof(VkDrawIndirectCommand)); - m_errorMonitor->VerifyFound(); - - // VUID-vkCmdDrawIndirectCountKHR-offset-02710 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndirectCountKHR-offset-02710"); - vkCmdDrawIndirectCountKHR(m_commandBuffer->handle(), draw_buffer, 1, count_buffer, 0, 1, sizeof(VkDrawIndirectCommand)); - m_errorMonitor->VerifyFound(); - - // VUID-vkCmdDrawIndirectCountKHR-countBufferOffset-02716 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndirectCountKHR-countBufferOffset-02716"); - vkCmdDrawIndirectCountKHR(m_commandBuffer->handle(), draw_buffer, 0, count_buffer, 1, 1, sizeof(VkDrawIndirectCommand)); - m_errorMonitor->VerifyFound(); - - // VUID-vkCmdDrawIndirectCountKHR-stride-03110 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndirectCountKHR-stride-03110"); - vkCmdDrawIndirectCountKHR(m_commandBuffer->handle(), draw_buffer, 0, count_buffer, 0, 1, 1); - m_errorMonitor->VerifyFound(); - - // TODO: These covered VUIDs aren't tested. There is also no test coverage for the core Vulkan 1.0 vkCmdDraw* equivalent of - // these: - // VUID-vkCmdDrawIndirectCountKHR-renderPass-02684 - // VUID-vkCmdDrawIndirectCountKHR-subpass-02685 - // VUID-vkCmdDrawIndirectCountKHR-commandBuffer-02701 - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - - vkDestroyBuffer(m_device->device(), draw_buffer, 0); - vkDestroyBuffer(m_device->device(), count_buffer, 0); - vkDestroyBuffer(m_device->device(), count_buffer_unbound, 0); - - vkFreeMemory(m_device->device(), draw_buffer_memory, 0); - vkFreeMemory(m_device->device(), count_buffer_memory, 0); -} - -TEST_F(VkLayerTest, DrawIndexedIndirectCountKHR) { - TEST_DESCRIPTION("Test covered valid usage for vkCmdDrawIndexedIndirectCountKHR"); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME); - } else { - printf(" VK_KHR_draw_indirect_count Extension not supported, skipping test\n"); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkMemoryRequirements memory_requirements; - VkMemoryAllocateInfo memory_allocate_info = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO}; - - auto vkCmdDrawIndexedIndirectCountKHR = - (PFN_vkCmdDrawIndexedIndirectCountKHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdDrawIndexedIndirectCountKHR"); - - char const *vsSource = - "#version 450\n" - "\n" - "void main() { gl_Position = vec4(0); }\n"; - char const *fsSource = - "#version 450\n" - "\n" - "layout(location=0) out vec4 color;\n" - "void main() {\n" - " color = vec4(1, 0, 0, 1);\n" - "}\n"; - VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - VkPipelineObj pipe(m_device); - pipe.AddShader(&vs); - pipe.AddShader(&fs); - pipe.AddDefaultColorAttachment(); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - VkResult err = pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass()); - ASSERT_VK_SUCCESS(err); - - m_commandBuffer->begin(); - m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); - - vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); - m_commandBuffer->BindDescriptorSet(descriptorSet); - - VkViewport viewport = {0, 0, 16, 16, 0, 1}; - vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); - VkRect2D scissor = {{0, 0}, {16, 16}}; - vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); - - VkBufferCreateInfo buffer_create_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; - buffer_create_info.size = sizeof(VkDrawIndexedIndirectCommand); - buffer_create_info.usage = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; - VkBuffer draw_buffer; - vkCreateBuffer(m_device->device(), &buffer_create_info, nullptr, &draw_buffer); - vkGetBufferMemoryRequirements(m_device->device(), draw_buffer, &memory_requirements); - memory_allocate_info.allocationSize = memory_requirements.size; - m_device->phy().set_memory_type(memory_requirements.memoryTypeBits, &memory_allocate_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - VkDeviceMemory draw_buffer_memory; - vkAllocateMemory(m_device->device(), &memory_allocate_info, NULL, &draw_buffer_memory); - vkBindBufferMemory(m_device->device(), draw_buffer, draw_buffer_memory, 0); - - VkBufferCreateInfo count_buffer_create_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; - count_buffer_create_info.size = sizeof(uint32_t); - count_buffer_create_info.usage = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; - VkBuffer count_buffer; - vkCreateBuffer(m_device->device(), &count_buffer_create_info, nullptr, &count_buffer); - vkGetBufferMemoryRequirements(m_device->device(), count_buffer, &memory_requirements); - memory_allocate_info.allocationSize = memory_requirements.size; - m_device->phy().set_memory_type(memory_requirements.memoryTypeBits, &memory_allocate_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - VkDeviceMemory count_buffer_memory; - vkAllocateMemory(m_device->device(), &memory_allocate_info, NULL, &count_buffer_memory); - vkBindBufferMemory(m_device->device(), count_buffer, count_buffer_memory, 0); - - VkBufferCreateInfo index_buffer_create_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; - index_buffer_create_info.size = sizeof(uint32_t); - index_buffer_create_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; - VkBuffer index_buffer; - vkCreateBuffer(m_device->device(), &index_buffer_create_info, nullptr, &index_buffer); - vkGetBufferMemoryRequirements(m_device->device(), index_buffer, &memory_requirements); - memory_allocate_info.allocationSize = memory_requirements.size; - m_device->phy().set_memory_type(memory_requirements.memoryTypeBits, &memory_allocate_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - VkDeviceMemory index_buffer_memory; - vkAllocateMemory(m_device->device(), &memory_allocate_info, NULL, &index_buffer_memory); - vkBindBufferMemory(m_device->device(), index_buffer, index_buffer_memory, 0); - - // VUID-vkCmdDrawIndexedIndirectCountKHR-commandBuffer-02701 (partial - only tests whether the index buffer is bound) - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdDrawIndexedIndirectCountKHR-commandBuffer-02701"); - vkCmdDrawIndexedIndirectCountKHR(m_commandBuffer->handle(), draw_buffer, 0, count_buffer, 0, 1, - sizeof(VkDrawIndexedIndirectCommand)); - m_errorMonitor->VerifyFound(); - - vkCmdBindIndexBuffer(m_commandBuffer->handle(), index_buffer, 0, VK_INDEX_TYPE_UINT32); - - VkBuffer draw_buffer_unbound; - vkCreateBuffer(m_device->device(), &count_buffer_create_info, nullptr, &draw_buffer_unbound); - - // VUID-vkCmdDrawIndexedIndirectCountKHR-buffer-02708 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndexedIndirectCountKHR-buffer-02708"); - vkCmdDrawIndexedIndirectCountKHR(m_commandBuffer->handle(), draw_buffer_unbound, 0, count_buffer, 0, 1, - sizeof(VkDrawIndexedIndirectCommand)); - m_errorMonitor->VerifyFound(); - - VkBuffer count_buffer_unbound; - vkCreateBuffer(m_device->device(), &count_buffer_create_info, nullptr, &count_buffer_unbound); - - // VUID-vkCmdDrawIndexedIndirectCountKHR-countBuffer-02714 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndexedIndirectCountKHR-countBuffer-02714"); - vkCmdDrawIndexedIndirectCountKHR(m_commandBuffer->handle(), draw_buffer, 0, count_buffer_unbound, 0, 1, - sizeof(VkDrawIndexedIndirectCommand)); - m_errorMonitor->VerifyFound(); - - // VUID-vkCmdDrawIndexedIndirectCountKHR-offset-02710 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndexedIndirectCountKHR-offset-02710"); - vkCmdDrawIndexedIndirectCountKHR(m_commandBuffer->handle(), draw_buffer, 1, count_buffer, 0, 1, - sizeof(VkDrawIndexedIndirectCommand)); - m_errorMonitor->VerifyFound(); - - // VUID-vkCmdDrawIndexedIndirectCountKHR-countBufferOffset-02716 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdDrawIndexedIndirectCountKHR-countBufferOffset-02716"); - vkCmdDrawIndexedIndirectCountKHR(m_commandBuffer->handle(), draw_buffer, 0, count_buffer, 1, 1, - sizeof(VkDrawIndexedIndirectCommand)); - m_errorMonitor->VerifyFound(); - - // VUID-vkCmdDrawIndexedIndirectCountKHR-stride-03142 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndexedIndirectCountKHR-stride-03142"); - vkCmdDrawIndexedIndirectCountKHR(m_commandBuffer->handle(), draw_buffer, 0, count_buffer, 0, 1, 1); - m_errorMonitor->VerifyFound(); - - // TODO: These covered VUIDs aren't tested. There is also no test coverage for the core Vulkan 1.0 vkCmdDraw* equivalent of - // these: - // VUID-vkCmdDrawIndexedIndirectCountKHR-renderPass-02684 - // VUID-vkCmdDrawIndexedIndirectCountKHR-subpass-02685 - // VUID-vkCmdDrawIndexedIndirectCountKHR-commandBuffer-02701 (partial) - - m_commandBuffer->EndRenderPass(); - m_commandBuffer->end(); - - vkDestroyBuffer(m_device->device(), draw_buffer, 0); - vkDestroyBuffer(m_device->device(), draw_buffer_unbound, 0); - vkDestroyBuffer(m_device->device(), count_buffer, 0); - vkDestroyBuffer(m_device->device(), count_buffer_unbound, 0); - vkDestroyBuffer(m_device->device(), index_buffer, 0); - - vkFreeMemory(m_device->device(), draw_buffer_memory, 0); - vkFreeMemory(m_device->device(), count_buffer_memory, 0); - vkFreeMemory(m_device->device(), index_buffer_memory, 0); -} - -TEST_F(VkLayerTest, ExclusiveScissorNV) { - TEST_DESCRIPTION("Test VK_NV_scissor_exclusive with multiViewport disabled."); - - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - std::array<const char *, 1> required_device_extensions = {{VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME}}; - for (auto device_extension : required_device_extensions) { - if (DeviceExtensionSupported(gpu(), nullptr, device_extension)) { - m_device_extension_names.push_back(device_extension); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension); - return; - } - } - - PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = - (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR"); - ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr); - - // Create a device that enables exclusive scissor but disables multiViewport - auto exclusive_scissor_features = lvl_init_struct<VkPhysicalDeviceExclusiveScissorFeaturesNV>(); - auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&exclusive_scissor_features); - vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2); - - features2.features.multiViewport = VK_FALSE; - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - if (m_device->phy().properties().limits.maxViewports) { - printf("%s Device doesn't support the necessary number of viewports, skipping test.\n", kSkipPrefix); - return; - } - - // Based on PSOViewportStateTests - { - VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; - VkViewport viewports[] = {viewport, viewport}; - VkRect2D scissor = {{0, 0}, {64, 64}}; - VkRect2D scissors[100] = {scissor, scissor}; - - using std::vector; - struct TestCase { - uint32_t viewport_count; - VkViewport *viewports; - uint32_t scissor_count; - VkRect2D *scissors; - uint32_t exclusive_scissor_count; - VkRect2D *exclusive_scissors; - - vector<std::string> vuids; - }; - - vector<TestCase> test_cases = { - {1, - viewports, - 1, - scissors, - 2, - scissors, - {"VUID-VkPipelineViewportExclusiveScissorStateCreateInfoNV-exclusiveScissorCount-02027", - "VUID-VkPipelineViewportExclusiveScissorStateCreateInfoNV-exclusiveScissorCount-02029"}}, - {1, - viewports, - 1, - scissors, - 100, - scissors, - {"VUID-VkPipelineViewportExclusiveScissorStateCreateInfoNV-exclusiveScissorCount-02027", - "VUID-VkPipelineViewportExclusiveScissorStateCreateInfoNV-exclusiveScissorCount-02028", - "VUID-VkPipelineViewportExclusiveScissorStateCreateInfoNV-exclusiveScissorCount-02029"}}, - {1, - viewports, - 1, - scissors, - 1, - nullptr, - {"VUID-VkPipelineViewportExclusiveScissorStateCreateInfoNV-pDynamicStates-02030"}}, - }; - - for (const auto &test_case : test_cases) { - VkPipelineViewportExclusiveScissorStateCreateInfoNV exc = { - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV}; - - const auto break_vp = [&test_case, &exc](CreatePipelineHelper &helper) { - helper.vp_state_ci_.viewportCount = test_case.viewport_count; - helper.vp_state_ci_.pViewports = test_case.viewports; - helper.vp_state_ci_.scissorCount = test_case.scissor_count; - helper.vp_state_ci_.pScissors = test_case.scissors; - helper.vp_state_ci_.pNext = &exc; - - exc.exclusiveScissorCount = test_case.exclusive_scissor_count; - exc.pExclusiveScissors = test_case.exclusive_scissors; - }; - CreatePipelineHelper::OneshotTest(*this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuids); - } - } - - // Based on SetDynScissorParamTests - { - auto vkCmdSetExclusiveScissorNV = - (PFN_vkCmdSetExclusiveScissorNV)vkGetDeviceProcAddr(m_device->device(), "vkCmdSetExclusiveScissorNV"); - - const VkRect2D scissor = {{0, 0}, {16, 16}}; - const VkRect2D scissors[] = {scissor, scissor}; - - m_commandBuffer->begin(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdSetExclusiveScissorNV-firstExclusiveScissor-02035"); - vkCmdSetExclusiveScissorNV(m_commandBuffer->handle(), 1, 1, scissors); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkCmdSetExclusiveScissorNV: parameter exclusiveScissorCount must be greater than 0"); - vkCmdSetExclusiveScissorNV(m_commandBuffer->handle(), 0, 0, nullptr); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdSetExclusiveScissorNV-exclusiveScissorCount-02036"); - vkCmdSetExclusiveScissorNV(m_commandBuffer->handle(), 0, 2, scissors); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkCmdSetExclusiveScissorNV: parameter exclusiveScissorCount must be greater than 0"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdSetExclusiveScissorNV-firstExclusiveScissor-02035"); - vkCmdSetExclusiveScissorNV(m_commandBuffer->handle(), 1, 0, scissors); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdSetExclusiveScissorNV-firstExclusiveScissor-02035"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdSetExclusiveScissorNV-exclusiveScissorCount-02036"); - vkCmdSetExclusiveScissorNV(m_commandBuffer->handle(), 1, 2, scissors); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "vkCmdSetExclusiveScissorNV: required parameter pExclusiveScissors specified as NULL"); - vkCmdSetExclusiveScissorNV(m_commandBuffer->handle(), 0, 1, nullptr); - m_errorMonitor->VerifyFound(); - - struct TestCase { - VkRect2D scissor; - std::string vuid; - }; - - std::vector<TestCase> test_cases = { - {{{-1, 0}, {16, 16}}, "VUID-vkCmdSetExclusiveScissorNV-x-02037"}, - {{{0, -1}, {16, 16}}, "VUID-vkCmdSetExclusiveScissorNV-x-02037"}, - {{{1, 0}, {INT32_MAX, 16}}, "VUID-vkCmdSetExclusiveScissorNV-offset-02038"}, - {{{INT32_MAX, 0}, {1, 16}}, "VUID-vkCmdSetExclusiveScissorNV-offset-02038"}, - {{{0, 0}, {uint32_t{INT32_MAX} + 1, 16}}, "VUID-vkCmdSetExclusiveScissorNV-offset-02038"}, - {{{0, 1}, {16, INT32_MAX}}, "VUID-vkCmdSetExclusiveScissorNV-offset-02039"}, - {{{0, INT32_MAX}, {16, 1}}, "VUID-vkCmdSetExclusiveScissorNV-offset-02039"}, - {{{0, 0}, {16, uint32_t{INT32_MAX} + 1}}, "VUID-vkCmdSetExclusiveScissorNV-offset-02039"}}; - - for (const auto &test_case : test_cases) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuid); - vkCmdSetExclusiveScissorNV(m_commandBuffer->handle(), 0, 1, &test_case.scissor); - m_errorMonitor->VerifyFound(); - } - - m_commandBuffer->end(); - } -} - -TEST_F(VkLayerTest, ShadingRateImageNV) { - TEST_DESCRIPTION("Test VK_NV_shading_rate_image."); - - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - std::array<const char *, 1> required_device_extensions = {{VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME}}; - for (auto device_extension : required_device_extensions) { - if (DeviceExtensionSupported(gpu(), nullptr, device_extension)) { - m_device_extension_names.push_back(device_extension); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension); - return; - } - } - - if (DeviceIsMockICD() || DeviceSimulation()) { - printf("%s Test not supported by MockICD, skipping tests\n", kSkipPrefix); - return; - } - - PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = - (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR"); - ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr); - - // Create a device that enables shading_rate_image but disables multiViewport - auto shading_rate_image_features = lvl_init_struct<VkPhysicalDeviceShadingRateImageFeaturesNV>(); - auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&shading_rate_image_features); - vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2); - - features2.features.multiViewport = VK_FALSE; - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Test shading rate image creation - VkImage image = VK_NULL_HANDLE; - VkResult result = VK_RESULT_MAX_ENUM; - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_R8_UINT; - image_create_info.extent.width = 4; - image_create_info.extent.height = 4; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV; - image_create_info.queueFamilyIndexCount = 0; - image_create_info.pQueueFamilyIndices = NULL; - image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_create_info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; - - // image type must be 2D - image_create_info.imageType = VK_IMAGE_TYPE_3D; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-imageType-02082"); - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } - image_create_info.imageType = VK_IMAGE_TYPE_2D; - - // must be single sample - image_create_info.samples = VK_SAMPLE_COUNT_2_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-samples-02083"); - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - - // tiling must be optimal - image_create_info.tiling = VK_IMAGE_TILING_LINEAR; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-tiling-02084"); - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - - // Should succeed. - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyNotFound(); - - // bind memory to the image - VkMemoryRequirements memory_reqs; - VkDeviceMemory image_memory; - bool pass; - VkMemoryAllocateInfo memory_info = {}; - memory_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_info.pNext = NULL; - memory_info.allocationSize = 0; - memory_info.memoryTypeIndex = 0; - vkGetImageMemoryRequirements(m_device->device(), image, &memory_reqs); - memory_info.allocationSize = memory_reqs.size; - pass = m_device->phy().set_memory_type(memory_reqs.memoryTypeBits, &memory_info, 0); - ASSERT_TRUE(pass); - result = vkAllocateMemory(m_device->device(), &memory_info, NULL, &image_memory); - ASSERT_VK_SUCCESS(result); - result = vkBindImageMemory(m_device->device(), image, image_memory, 0); - ASSERT_VK_SUCCESS(result); - - // Test image view creation - VkImageView view; - VkImageViewCreateInfo ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.image = image; - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.format = VK_FORMAT_R8_UINT; - ivci.subresourceRange.layerCount = 1; - ivci.subresourceRange.baseMipLevel = 0; - ivci.subresourceRange.levelCount = 1; - ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - // view type must be 2D or 2D_ARRAY - ivci.viewType = VK_IMAGE_VIEW_TYPE_CUBE; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-image-02086"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-image-01003"); - result = vkCreateImageView(m_device->device(), &ivci, nullptr, &view); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImageView(m_device->device(), view, NULL); - view = VK_NULL_HANDLE; - } - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - - // format must be R8_UINT - ivci.format = VK_FORMAT_R8_UNORM; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-image-02087"); - result = vkCreateImageView(m_device->device(), &ivci, nullptr, &view); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImageView(m_device->device(), view, NULL); - view = VK_NULL_HANDLE; - } - ivci.format = VK_FORMAT_R8_UINT; - - vkCreateImageView(m_device->device(), &ivci, nullptr, &view); - m_errorMonitor->VerifyNotFound(); - - // Test pipeline creation - VkPipelineViewportShadingRateImageStateCreateInfoNV vsrisci = { - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV}; - - VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; - VkViewport viewports[20] = {viewport, viewport}; - VkRect2D scissor = {{0, 0}, {64, 64}}; - VkRect2D scissors[20] = {scissor, scissor}; - VkDynamicState dynPalette = VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV; - VkPipelineDynamicStateCreateInfo dyn = {VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, nullptr, 0, 1, &dynPalette}; - - // viewportCount must be 0 or 1 when multiViewport is disabled - { - const auto break_vp = [&](CreatePipelineHelper &helper) { - helper.vp_state_ci_.viewportCount = 2; - helper.vp_state_ci_.pViewports = viewports; - helper.vp_state_ci_.scissorCount = 2; - helper.vp_state_ci_.pScissors = scissors; - helper.vp_state_ci_.pNext = &vsrisci; - helper.dyn_state_ci_ = dyn; - - vsrisci.shadingRateImageEnable = VK_TRUE; - vsrisci.viewportCount = 2; - }; - CreatePipelineHelper::OneshotTest( - *this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, - vector<std::string>({"VUID-VkPipelineViewportShadingRateImageStateCreateInfoNV-viewportCount-02054", - "VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", - "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217"})); - } - - // viewportCounts must match - { - const auto break_vp = [&](CreatePipelineHelper &helper) { - helper.vp_state_ci_.viewportCount = 1; - helper.vp_state_ci_.pViewports = viewports; - helper.vp_state_ci_.scissorCount = 1; - helper.vp_state_ci_.pScissors = scissors; - helper.vp_state_ci_.pNext = &vsrisci; - helper.dyn_state_ci_ = dyn; - - vsrisci.shadingRateImageEnable = VK_TRUE; - vsrisci.viewportCount = 0; - }; - CreatePipelineHelper::OneshotTest( - *this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, - vector<std::string>({"VUID-VkPipelineViewportShadingRateImageStateCreateInfoNV-shadingRateImageEnable-02056"})); - } - - // pShadingRatePalettes must not be NULL. - { - const auto break_vp = [&](CreatePipelineHelper &helper) { - helper.vp_state_ci_.viewportCount = 1; - helper.vp_state_ci_.pViewports = viewports; - helper.vp_state_ci_.scissorCount = 1; - helper.vp_state_ci_.pScissors = scissors; - helper.vp_state_ci_.pNext = &vsrisci; - - vsrisci.shadingRateImageEnable = VK_TRUE; - vsrisci.viewportCount = 1; - }; - CreatePipelineHelper::OneshotTest( - *this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, - vector<std::string>({"VUID-VkPipelineViewportShadingRateImageStateCreateInfoNV-pDynamicStates-02057"})); - } - - // Create an image without the SRI bit - VkImageObj nonSRIimage(m_device); - nonSRIimage.Init(256, 256, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); - ASSERT_TRUE(nonSRIimage.initialized()); - VkImageView nonSRIview = nonSRIimage.targetView(VK_FORMAT_B8G8R8A8_UNORM); - - // Test SRI layout on non-SRI image - VkImageMemoryBarrier img_barrier = {}; - img_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - img_barrier.pNext = nullptr; - img_barrier.srcAccessMask = 0; - img_barrier.dstAccessMask = 0; - img_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - img_barrier.newLayout = VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV; - img_barrier.image = nonSRIimage.handle(); - img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - img_barrier.subresourceRange.baseArrayLayer = 0; - img_barrier.subresourceRange.baseMipLevel = 0; - img_barrier.subresourceRange.layerCount = 1; - img_barrier.subresourceRange.levelCount = 1; - - m_commandBuffer->begin(); - - // Error trying to convert it to SRI layout - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-oldLayout-02088"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, - nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyFound(); - - // succeed converting it to GENERAL - img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, - nullptr, 0, nullptr, 1, &img_barrier); - m_errorMonitor->VerifyNotFound(); - - // Test vkCmdBindShadingRateImageNV errors - auto vkCmdBindShadingRateImageNV = - (PFN_vkCmdBindShadingRateImageNV)vkGetDeviceProcAddr(m_device->device(), "vkCmdBindShadingRateImageNV"); - - // if the view is non-NULL, it must be R8_UINT, USAGE_SRI, image layout must match, layout must be valid - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindShadingRateImageNV-imageView-02060"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindShadingRateImageNV-imageView-02061"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindShadingRateImageNV-imageView-02062"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindShadingRateImageNV-imageLayout-02063"); - vkCmdBindShadingRateImageNV(m_commandBuffer->handle(), nonSRIview, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - m_errorMonitor->VerifyFound(); - - // Test vkCmdSetViewportShadingRatePaletteNV errors - auto vkCmdSetViewportShadingRatePaletteNV = - (PFN_vkCmdSetViewportShadingRatePaletteNV)vkGetDeviceProcAddr(m_device->device(), "vkCmdSetViewportShadingRatePaletteNV"); - - VkShadingRatePaletteEntryNV paletteEntries[100] = {}; - VkShadingRatePaletteNV palette = {100, paletteEntries}; - VkShadingRatePaletteNV palettes[] = {palette, palette}; - - // errors on firstViewport/viewportCount - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdSetViewportShadingRatePaletteNV-firstViewport-02066"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdSetViewportShadingRatePaletteNV-firstViewport-02067"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdSetViewportShadingRatePaletteNV-firstViewport-02068"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdSetViewportShadingRatePaletteNV-viewportCount-02069"); - vkCmdSetViewportShadingRatePaletteNV(m_commandBuffer->handle(), 20, 2, palettes); - m_errorMonitor->VerifyFound(); - - // shadingRatePaletteEntryCount must be in range - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkShadingRatePaletteNV-shadingRatePaletteEntryCount-02071"); - vkCmdSetViewportShadingRatePaletteNV(m_commandBuffer->handle(), 0, 1, palettes); - m_errorMonitor->VerifyFound(); - - VkCoarseSampleLocationNV locations[100] = { - {0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1, 1}, {0, 1, 1}, // duplicate - {1000, 0, 0}, // pixelX too large - {0, 1000, 0}, // pixelY too large - {0, 0, 1000}, // sample too large - }; - - // Test custom sample orders, both via pipeline state and via dynamic state - { - VkCoarseSampleOrderCustomNV sampOrdBadShadingRate = {VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV, 1, 1, - locations}; - VkCoarseSampleOrderCustomNV sampOrdBadSampleCount = {VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV, 3, 1, - locations}; - VkCoarseSampleOrderCustomNV sampOrdBadSampleLocationCount = {VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV, - 2, 2, locations}; - VkCoarseSampleOrderCustomNV sampOrdDuplicateLocations = {VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV, 2, - 1 * 2 * 2, &locations[1]}; - VkCoarseSampleOrderCustomNV sampOrdOutOfRangeLocations = {VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV, 2, - 1 * 2 * 2, &locations[4]}; - VkCoarseSampleOrderCustomNV sampOrdTooLargeSampleLocationCount = { - VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV, 4, 64, &locations[8]}; - VkCoarseSampleOrderCustomNV sampOrdGood = {VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV, 2, 1 * 2 * 2, - &locations[0]}; - - VkPipelineViewportCoarseSampleOrderStateCreateInfoNV csosci = { - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV}; - csosci.sampleOrderType = VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV; - csosci.customSampleOrderCount = 1; - - using std::vector; - struct TestCase { - const VkCoarseSampleOrderCustomNV *order; - vector<std::string> vuids; - }; - - vector<TestCase> test_cases = { - {&sampOrdBadShadingRate, {"VUID-VkCoarseSampleOrderCustomNV-shadingRate-02073"}}, - {&sampOrdBadSampleCount, - {"VUID-VkCoarseSampleOrderCustomNV-sampleCount-02074", "VUID-VkCoarseSampleOrderCustomNV-sampleLocationCount-02075"}}, - {&sampOrdBadSampleLocationCount, {"VUID-VkCoarseSampleOrderCustomNV-sampleLocationCount-02075"}}, - {&sampOrdDuplicateLocations, {"VUID-VkCoarseSampleOrderCustomNV-pSampleLocations-02077"}}, - {&sampOrdOutOfRangeLocations, - {"VUID-VkCoarseSampleOrderCustomNV-pSampleLocations-02077", "VUID-VkCoarseSampleLocationNV-pixelX-02078", - "VUID-VkCoarseSampleLocationNV-pixelY-02079", "VUID-VkCoarseSampleLocationNV-sample-02080"}}, - {&sampOrdTooLargeSampleLocationCount, - {"VUID-VkCoarseSampleOrderCustomNV-sampleLocationCount-02076", - "VUID-VkCoarseSampleOrderCustomNV-pSampleLocations-02077"}}, - {&sampOrdGood, {}}, - }; - - for (const auto &test_case : test_cases) { - const auto break_vp = [&](CreatePipelineHelper &helper) { - helper.vp_state_ci_.pNext = &csosci; - csosci.pCustomSampleOrders = test_case.order; - }; - CreatePipelineHelper::OneshotTest(*this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuids); - } - - // Test vkCmdSetCoarseSampleOrderNV errors - auto vkCmdSetCoarseSampleOrderNV = - (PFN_vkCmdSetCoarseSampleOrderNV)vkGetDeviceProcAddr(m_device->device(), "vkCmdSetCoarseSampleOrderNV"); - - for (const auto &test_case : test_cases) { - for (uint32_t i = 0; i < test_case.vuids.size(); ++i) { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuids[i]); - } - vkCmdSetCoarseSampleOrderNV(m_commandBuffer->handle(), VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV, 1, test_case.order); - if (test_case.vuids.size()) { - m_errorMonitor->VerifyFound(); - } else { - m_errorMonitor->VerifyNotFound(); - } - } - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkCmdSetCoarseSampleOrderNV-sampleOrderType-02081"); - vkCmdSetCoarseSampleOrderNV(m_commandBuffer->handle(), VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV, 1, &sampOrdGood); - m_errorMonitor->VerifyFound(); - } - - m_commandBuffer->end(); - - vkDestroyImageView(m_device->device(), view, NULL); - vkDestroyImage(m_device->device(), image, NULL); - vkFreeMemory(m_device->device(), image_memory, NULL); -} - -TEST_F(VkLayerTest, CornerSampledImageNV) { - TEST_DESCRIPTION("Test VK_NV_corner_sampled_image."); - - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - std::array<const char *, 1> required_device_extensions = {{VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME}}; - for (auto device_extension : required_device_extensions) { - if (DeviceExtensionSupported(gpu(), nullptr, device_extension)) { - m_device_extension_names.push_back(device_extension); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension); - return; - } - } - - PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = - (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR"); - ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr); - - // Create a device that enables exclusive scissor but disables multiViewport - auto corner_sampled_image_features = lvl_init_struct<VkPhysicalDeviceCornerSampledImageFeaturesNV>(); - auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&corner_sampled_image_features); - vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2); - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); - - VkImage image = VK_NULL_HANDLE; - VkResult result = VK_RESULT_MAX_ENUM; - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = NULL; - image_create_info.imageType = VK_IMAGE_TYPE_1D; - image_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; - image_create_info.extent.width = 2; - image_create_info.extent.height = 1; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; - image_create_info.queueFamilyIndexCount = 0; - image_create_info.pQueueFamilyIndices = NULL; - image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_create_info.flags = VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV; - - // image type must be 2D or 3D - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-flags-02050"); - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } - - // cube/depth not supported - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.extent.height = 2; - image_create_info.format = VK_FORMAT_D24_UNORM_S8_UINT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-flags-02051"); - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } - image_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; - - // 2D width/height must be > 1 - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.extent.height = 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-flags-02052"); - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } - - // 3D width/height/depth must be > 1 - image_create_info.imageType = VK_IMAGE_TYPE_3D; - image_create_info.extent.height = 2; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-flags-02053"); - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } - image_create_info.imageType = VK_IMAGE_TYPE_2D; - - // Valid # of mip levels - image_create_info.extent = {7, 7, 1}; - image_create_info.mipLevels = 3; // 3 = ceil(log2(7)) - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyNotFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } - - image_create_info.extent = {8, 8, 1}; - image_create_info.mipLevels = 3; // 3 = ceil(log2(8)) - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyNotFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } - - image_create_info.extent = {9, 9, 1}; - image_create_info.mipLevels = 3; // 4 = ceil(log2(9)) - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyNotFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } - - // Invalid # of mip levels - image_create_info.extent = {8, 8, 1}; - image_create_info.mipLevels = 4; // 3 = ceil(log2(8)) - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-mipLevels-00958"); - result = vkCreateImage(m_device->device(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); - if (VK_SUCCESS == result) { - vkDestroyImage(m_device->device(), image, NULL); - image = VK_NULL_HANDLE; - } -} - -TEST_F(VkLayerTest, MeshShaderNV) { - TEST_DESCRIPTION("Test VK_NV_mesh_shader."); - - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - std::array<const char *, 1> required_device_extensions = {{VK_NV_MESH_SHADER_EXTENSION_NAME}}; - for (auto device_extension : required_device_extensions) { - if (DeviceExtensionSupported(gpu(), nullptr, device_extension)) { - m_device_extension_names.push_back(device_extension); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension); - return; - } - } - - if (DeviceIsMockICD() || DeviceSimulation()) { - printf("%sNot suppored by MockICD, skipping tests\n", kSkipPrefix); - return; - } - - PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = - (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR"); - ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr); - - // Create a device that enables mesh_shader - auto mesh_shader_features = lvl_init_struct<VkPhysicalDeviceMeshShaderFeaturesNV>(); - auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&mesh_shader_features); - vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2); - features2.features.multiDrawIndirect = VK_FALSE; - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - static const char vertShaderText[] = - "#version 450\n" - "vec2 vertices[3];\n" - "void main() {\n" - " vertices[0] = vec2(-1.0, -1.0);\n" - " vertices[1] = vec2( 1.0, -1.0);\n" - " vertices[2] = vec2( 0.0, 1.0);\n" - " gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);\n" - " gl_PointSize = 1.0f;\n" - "}\n"; - - static const char meshShaderText[] = - "#version 450\n" - "#extension GL_NV_mesh_shader : require\n" - "layout(local_size_x = 1) in;\n" - "layout(max_vertices = 3) out;\n" - "layout(max_primitives = 1) out;\n" - "layout(triangles) out;\n" - "void main() {\n" - " gl_MeshVerticesNV[0].gl_Position = vec4(-1.0, -1.0, 0, 1);\n" - " gl_MeshVerticesNV[1].gl_Position = vec4( 1.0, -1.0, 0, 1);\n" - " gl_MeshVerticesNV[2].gl_Position = vec4( 0.0, 1.0, 0, 1);\n" - " gl_PrimitiveIndicesNV[0] = 0;\n" - " gl_PrimitiveIndicesNV[1] = 1;\n" - " gl_PrimitiveIndicesNV[2] = 2;\n" - " gl_PrimitiveCountNV = 1;\n" - "}\n"; - - VkShaderObj vs(m_device, vertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkShaderObj ms(m_device, meshShaderText, VK_SHADER_STAGE_MESH_BIT_NV, this); - VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - // Test pipeline creation - { - // can't mix mesh with vertex - const auto break_vp = [&](CreatePipelineHelper &helper) { - helper.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo(), ms.GetStageCreateInfo()}; - }; - CreatePipelineHelper::OneshotTest(*this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, - vector<std::string>({"VUID-VkGraphicsPipelineCreateInfo-pStages-02095"})); - - // vertex or mesh must be present - const auto break_vp2 = [&](CreatePipelineHelper &helper) { helper.shader_stages_ = {fs.GetStageCreateInfo()}; }; - CreatePipelineHelper::OneshotTest(*this, break_vp2, VK_DEBUG_REPORT_ERROR_BIT_EXT, - vector<std::string>({"VUID-VkGraphicsPipelineCreateInfo-stage-02096"})); - - // vertexinput and inputassembly must be valid when vertex stage is present - const auto break_vp3 = [&](CreatePipelineHelper &helper) { - helper.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; - helper.gp_ci_.pVertexInputState = nullptr; - helper.gp_ci_.pInputAssemblyState = nullptr; - }; - CreatePipelineHelper::OneshotTest(*this, break_vp3, VK_DEBUG_REPORT_ERROR_BIT_EXT, - vector<std::string>({"VUID-VkGraphicsPipelineCreateInfo-pStages-02097", - "VUID-VkGraphicsPipelineCreateInfo-pStages-02098"})); - } - - PFN_vkCmdDrawMeshTasksIndirectNV vkCmdDrawMeshTasksIndirectNV = - (PFN_vkCmdDrawMeshTasksIndirectNV)vkGetInstanceProcAddr(instance(), "vkCmdDrawMeshTasksIndirectNV"); - - VkBufferCreateInfo buffer_create_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; - buffer_create_info.size = sizeof(uint32_t); - buffer_create_info.usage = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; - VkBuffer buffer; - VkResult result = vkCreateBuffer(m_device->device(), &buffer_create_info, nullptr, &buffer); - ASSERT_VK_SUCCESS(result); - - m_commandBuffer->begin(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawMeshTasksIndirectNV-drawCount-02146"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawMeshTasksIndirectNV-drawCount-02718"); - vkCmdDrawMeshTasksIndirectNV(m_commandBuffer->handle(), buffer, 0, 2, 0); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->end(); - - vkDestroyBuffer(m_device->device(), buffer, 0); -} - -TEST_F(VkLayerTest, MeshShaderDisabledNV) { - TEST_DESCRIPTION("Test VK_NV_mesh_shader VUs with NV_mesh_shader disabled."); - ASSERT_NO_FATAL_FAILURE(Init()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkEvent event; - VkEventCreateInfo event_create_info{}; - event_create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - vkCreateEvent(m_device->device(), &event_create_info, nullptr, &event); - - m_commandBuffer->begin(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetEvent-stageMask-02107"); - vkCmdSetEvent(m_commandBuffer->handle(), event, VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetEvent-stageMask-02108"); - vkCmdSetEvent(m_commandBuffer->handle(), event, VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdResetEvent-stageMask-02109"); - vkCmdResetEvent(m_commandBuffer->handle(), event, VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdResetEvent-stageMask-02110"); - vkCmdResetEvent(m_commandBuffer->handle(), event, VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdWaitEvents-srcStageMask-02111"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdWaitEvents-dstStageMask-02113"); - vkCmdWaitEvents(m_commandBuffer->handle(), 1, &event, VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV, - VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV, 0, nullptr, 0, nullptr, 0, nullptr); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdWaitEvents-srcStageMask-02112"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdWaitEvents-dstStageMask-02114"); - vkCmdWaitEvents(m_commandBuffer->handle(), 1, &event, VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV, - VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV, 0, nullptr, 0, nullptr, 0, nullptr); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-srcStageMask-02115"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-dstStageMask-02117"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV, VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV, 0, - 0, nullptr, 0, nullptr, 0, nullptr); - m_errorMonitor->VerifyFound(); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-srcStageMask-02116"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-dstStageMask-02118"); - vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV, VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV, 0, - 0, nullptr, 0, nullptr, 0, nullptr); - m_errorMonitor->VerifyFound(); - - m_commandBuffer->end(); - - VkSemaphoreCreateInfo semaphore_create_info = {}; - semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - VkSemaphore semaphore; - ASSERT_VK_SUCCESS(vkCreateSemaphore(m_device->device(), &semaphore_create_info, nullptr, &semaphore)); - - VkPipelineStageFlags stage_flags = VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV | VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV; - VkSubmitInfo submit_info = {}; - - // Signal the semaphore so the next test can wait on it. - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &semaphore; - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyNotFound(); - - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.signalSemaphoreCount = 0; - submit_info.pSignalSemaphores = nullptr; - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &semaphore; - submit_info.pWaitDstStageMask = &stage_flags; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkSubmitInfo-pWaitDstStageMask-02089"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkSubmitInfo-pWaitDstStageMask-02090"); - vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); - m_errorMonitor->VerifyFound(); - - vkQueueWaitIdle(m_device->m_queue); - - VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); - VkPipelineShaderStageCreateInfo meshStage = {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO}; - meshStage = vs.GetStageCreateInfo(); - meshStage.stage = VK_SHADER_STAGE_MESH_BIT_NV; - VkPipelineShaderStageCreateInfo taskStage = {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO}; - taskStage = vs.GetStageCreateInfo(); - taskStage.stage = VK_SHADER_STAGE_TASK_BIT_NV; - - // mesh and task shaders not supported - const auto break_vp = [&](CreatePipelineHelper &helper) { - helper.shader_stages_ = {meshStage, taskStage, vs.GetStageCreateInfo()}; - }; - CreatePipelineHelper::OneshotTest( - *this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, - vector<std::string>({"VUID-VkPipelineShaderStageCreateInfo-pName-00707", "VUID-VkPipelineShaderStageCreateInfo-pName-00707", - "VUID-VkPipelineShaderStageCreateInfo-stage-02091", - "VUID-VkPipelineShaderStageCreateInfo-stage-02092"})); - - vkDestroyEvent(m_device->device(), event, nullptr); - vkDestroySemaphore(m_device->device(), semaphore, nullptr); -} - -TEST_F(VkLayerTest, InlineUniformBlockEXT) { - TEST_DESCRIPTION("Test VK_EXT_inline_uniform_block."); - - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - std::array<const char *, 2> required_device_extensions = {VK_KHR_MAINTENANCE1_EXTENSION_NAME, - VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME}; - for (auto device_extension : required_device_extensions) { - if (DeviceExtensionSupported(gpu(), nullptr, device_extension)) { - m_device_extension_names.push_back(device_extension); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension); - return; - } - } - - // Enable descriptor indexing if supported, but don't require it. - bool supportsDescriptorIndexing = true; - required_device_extensions = {VK_KHR_MAINTENANCE3_EXTENSION_NAME, VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME}; - for (auto device_extension : required_device_extensions) { - if (DeviceExtensionSupported(gpu(), nullptr, device_extension)) { - m_device_extension_names.push_back(device_extension); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension); - supportsDescriptorIndexing = false; - return; - } - } - - PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = - (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR"); - ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr); - - auto descriptor_indexing_features = lvl_init_struct<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>(); - void *pNext = supportsDescriptorIndexing ? &descriptor_indexing_features : nullptr; - // Create a device that enables inline_uniform_block - auto inline_uniform_block_features = lvl_init_struct<VkPhysicalDeviceInlineUniformBlockFeaturesEXT>(pNext); - auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&inline_uniform_block_features); - vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2); - - PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR = - (PFN_vkGetPhysicalDeviceProperties2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceProperties2KHR"); - assert(vkGetPhysicalDeviceProperties2KHR != nullptr); - - // Get the inline uniform block limits - auto inline_uniform_props = lvl_init_struct<VkPhysicalDeviceInlineUniformBlockPropertiesEXT>(); - auto prop2 = lvl_init_struct<VkPhysicalDeviceProperties2KHR>(&inline_uniform_props); - vkGetPhysicalDeviceProperties2KHR(gpu(), &prop2); - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); - - VkDescriptorSetLayoutBinding dslb = {}; - std::vector<VkDescriptorSetLayoutBinding> dslb_vec = {}; - VkDescriptorSetLayoutCreateInfo ds_layout_ci = {}; - ds_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - VkDescriptorSetLayout ds_layout = {}; - - // Test too many bindings - dslb_vec.clear(); - dslb.binding = 0; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT; - dslb.descriptorCount = 4; - dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - - if (inline_uniform_props.maxInlineUniformBlockSize < dslb.descriptorCount) { - printf("%sDescriptorCount exceeds InlineUniformBlockSize limit, skipping tests\n", kSkipPrefix); - return; - } - - uint32_t maxBlocks = std::max(inline_uniform_props.maxPerStageDescriptorInlineUniformBlocks, - inline_uniform_props.maxDescriptorSetInlineUniformBlocks); - for (uint32_t i = 0; i < 1 + maxBlocks; ++i) { - dslb.binding = i; - dslb_vec.push_back(dslb); - } - - ds_layout_ci.bindingCount = dslb_vec.size(); - ds_layout_ci.pBindings = dslb_vec.data(); - VkResult err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - ASSERT_VK_SUCCESS(err); - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-descriptorType-02214"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-descriptorType-02216"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-descriptorType-02215"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-descriptorType-02217"); - - VkPipelineLayoutCreateInfo pipeline_layout_ci = {}; - pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_ci.pNext = NULL; - pipeline_layout_ci.setLayoutCount = 1; - pipeline_layout_ci.pSetLayouts = &ds_layout; - VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; - - err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout); - m_errorMonitor->VerifyFound(); - vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL); - pipeline_layout = VK_NULL_HANDLE; - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, nullptr); - ds_layout = VK_NULL_HANDLE; - - // Single binding that's too large and is not a multiple of 4 - dslb.binding = 0; - dslb.descriptorCount = inline_uniform_props.maxInlineUniformBlockSize + 1; - - ds_layout_ci.bindingCount = 1; - ds_layout_ci.pBindings = &dslb; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorSetLayoutBinding-descriptorType-02209"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorSetLayoutBinding-descriptorType-02210"); - err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - m_errorMonitor->VerifyFound(); - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, nullptr); - ds_layout = VK_NULL_HANDLE; - - // Pool size must be a multiple of 4 - VkDescriptorPoolSize ds_type_count = {}; - ds_type_count.type = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT; - ds_type_count.descriptorCount = 33; - - VkDescriptorPoolCreateInfo ds_pool_ci = {}; - ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - ds_pool_ci.pNext = NULL; - ds_pool_ci.flags = 0; - ds_pool_ci.maxSets = 2; - ds_pool_ci.poolSizeCount = 1; - ds_pool_ci.pPoolSizes = &ds_type_count; - - VkDescriptorPool ds_pool = VK_NULL_HANDLE; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorPoolSize-type-02218"); - err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - m_errorMonitor->VerifyFound(); - if (ds_pool) { - vkDestroyDescriptorPool(m_device->handle(), ds_pool, nullptr); - ds_pool = VK_NULL_HANDLE; - } - - // Create a valid pool - ds_type_count.descriptorCount = 32; - err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); - m_errorMonitor->VerifyNotFound(); - - // Create two valid sets with 8 bytes each - dslb_vec.clear(); - dslb.binding = 0; - dslb.descriptorType = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT; - dslb.descriptorCount = 8; - dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - dslb_vec.push_back(dslb); - dslb.binding = 1; - dslb_vec.push_back(dslb); - - ds_layout_ci.bindingCount = dslb_vec.size(); - ds_layout_ci.pBindings = &dslb_vec[0]; - - err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout); - m_errorMonitor->VerifyNotFound(); - - VkDescriptorSet descriptor_sets[2]; - VkDescriptorSetLayout set_layouts[2] = {ds_layout, ds_layout}; - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorSetCount = 2; - alloc_info.descriptorPool = ds_pool; - alloc_info.pSetLayouts = set_layouts; - err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, descriptor_sets); - m_errorMonitor->VerifyNotFound(); - - // Test invalid VkWriteDescriptorSet parameters (array element and size must be multiple of 4) - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = descriptor_sets[0]; - descriptor_write.dstBinding = 0; - descriptor_write.dstArrayElement = 0; - descriptor_write.descriptorCount = 3; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT; - - uint32_t dummyData[8] = {}; - VkWriteDescriptorSetInlineUniformBlockEXT write_inline_uniform = {}; - write_inline_uniform.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT; - write_inline_uniform.dataSize = 3; - write_inline_uniform.pData = &dummyData[0]; - descriptor_write.pNext = &write_inline_uniform; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-02220"); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - - descriptor_write.dstArrayElement = 1; - descriptor_write.descriptorCount = 4; - write_inline_uniform.dataSize = 4; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-02219"); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - - descriptor_write.pNext = nullptr; - descriptor_write.dstArrayElement = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-02221"); - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyFound(); - - descriptor_write.pNext = &write_inline_uniform; - vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); - m_errorMonitor->VerifyNotFound(); - - // Test invalid VkCopyDescriptorSet parameters (array element and size must be multiple of 4) - VkCopyDescriptorSet copy_ds_update = {}; - copy_ds_update.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; - copy_ds_update.srcSet = descriptor_sets[0]; - copy_ds_update.srcBinding = 0; - copy_ds_update.srcArrayElement = 0; - copy_ds_update.dstSet = descriptor_sets[1]; - copy_ds_update.dstBinding = 0; - copy_ds_update.dstArrayElement = 0; - copy_ds_update.descriptorCount = 4; - - copy_ds_update.srcArrayElement = 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkCopyDescriptorSet-srcBinding-02223"); - vkUpdateDescriptorSets(m_device->device(), 0, NULL, 1, ©_ds_update); - m_errorMonitor->VerifyFound(); - - copy_ds_update.srcArrayElement = 0; - copy_ds_update.dstArrayElement = 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkCopyDescriptorSet-dstBinding-02224"); - vkUpdateDescriptorSets(m_device->device(), 0, NULL, 1, ©_ds_update); - m_errorMonitor->VerifyFound(); - - copy_ds_update.dstArrayElement = 0; - copy_ds_update.descriptorCount = 5; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkCopyDescriptorSet-srcBinding-02225"); - vkUpdateDescriptorSets(m_device->device(), 0, NULL, 1, ©_ds_update); - m_errorMonitor->VerifyFound(); - - copy_ds_update.descriptorCount = 4; - vkUpdateDescriptorSets(m_device->device(), 0, NULL, 1, ©_ds_update); - m_errorMonitor->VerifyNotFound(); - - vkDestroyDescriptorPool(m_device->handle(), ds_pool, nullptr); - vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, nullptr); -} - -TEST_F(VkLayerTest, FramebufferMixedSamplesNV) { - TEST_DESCRIPTION("Verify VK_NV_framebuffer_mixed_samples."); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if (DeviceExtensionSupported(gpu(), nullptr, VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME); - return; - } - - VkPhysicalDeviceFeatures device_features = {}; - ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features)); - if (VK_TRUE != device_features.sampleRateShading) { - printf("%s Test requires unsupported sampleRateShading feature.\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - struct TestCase { - VkSampleCountFlagBits color_samples; - VkSampleCountFlagBits depth_samples; - VkSampleCountFlagBits raster_samples; - VkBool32 depth_test; - VkBool32 sample_shading; - uint32_t table_count; - bool positiveTest; - std::string vuid; - }; - - std::vector<TestCase> test_cases = { - {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_FALSE, VK_FALSE, 1, true, - "VUID-VkGraphicsPipelineCreateInfo-subpass-00757"}, - {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT, VK_FALSE, VK_FALSE, 4, false, - "VUID-VkPipelineCoverageModulationStateCreateInfoNV-coverageModulationTableEnable-01405"}, - {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT, VK_FALSE, VK_FALSE, 2, true, - "VUID-VkPipelineCoverageModulationStateCreateInfoNV-coverageModulationTableEnable-01405"}, - {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, VK_TRUE, VK_FALSE, 1, false, - "VUID-VkGraphicsPipelineCreateInfo-subpass-01411"}, - {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_8_BIT, VK_TRUE, VK_FALSE, 1, true, - "VUID-VkGraphicsPipelineCreateInfo-subpass-01411"}, - {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_1_BIT, VK_FALSE, VK_FALSE, 1, false, - "VUID-VkGraphicsPipelineCreateInfo-subpass-01412"}, - {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT, VK_FALSE, VK_FALSE, 1, true, - "VUID-VkGraphicsPipelineCreateInfo-subpass-01412"}, - {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_FALSE, VK_TRUE, 1, false, - "VUID-VkPipelineMultisampleStateCreateInfo-rasterizationSamples-01415"}, - {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_FALSE, VK_FALSE, 1, true, - "VUID-VkPipelineMultisampleStateCreateInfo-rasterizationSamples-01415"}, - {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, VK_FALSE, VK_FALSE, 1, true, - "VUID-VkGraphicsPipelineCreateInfo-subpass-00757"}}; - - for (const auto &test_case : test_cases) { - VkAttachmentDescription att[2] = {{}, {}}; - att[0].format = VK_FORMAT_R8G8B8A8_UNORM; - att[0].samples = test_case.color_samples; - att[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - att[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - att[1].format = VK_FORMAT_D24_UNORM_S8_UINT; - att[1].samples = test_case.depth_samples; - att[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - att[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference cr = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - VkAttachmentReference dr = {1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}; - - VkSubpassDescription sp = {}; - sp.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - sp.colorAttachmentCount = 1; - sp.pColorAttachments = &cr; - sp.pResolveAttachments = NULL; - sp.pDepthStencilAttachment = &dr; - - VkRenderPassCreateInfo rpi = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO}; - rpi.attachmentCount = 2; - rpi.pAttachments = att; - rpi.subpassCount = 1; - rpi.pSubpasses = &sp; - - VkRenderPass rp; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkSubpassDescription-pDepthStencilAttachment-01418"); - VkResult err = vkCreateRenderPass(m_device->device(), &rpi, nullptr, &rp); - m_errorMonitor->VerifyNotFound(); - - ASSERT_VK_SUCCESS(err); - - VkPipelineDepthStencilStateCreateInfo ds = {VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO}; - VkPipelineCoverageModulationStateCreateInfoNV cmi = {VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV}; - - // Create a dummy modulation table that can be used for the positive - // coverageModulationTableCount test. - std::vector<float> cm_table{}; - - const auto break_samples = [&cmi, &rp, &ds, &cm_table, &test_case](CreatePipelineHelper &helper) { - cm_table.resize(test_case.raster_samples / test_case.color_samples); - - cmi.flags = 0; - cmi.coverageModulationTableEnable = (test_case.table_count > 1); - cmi.coverageModulationTableCount = test_case.table_count; - cmi.pCoverageModulationTable = cm_table.data(); - - ds.depthTestEnable = test_case.depth_test; - - helper.pipe_ms_state_ci_.pNext = &cmi; - helper.pipe_ms_state_ci_.rasterizationSamples = test_case.raster_samples; - helper.pipe_ms_state_ci_.sampleShadingEnable = test_case.sample_shading; - - helper.gp_ci_.renderPass = rp; - helper.gp_ci_.pDepthStencilState = &ds; - }; - - CreatePipelineHelper::OneshotTest(*this, break_samples, VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuid, - test_case.positiveTest); - - vkDestroyRenderPass(m_device->device(), rp, nullptr); - } -} - -TEST_F(VkLayerTest, FramebufferMixedSamples) { - TEST_DESCRIPTION("Verify that the expected VUIds are hits when VK_NV_framebuffer_mixed_samples is disabled."); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - ASSERT_NO_FATAL_FAILURE(InitState()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - struct TestCase { - VkSampleCountFlagBits color_samples; - VkSampleCountFlagBits depth_samples; - VkSampleCountFlagBits raster_samples; - bool positiveTest; - }; - - std::vector<TestCase> test_cases = { - {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, - false}, // Fails vkCreateRenderPass and vkCreateGraphicsPipeline - {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, false}, // Fails vkCreateGraphicsPipeline - {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, true} // Pass - }; - - for (const auto &test_case : test_cases) { - VkAttachmentDescription att[2] = {{}, {}}; - att[0].format = VK_FORMAT_R8G8B8A8_UNORM; - att[0].samples = test_case.color_samples; - att[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - att[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - att[1].format = VK_FORMAT_D24_UNORM_S8_UINT; - att[1].samples = test_case.depth_samples; - att[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - att[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference cr = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - VkAttachmentReference dr = {1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}; - - VkSubpassDescription sp = {}; - sp.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - sp.colorAttachmentCount = 1; - sp.pColorAttachments = &cr; - sp.pResolveAttachments = NULL; - sp.pDepthStencilAttachment = &dr; - - VkRenderPassCreateInfo rpi = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO}; - rpi.attachmentCount = 2; - rpi.pAttachments = att; - rpi.subpassCount = 1; - rpi.pSubpasses = &sp; - - VkRenderPass rp; - - if (test_case.color_samples == test_case.depth_samples) { - m_errorMonitor->ExpectSuccess(); - } else { - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkSubpassDescription-pDepthStencilAttachment-01418"); - } - - VkResult err = vkCreateRenderPass(m_device->device(), &rpi, nullptr, &rp); - - if (test_case.color_samples == test_case.depth_samples) { - m_errorMonitor->VerifyNotFound(); - } else { - m_errorMonitor->VerifyFound(); - continue; - } - - ASSERT_VK_SUCCESS(err); - - VkPipelineDepthStencilStateCreateInfo ds = {VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO}; - - const auto break_samples = [&rp, &ds, &test_case](CreatePipelineHelper &helper) { - helper.pipe_ms_state_ci_.rasterizationSamples = test_case.raster_samples; - - helper.gp_ci_.renderPass = rp; - helper.gp_ci_.pDepthStencilState = &ds; - }; - - CreatePipelineHelper::OneshotTest(*this, break_samples, VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkGraphicsPipelineCreateInfo-subpass-00757", test_case.positiveTest); - - vkDestroyRenderPass(m_device->device(), rp, nullptr); - } -} - -TEST_F(VkLayerTest, FragmentCoverageToColorNV) { - TEST_DESCRIPTION("Verify VK_NV_fragment_coverage_to_color."); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if (DeviceExtensionSupported(gpu(), nullptr, VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - struct TestCase { - VkFormat format; - VkBool32 enabled; - uint32_t location; - bool positive; - }; - - const std::array<TestCase, 9> test_cases = {{ - {VK_FORMAT_R8G8B8A8_UNORM, VK_FALSE, 0, true}, - {VK_FORMAT_R8_UINT, VK_TRUE, 1, true}, - {VK_FORMAT_R16_UINT, VK_TRUE, 1, true}, - {VK_FORMAT_R16_SINT, VK_TRUE, 1, true}, - {VK_FORMAT_R32_UINT, VK_TRUE, 1, true}, - {VK_FORMAT_R32_SINT, VK_TRUE, 1, true}, - {VK_FORMAT_R32_SINT, VK_TRUE, 2, false}, - {VK_FORMAT_R8_SINT, VK_TRUE, 3, false}, - {VK_FORMAT_R8G8B8A8_UNORM, VK_TRUE, 1, false}, - }}; - - for (const auto &test_case : test_cases) { - std::array<VkAttachmentDescription, 2> att = {{{}, {}}}; - att[0].format = VK_FORMAT_R8G8B8A8_UNORM; - att[0].samples = VK_SAMPLE_COUNT_1_BIT; - att[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - att[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - att[1].format = VK_FORMAT_R8G8B8A8_UNORM; - att[1].samples = VK_SAMPLE_COUNT_1_BIT; - att[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - att[1].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - if (test_case.location < att.size()) { - att[test_case.location].format = test_case.format; - } - - const std::array<VkAttachmentReference, 3> cr = {{{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - {1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, - {VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}}}; - - VkSubpassDescription sp = {}; - sp.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - sp.colorAttachmentCount = cr.size(); - sp.pColorAttachments = cr.data(); - - VkRenderPassCreateInfo rpi = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO}; - rpi.attachmentCount = att.size(); - rpi.pAttachments = att.data(); - rpi.subpassCount = 1; - rpi.pSubpasses = &sp; - - const std::array<VkPipelineColorBlendAttachmentState, 3> cba = {{{}, {}, {}}}; - - VkPipelineColorBlendStateCreateInfo cbi = {VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO}; - cbi.attachmentCount = cba.size(); - cbi.pAttachments = cba.data(); - - VkRenderPass rp; - VkResult err = vkCreateRenderPass(m_device->device(), &rpi, nullptr, &rp); - ASSERT_VK_SUCCESS(err); - - VkPipelineCoverageToColorStateCreateInfoNV cci = {VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV}; - - const auto break_samples = [&cci, &cbi, &rp, &test_case](CreatePipelineHelper &helper) { - cci.coverageToColorEnable = test_case.enabled; - cci.coverageToColorLocation = test_case.location; - - helper.pipe_ms_state_ci_.pNext = &cci; - helper.gp_ci_.renderPass = rp; - helper.gp_ci_.pColorBlendState = &cbi; - }; - - CreatePipelineHelper::OneshotTest(*this, break_samples, VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineCoverageToColorStateCreateInfoNV-coverageToColorEnable-01404", - test_case.positive); - - vkDestroyRenderPass(m_device->device(), rp, nullptr); - } -} - -TEST_F(VkPositiveLayerTest, RayTracingPipelineNV) { - TEST_DESCRIPTION("Test VK_NV_ray_tracing."); - - if (!CreateNVRayTracingPipelineHelper::InitInstanceExtensions(*this, m_instance_extension_names)) { - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = - (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR"); - ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr); - - if (!CreateNVRayTracingPipelineHelper::InitDeviceExtensions(*this, m_device_extension_names)) { - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - auto ignore_update = [](CreateNVRayTracingPipelineHelper &helper) {}; - CreateNVRayTracingPipelineHelper::OneshotPositiveTest(*this, ignore_update); -} - -TEST_F(VkLayerTest, CreateYCbCrSampler) { - TEST_DESCRIPTION("Verify YCbCr sampler creation."); - - // Test requires API 1.1 or (API 1.0 + SamplerYCbCr extension). Request API 1.1 - SetTargetApiVersion(VK_API_VERSION_1_1); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - // In case we don't have API 1.1+, try enabling the extension directly (and it's dependencies) - if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - VkDevice dev = m_device->device(); - - // Verify we have the requested support - bool ycbcr_support = (DeviceExtensionEnabled(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME) || - (DeviceValidationVersion() >= VK_API_VERSION_1_1)); - if (!ycbcr_support) { - printf("%s Did not find required device extension %s; test skipped.\n", kSkipPrefix, - VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - return; - } - - VkSamplerYcbcrConversion ycbcr_conv = VK_NULL_HANDLE; - VkSamplerYcbcrConversionCreateInfo sycci = {}; - sycci.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO; - sycci.format = VK_FORMAT_UNDEFINED; - sycci.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; - sycci.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkSamplerYcbcrConversionCreateInfo-format-01649"); - vkCreateSamplerYcbcrConversion(dev, &sycci, NULL, &ycbcr_conv); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkPositiveLayerTest, ViewportArray2NV) { - TEST_DESCRIPTION("Test to validate VK_NV_viewport_array2"); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - VkPhysicalDeviceFeatures available_features = {}; - ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&available_features)); - - if (!available_features.multiViewport) { - printf("VkPhysicalDeviceFeatures::multiViewport is not supported, skipping tests\n"); - return; - } - if (!available_features.tessellationShader) { - printf("VkPhysicalDeviceFeatures::tessellationShader is not supported, skipping tests\n"); - return; - } - if (!available_features.geometryShader) { - printf("VkPhysicalDeviceFeatures::geometryShader is not supported, skipping tests\n"); - return; - } - - if (DeviceExtensionSupported(gpu(), nullptr, VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - const char tcs_src[] = R"( - #version 450 - layout(vertices = 3) out; - - void main() { - gl_TessLevelOuter[0] = 4.0f; - gl_TessLevelOuter[1] = 4.0f; - gl_TessLevelOuter[2] = 4.0f; - gl_TessLevelInner[0] = 3.0f; - - gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; - })"; - - const char fs_src[] = R"( - #version 450 - layout(location = 0) out vec4 outColor; - void main() { - outColor = vec4(1.0f); - })"; - - // Create tessellation control and fragment shader here since they will not be - // modified by the different test cases. - VkShaderObj tcs(m_device, tcs_src, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, this); - VkShaderObj fs(m_device, fs_src, VK_SHADER_STAGE_FRAGMENT_BIT, this); - - std::vector<VkViewport> vps = {{0.0f, 0.0f, m_width / 2.0f, m_height}, {m_width / 2.0f, 0.0f, m_width / 2.0f, m_height}}; - std::vector<VkRect2D> scs = { - {{0, 0}, {static_cast<uint32_t>(m_width) / 2, static_cast<uint32_t>(m_height)}}, - {{static_cast<int32_t>(m_width) / 2, 0}, {static_cast<uint32_t>(m_width) / 2, static_cast<uint32_t>(m_height)}}}; - - enum class TestStage { VERTEX = 0, TESSELLATION_EVAL = 1, GEOMETRY = 2 }; - std::array<TestStage, 3> vertex_stages = {{TestStage::VERTEX, TestStage::TESSELLATION_EVAL, TestStage::GEOMETRY}}; - - // Verify that the usage of gl_ViewportMask[] in the allowed vertex processing - // stages does not cause any errors. - for (auto stage : vertex_stages) { - m_errorMonitor->ExpectSuccess(); - - VkPipelineInputAssemblyStateCreateInfo iaci = {VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO}; - iaci.topology = (stage != TestStage::VERTEX) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - - VkPipelineTessellationStateCreateInfo tsci = {VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO}; - tsci.patchControlPoints = 3; - - const VkPipelineLayoutObj pl(m_device); - - VkPipelineObj pipe(m_device); - pipe.AddDefaultColorAttachment(); - pipe.SetInputAssembly(&iaci); - pipe.SetViewport(vps); - pipe.SetScissor(scs); - pipe.AddShader(&fs); - - std::stringstream vs_src, tes_src, geom_src; - - vs_src << R"( - #version 450 - #extension GL_NV_viewport_array2 : require - - vec2 positions[3] = { vec2( 0.0f, -0.5f), - vec2( 0.5f, 0.5f), - vec2(-0.5f, 0.5f) - }; - void main() {)"; - // Write viewportMask if the vertex shader is the last vertex processing stage. - if (stage == TestStage::VERTEX) { - vs_src << "gl_ViewportMask[0] = 3;\n"; - } - vs_src << R"( - gl_Position = vec4(positions[gl_VertexIndex % 3], 0.0, 1.0); - })"; - - VkShaderObj vs(m_device, vs_src.str().c_str(), VK_SHADER_STAGE_VERTEX_BIT, this); - pipe.AddShader(&vs); - - std::unique_ptr<VkShaderObj> tes, geom; - - if (stage >= TestStage::TESSELLATION_EVAL) { - tes_src << R"( - #version 450 - #extension GL_NV_viewport_array2 : require - layout(triangles) in; - - void main() { - gl_Position = (gl_in[0].gl_Position * gl_TessCoord.x + - gl_in[1].gl_Position * gl_TessCoord.y + - gl_in[2].gl_Position * gl_TessCoord.z);)"; - // Write viewportMask if the tess eval shader is the last vertex processing stage. - if (stage == TestStage::TESSELLATION_EVAL) { - tes_src << "gl_ViewportMask[0] = 3;\n"; - } - tes_src << "}"; - - tes = std::unique_ptr<VkShaderObj>( - new VkShaderObj(m_device, tes_src.str().c_str(), VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, this)); - pipe.AddShader(tes.get()); - pipe.AddShader(&tcs); - pipe.SetTessellation(&tsci); - } - - if (stage >= TestStage::GEOMETRY) { - geom_src << R"( - #version 450 - #extension GL_NV_viewport_array2 : require - layout(triangles) in; - layout(triangle_strip, max_vertices = 3) out; - - void main() { - gl_ViewportMask[0] = 3; - for(int i = 0; i < 3; ++i) { - gl_Position = gl_in[i].gl_Position; - EmitVertex(); - } - })"; - - geom = - std::unique_ptr<VkShaderObj>(new VkShaderObj(m_device, geom_src.str().c_str(), VK_SHADER_STAGE_GEOMETRY_BIT, this)); - pipe.AddShader(geom.get()); - } - - pipe.CreateVKPipeline(pl.handle(), renderPass()); - m_errorMonitor->VerifyNotFound(); - } -} - -#ifdef VK_USE_PLATFORM_ANDROID_KHR -#include "android_ndk_types.h" - -TEST_F(VkLayerTest, AndroidHardwareBufferImageCreate) { - TEST_DESCRIPTION("Verify AndroidHardwareBuffer image create info."); - - SetTargetApiVersion(VK_API_VERSION_1_1); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if ((DeviceExtensionSupported(gpu(), nullptr, VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME)) && - // Also skip on devices that advertise AHB, but not the pre-requisite foreign_queue extension - (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME))) { - m_device_extension_names.push_back(VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME); - m_device_extension_names.push_back(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME); - } else { - printf("%s %s extension not supported, skipping tests\n", kSkipPrefix, - VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - VkDevice dev = m_device->device(); - - VkImage img = VK_NULL_HANDLE; - auto reset_img = [&img, dev]() { - if (VK_NULL_HANDLE != img) vkDestroyImage(dev, img, NULL); - img = VK_NULL_HANDLE; - }; - - VkImageCreateInfo ici = {}; - ici.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ici.pNext = nullptr; - ici.imageType = VK_IMAGE_TYPE_2D; - ici.arrayLayers = 1; - ici.extent = {64, 64, 1}; - ici.format = VK_FORMAT_UNDEFINED; - ici.mipLevels = 1; - ici.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - ici.samples = VK_SAMPLE_COUNT_1_BIT; - ici.tiling = VK_IMAGE_TILING_OPTIMAL; - ici.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - - // undefined format - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-pNext-01975"); - m_errorMonitor->SetUnexpectedError("VUID_Undefined"); - vkCreateImage(dev, &ici, NULL, &img); - m_errorMonitor->VerifyFound(); - reset_img(); - - // also undefined format - VkExternalFormatANDROID efa = {}; - efa.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID; - efa.externalFormat = 0; - ici.pNext = &efa; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-pNext-01975"); - vkCreateImage(dev, &ici, NULL, &img); - m_errorMonitor->VerifyFound(); - reset_img(); - - // undefined format with an unknown external format - efa.externalFormat = 0xBADC0DE; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkExternalFormatANDROID-externalFormat-01894"); - vkCreateImage(dev, &ici, NULL, &img); - m_errorMonitor->VerifyFound(); - reset_img(); - - AHardwareBuffer *ahb; - AHardwareBuffer_Desc ahb_desc = {}; - ahb_desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM; - ahb_desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; - ahb_desc.width = 64; - ahb_desc.height = 64; - ahb_desc.layers = 1; - // Allocate an AHardwareBuffer - AHardwareBuffer_allocate(&ahb_desc, &ahb); - - // Retrieve it's properties to make it's external format 'known' (AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM) - VkAndroidHardwareBufferFormatPropertiesANDROID ahb_fmt_props = {}; - ahb_fmt_props.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID; - VkAndroidHardwareBufferPropertiesANDROID ahb_props = {}; - ahb_props.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID; - ahb_props.pNext = &ahb_fmt_props; - PFN_vkGetAndroidHardwareBufferPropertiesANDROID pfn_GetAHBProps = - (PFN_vkGetAndroidHardwareBufferPropertiesANDROID)vkGetDeviceProcAddr(dev, "vkGetAndroidHardwareBufferPropertiesANDROID"); - ASSERT_TRUE(pfn_GetAHBProps != nullptr); - pfn_GetAHBProps(dev, ahb, &ahb_props); - - // a defined image format with a non-zero external format - ici.format = VK_FORMAT_R8G8B8A8_UNORM; - efa.externalFormat = ahb_fmt_props.externalFormat; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-pNext-01974"); - vkCreateImage(dev, &ici, NULL, &img); - m_errorMonitor->VerifyFound(); - reset_img(); - ici.format = VK_FORMAT_UNDEFINED; - - // external format while MUTABLE - ici.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-pNext-02396"); - vkCreateImage(dev, &ici, NULL, &img); - m_errorMonitor->VerifyFound(); - reset_img(); - ici.flags = 0; - - // external format while usage other than SAMPLED - ici.usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-pNext-02397"); - vkCreateImage(dev, &ici, NULL, &img); - m_errorMonitor->VerifyFound(); - reset_img(); - ici.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - - // external format while tiline other than OPTIMAL - ici.tiling = VK_IMAGE_TILING_LINEAR; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-pNext-02398"); - vkCreateImage(dev, &ici, NULL, &img); - m_errorMonitor->VerifyFound(); - reset_img(); - ici.tiling = VK_IMAGE_TILING_OPTIMAL; - - // imageType - VkExternalMemoryImageCreateInfo emici = {}; - emici.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; - emici.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; - ici.pNext = &emici; // remove efa from chain, insert emici - ici.format = VK_FORMAT_R8G8B8A8_UNORM; - ici.imageType = VK_IMAGE_TYPE_3D; - ici.extent = {64, 64, 64}; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-pNext-02393"); - vkCreateImage(dev, &ici, NULL, &img); - m_errorMonitor->VerifyFound(); - reset_img(); - - // wrong mipLevels - ici.imageType = VK_IMAGE_TYPE_2D; - ici.extent = {64, 64, 1}; - ici.mipLevels = 6; // should be 7 - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-pNext-02394"); - vkCreateImage(dev, &ici, NULL, &img); - m_errorMonitor->VerifyFound(); - reset_img(); -} - -TEST_F(VkLayerTest, AndroidHardwareBufferFetchUnboundImageInfo) { - TEST_DESCRIPTION("Verify AndroidHardwareBuffer retreive image properties while memory unbound."); - - SetTargetApiVersion(VK_API_VERSION_1_1); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if ((DeviceExtensionSupported(gpu(), nullptr, VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME)) && - // Also skip on devices that advertise AHB, but not the pre-requisite foreign_queue extension - (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME))) { - m_device_extension_names.push_back(VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME); - m_device_extension_names.push_back(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME); - } else { - printf("%s %s extension not supported, skipping tests\n", kSkipPrefix, - VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - VkDevice dev = m_device->device(); - - VkImage img = VK_NULL_HANDLE; - auto reset_img = [&img, dev]() { - if (VK_NULL_HANDLE != img) vkDestroyImage(dev, img, NULL); - img = VK_NULL_HANDLE; - }; - - VkImageCreateInfo ici = {}; - ici.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ici.pNext = nullptr; - ici.imageType = VK_IMAGE_TYPE_2D; - ici.arrayLayers = 1; - ici.extent = {64, 64, 1}; - ici.format = VK_FORMAT_R8G8B8A8_UNORM; - ici.mipLevels = 1; - ici.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - ici.samples = VK_SAMPLE_COUNT_1_BIT; - ici.tiling = VK_IMAGE_TILING_LINEAR; - ici.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - - VkExternalMemoryImageCreateInfo emici = {}; - emici.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; - emici.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; - ici.pNext = &emici; - - m_errorMonitor->ExpectSuccess(); - vkCreateImage(dev, &ici, NULL, &img); - m_errorMonitor->VerifyNotFound(); - - // attempt to fetch layout from unbound image - VkImageSubresource sub_rsrc = {}; - sub_rsrc.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - VkSubresourceLayout sub_layout = {}; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkGetImageSubresourceLayout-image-01895"); - vkGetImageSubresourceLayout(dev, img, &sub_rsrc, &sub_layout); - m_errorMonitor->VerifyFound(); - - // attempt to get memory reqs from unbound image - VkImageMemoryRequirementsInfo2 imri = {}; - imri.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2; - imri.image = img; - VkMemoryRequirements2 mem_reqs = {}; - mem_reqs.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryRequirementsInfo2-image-01897"); - vkGetImageMemoryRequirements2(dev, &imri, &mem_reqs); - m_errorMonitor->VerifyFound(); - - reset_img(); -} - -TEST_F(VkLayerTest, AndroidHardwareBufferMemoryAllocation) { - TEST_DESCRIPTION("Verify AndroidHardwareBuffer memory allocation."); - - SetTargetApiVersion(VK_API_VERSION_1_1); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if ((DeviceExtensionSupported(gpu(), nullptr, VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME)) && - // Also skip on devices that advertise AHB, but not the pre-requisite foreign_queue extension - (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME))) { - m_device_extension_names.push_back(VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME); - m_device_extension_names.push_back(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME); - } else { - printf("%s %s extension not supported, skipping tests\n", kSkipPrefix, - VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - VkDevice dev = m_device->device(); - - VkImage img = VK_NULL_HANDLE; - auto reset_img = [&img, dev]() { - if (VK_NULL_HANDLE != img) vkDestroyImage(dev, img, NULL); - img = VK_NULL_HANDLE; - }; - VkDeviceMemory mem_handle = VK_NULL_HANDLE; - auto reset_mem = [&mem_handle, dev]() { - if (VK_NULL_HANDLE != mem_handle) vkFreeMemory(dev, mem_handle, NULL); - mem_handle = VK_NULL_HANDLE; - }; - - PFN_vkGetAndroidHardwareBufferPropertiesANDROID pfn_GetAHBProps = - (PFN_vkGetAndroidHardwareBufferPropertiesANDROID)vkGetDeviceProcAddr(dev, "vkGetAndroidHardwareBufferPropertiesANDROID"); - ASSERT_TRUE(pfn_GetAHBProps != nullptr); - - // AHB structs - AHardwareBuffer *ahb = nullptr; - AHardwareBuffer_Desc ahb_desc = {}; - VkAndroidHardwareBufferFormatPropertiesANDROID ahb_fmt_props = {}; - ahb_fmt_props.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID; - VkAndroidHardwareBufferPropertiesANDROID ahb_props = {}; - ahb_props.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID; - ahb_props.pNext = &ahb_fmt_props; - VkImportAndroidHardwareBufferInfoANDROID iahbi = {}; - iahbi.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID; - - // destroy and re-acquire an AHB, and fetch it's properties - auto recreate_ahb = [&ahb, &iahbi, &ahb_desc, &ahb_props, dev, pfn_GetAHBProps]() { - if (ahb) AHardwareBuffer_release(ahb); - ahb = nullptr; - AHardwareBuffer_allocate(&ahb_desc, &ahb); - if (ahb) { - pfn_GetAHBProps(dev, ahb, &ahb_props); - iahbi.buffer = ahb; - } - }; - - // Allocate an AHardwareBuffer - ahb_desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM; - ahb_desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; - ahb_desc.width = 64; - ahb_desc.height = 64; - ahb_desc.layers = 1; - recreate_ahb(); - - // Create an image w/ external format - VkExternalFormatANDROID efa = {}; - efa.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID; - efa.externalFormat = ahb_fmt_props.externalFormat; - - VkImageCreateInfo ici = {}; - ici.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ici.pNext = &efa; - ici.imageType = VK_IMAGE_TYPE_2D; - ici.arrayLayers = 1; - ici.extent = {64, 64, 1}; - ici.format = VK_FORMAT_UNDEFINED; - ici.mipLevels = 1; - ici.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - ici.samples = VK_SAMPLE_COUNT_1_BIT; - ici.tiling = VK_IMAGE_TILING_OPTIMAL; - ici.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - VkResult res = vkCreateImage(dev, &ici, NULL, &img); - ASSERT_VK_SUCCESS(res); - - VkMemoryAllocateInfo mai = {}; - mai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mai.pNext = &iahbi; // Chained import struct - mai.allocationSize = ahb_props.allocationSize; - mai.memoryTypeIndex = 32; - // Set index to match one of the bits in ahb_props - for (int i = 0; i < 32; i++) { - if (ahb_props.memoryTypeBits & (1 << i)) { - mai.memoryTypeIndex = i; - break; - } - } - ASSERT_NE(32, mai.memoryTypeIndex); - - // Import w/ non-dedicated memory allocation - - // Import requires format AHB_FMT_BLOB and usage AHB_USAGE_GPU_DATA_BUFFER - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMemoryAllocateInfo-pNext-02384"); - vkAllocateMemory(dev, &mai, NULL, &mem_handle); - m_errorMonitor->VerifyFound(); - reset_mem(); - - // Allocation size mismatch - ahb_desc.format = AHARDWAREBUFFER_FORMAT_BLOB; - ahb_desc.usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER; - ahb_desc.height = 1; - recreate_ahb(); - mai.allocationSize = ahb_props.allocationSize + 1; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMemoryAllocateInfo-allocationSize-02383"); - vkAllocateMemory(dev, &mai, NULL, &mem_handle); - m_errorMonitor->VerifyFound(); - mai.allocationSize = ahb_props.allocationSize; - reset_mem(); - - // memoryTypeIndex mismatch - mai.memoryTypeIndex++; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMemoryAllocateInfo-memoryTypeIndex-02385"); - vkAllocateMemory(dev, &mai, NULL, &mem_handle); - m_errorMonitor->VerifyFound(); - mai.memoryTypeIndex--; - reset_mem(); - - // Insert dedicated image memory allocation to mai chain - VkMemoryDedicatedAllocateInfo mdai = {}; - mdai.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO; - mdai.image = img; - mdai.buffer = VK_NULL_HANDLE; - mdai.pNext = mai.pNext; - mai.pNext = &mdai; - - // Dedicated allocation with unmatched usage bits - ahb_desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; - ahb_desc.usage = AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT; - ahb_desc.height = 64; - recreate_ahb(); - mai.allocationSize = ahb_props.allocationSize; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMemoryAllocateInfo-pNext-02390"); - vkAllocateMemory(dev, &mai, NULL, &mem_handle); - m_errorMonitor->VerifyFound(); - reset_mem(); - - // Dedicated allocation with incomplete mip chain - reset_img(); - ici.mipLevels = 2; - vkCreateImage(dev, &ici, NULL, &img); - mdai.image = img; - ahb_desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE; - recreate_ahb(); - - if (ahb) { - mai.allocationSize = ahb_props.allocationSize; - for (int i = 0; i < 32; i++) { - if (ahb_props.memoryTypeBits & (1 << i)) { - mai.memoryTypeIndex = i; - break; - } - } - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMemoryAllocateInfo-pNext-02389"); - vkAllocateMemory(dev, &mai, NULL, &mem_handle); - m_errorMonitor->VerifyFound(); - reset_mem(); - } else { - // ERROR: AHardwareBuffer_allocate() with MIPMAP_COMPLETE fails. It returns -12, NO_MEMORY. - // The problem seems to happen in Pixel 2, not Pixel 3. - printf("%s AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE not supported, skipping tests\n", kSkipPrefix); - } - - // Dedicated allocation with mis-matched dimension - ahb_desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; - ahb_desc.height = 32; - ahb_desc.width = 128; - recreate_ahb(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMemoryAllocateInfo-pNext-02388"); - vkAllocateMemory(dev, &mai, NULL, &mem_handle); - m_errorMonitor->VerifyFound(); - reset_mem(); - - // Dedicated allocation with mis-matched VkFormat - ahb_desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; - ahb_desc.height = 64; - ahb_desc.width = 64; - recreate_ahb(); - ici.mipLevels = 1; - ici.format = VK_FORMAT_B8G8R8A8_UNORM; - ici.pNext = NULL; - VkImage img2; - vkCreateImage(dev, &ici, NULL, &img2); - mdai.image = img2; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMemoryAllocateInfo-pNext-02387"); - vkAllocateMemory(dev, &mai, NULL, &mem_handle); - m_errorMonitor->VerifyFound(); - vkDestroyImage(dev, img2, NULL); - mdai.image = img; - reset_mem(); - - // Missing required ahb usage - ahb_desc.usage = AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkGetAndroidHardwareBufferPropertiesANDROID-buffer-01884"); - recreate_ahb(); - m_errorMonitor->VerifyFound(); - - // Dedicated allocation with missing usage bits - // Setting up this test also triggers a slew of others - mai.allocationSize = ahb_props.allocationSize + 1; - mai.memoryTypeIndex = 0; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMemoryAllocateInfo-pNext-02390"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMemoryAllocateInfo-memoryTypeIndex-02385"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMemoryAllocateInfo-allocationSize-02383"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMemoryAllocateInfo-pNext-02386"); - vkAllocateMemory(dev, &mai, NULL, &mem_handle); - m_errorMonitor->VerifyFound(); - reset_mem(); - - // Non-import allocation - replace import struct in chain with export struct - VkExportMemoryAllocateInfo emai = {}; - emai.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO; - emai.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; - mai.pNext = &emai; - emai.pNext = &mdai; // still dedicated - mdai.pNext = nullptr; - - // Export with allocation size non-zero - ahb_desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; - recreate_ahb(); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMemoryAllocateInfo-pNext-01874"); - vkAllocateMemory(dev, &mai, NULL, &mem_handle); - m_errorMonitor->VerifyFound(); - reset_mem(); - - AHardwareBuffer_release(ahb); - reset_mem(); - reset_img(); -} - -TEST_F(VkLayerTest, AndroidHardwareBufferCreateYCbCrSampler) { - TEST_DESCRIPTION("Verify AndroidHardwareBuffer YCbCr sampler creation."); - - SetTargetApiVersion(VK_API_VERSION_1_1); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if ((DeviceExtensionSupported(gpu(), nullptr, VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME)) && - // Also skip on devices that advertise AHB, but not the pre-requisite foreign_queue extension - (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME))) { - m_device_extension_names.push_back(VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME); - m_device_extension_names.push_back(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME); - } else { - printf("%s %s extension not supported, skipping tests\n", kSkipPrefix, - VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - VkDevice dev = m_device->device(); - - VkSamplerYcbcrConversion ycbcr_conv = VK_NULL_HANDLE; - VkSamplerYcbcrConversionCreateInfo sycci = {}; - sycci.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO; - sycci.format = VK_FORMAT_UNDEFINED; - sycci.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; - sycci.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkSamplerYcbcrConversionCreateInfo-format-01904"); - vkCreateSamplerYcbcrConversion(dev, &sycci, NULL, &ycbcr_conv); - m_errorMonitor->VerifyFound(); - - VkExternalFormatANDROID efa = {}; - efa.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID; - efa.externalFormat = AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM; - sycci.format = VK_FORMAT_R8G8B8A8_UNORM; - sycci.pNext = &efa; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkSamplerYcbcrConversionCreateInfo-format-01904"); - vkCreateSamplerYcbcrConversion(dev, &sycci, NULL, &ycbcr_conv); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, AndroidHardwareBufferPhysDevImageFormatProp2) { - TEST_DESCRIPTION("Verify AndroidHardwareBuffer GetPhysicalDeviceImageFormatProperties."); - - SetTargetApiVersion(VK_API_VERSION_1_1); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if ((DeviceExtensionSupported(gpu(), nullptr, VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME)) && - // Also skip on devices that advertise AHB, but not the pre-requisite foreign_queue extension - (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME))) { - m_device_extension_names.push_back(VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME); - m_device_extension_names.push_back(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME); - } else { - printf("%s %s extension not supported, skipping test\n", kSkipPrefix, - VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - - if ((m_instance_api_version < VK_API_VERSION_1_1) && - !InstanceExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - printf("%s %s extension not supported, skipping test\n", kSkipPrefix, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - return; - } - - VkImageFormatProperties2 ifp = {}; - ifp.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2; - VkPhysicalDeviceImageFormatInfo2 pdifi = {}; - pdifi.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2; - pdifi.format = VK_FORMAT_R8G8B8A8_UNORM; - pdifi.tiling = VK_IMAGE_TILING_OPTIMAL; - pdifi.type = VK_IMAGE_TYPE_2D; - pdifi.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - VkAndroidHardwareBufferUsageANDROID ahbu = {}; - ahbu.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID; - ahbu.androidHardwareBufferUsage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; - ifp.pNext = &ahbu; - - // AHB_usage chained to input without a matching external image format struc chained to output - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkGetPhysicalDeviceImageFormatProperties2-pNext-01868"); - vkGetPhysicalDeviceImageFormatProperties2(m_device->phy().handle(), &pdifi, &ifp); - m_errorMonitor->VerifyFound(); - - // output struct chained, but does not include VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID usage - VkPhysicalDeviceExternalImageFormatInfo pdeifi = {}; - pdeifi.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO; - pdeifi.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; - pdifi.pNext = &pdeifi; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-vkGetPhysicalDeviceImageFormatProperties2-pNext-01868"); - vkGetPhysicalDeviceImageFormatProperties2(m_device->phy().handle(), &pdifi, &ifp); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, AndroidHardwareBufferCreateImageView) { - TEST_DESCRIPTION("Verify AndroidHardwareBuffer image view creation."); - - SetTargetApiVersion(VK_API_VERSION_1_1); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if ((DeviceExtensionSupported(gpu(), nullptr, VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME)) && - // Also skip on devices that advertise AHB, but not the pre-requisite foreign_queue extension - (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME))) { - m_device_extension_names.push_back(VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME); - m_device_extension_names.push_back(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME); - } else { - printf("%s %s extension not supported, skipping tests\n", kSkipPrefix, - VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - VkDevice dev = m_device->device(); - - // Allocate an AHB and fetch its properties - AHardwareBuffer *ahb = nullptr; - AHardwareBuffer_Desc ahb_desc = {}; - ahb_desc.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM; - ahb_desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; - ahb_desc.width = 64; - ahb_desc.height = 64; - ahb_desc.layers = 1; - AHardwareBuffer_allocate(&ahb_desc, &ahb); - - // Retrieve AHB properties to make it's external format 'known' - VkAndroidHardwareBufferFormatPropertiesANDROID ahb_fmt_props = {}; - ahb_fmt_props.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID; - VkAndroidHardwareBufferPropertiesANDROID ahb_props = {}; - ahb_props.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID; - ahb_props.pNext = &ahb_fmt_props; - PFN_vkGetAndroidHardwareBufferPropertiesANDROID pfn_GetAHBProps = - (PFN_vkGetAndroidHardwareBufferPropertiesANDROID)vkGetDeviceProcAddr(dev, "vkGetAndroidHardwareBufferPropertiesANDROID"); - ASSERT_TRUE(pfn_GetAHBProps != nullptr); - pfn_GetAHBProps(dev, ahb, &ahb_props); - AHardwareBuffer_release(ahb); - - // Give image an external format - VkExternalFormatANDROID efa = {}; - efa.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID; - efa.externalFormat = ahb_fmt_props.externalFormat; - - ahb_desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; - ahb_desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; - ahb_desc.width = 64; - ahb_desc.height = 1; - ahb_desc.layers = 1; - AHardwareBuffer_allocate(&ahb_desc, &ahb); - - // Create another VkExternalFormatANDROID for test VUID-VkImageViewCreateInfo-image-02400 - VkAndroidHardwareBufferFormatPropertiesANDROID ahb_fmt_props_Ycbcr = {}; - ahb_fmt_props_Ycbcr.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID; - VkAndroidHardwareBufferPropertiesANDROID ahb_props_Ycbcr = {}; - ahb_props_Ycbcr.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID; - ahb_props_Ycbcr.pNext = &ahb_fmt_props_Ycbcr; - pfn_GetAHBProps(dev, ahb, &ahb_props_Ycbcr); - AHardwareBuffer_release(ahb); - - VkExternalFormatANDROID efa_Ycbcr = {}; - efa_Ycbcr.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID; - efa_Ycbcr.externalFormat = ahb_fmt_props_Ycbcr.externalFormat; - - // Create the image - VkImage img = VK_NULL_HANDLE; - VkImageCreateInfo ici = {}; - ici.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ici.pNext = &efa; - ici.imageType = VK_IMAGE_TYPE_2D; - ici.arrayLayers = 1; - ici.extent = {64, 64, 1}; - ici.format = VK_FORMAT_UNDEFINED; - ici.mipLevels = 1; - ici.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - ici.samples = VK_SAMPLE_COUNT_1_BIT; - ici.tiling = VK_IMAGE_TILING_OPTIMAL; - ici.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - vkCreateImage(dev, &ici, NULL, &img); - - // Set up memory allocation - VkDeviceMemory img_mem = VK_NULL_HANDLE; - VkMemoryAllocateInfo mai = {}; - mai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mai.allocationSize = 64 * 64 * 4; - mai.memoryTypeIndex = 0; - vkAllocateMemory(dev, &mai, NULL, &img_mem); - - // It shouldn't use vkGetImageMemoryRequirements for AndroidHardwareBuffer. - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "UNASSIGNED-CoreValidation-DrawState-InvalidImage"); - VkMemoryRequirements img_mem_reqs = {}; - vkGetImageMemoryRequirements(m_device->device(), img, &img_mem_reqs); - vkBindImageMemory(dev, img, img_mem, 0); - m_errorMonitor->VerifyFound(); - - // Bind image to memory - vkDestroyImage(dev, img, NULL); - vkFreeMemory(dev, img_mem, NULL); - vkCreateImage(dev, &ici, NULL, &img); - vkAllocateMemory(dev, &mai, NULL, &img_mem); - vkBindImageMemory(dev, img, img_mem, 0); - - // Create a YCbCr conversion, with different external format, chain to view - VkSamplerYcbcrConversion ycbcr_conv = VK_NULL_HANDLE; - VkSamplerYcbcrConversionCreateInfo sycci = {}; - sycci.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO; - sycci.pNext = &efa_Ycbcr; - sycci.format = VK_FORMAT_UNDEFINED; - sycci.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; - sycci.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; - vkCreateSamplerYcbcrConversion(dev, &sycci, NULL, &ycbcr_conv); - VkSamplerYcbcrConversionInfo syci = {}; - syci.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO; - syci.conversion = ycbcr_conv; - - // Create a view - VkImageView image_view = VK_NULL_HANDLE; - VkImageViewCreateInfo ivci = {}; - ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - ivci.pNext = &syci; - ivci.image = img; - ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.format = VK_FORMAT_UNDEFINED; - ivci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - - auto reset_view = [&image_view, dev]() { - if (VK_NULL_HANDLE != image_view) vkDestroyImageView(dev, image_view, NULL); - image_view = VK_NULL_HANDLE; - }; - - // Up to this point, no errors expected - m_errorMonitor->VerifyNotFound(); - - // Chained ycbcr conversion has different (external) format than image - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-image-02400"); - // Also causes "unsupported format" - should be removed in future spec update - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-None-02273"); - vkCreateImageView(dev, &ivci, NULL, &image_view); - m_errorMonitor->VerifyFound(); - - reset_view(); - vkDestroySamplerYcbcrConversion(dev, ycbcr_conv, NULL); - sycci.pNext = &efa; - vkCreateSamplerYcbcrConversion(dev, &sycci, NULL, &ycbcr_conv); - syci.conversion = ycbcr_conv; - - // View component swizzle not IDENTITY - ivci.components.r = VK_COMPONENT_SWIZZLE_B; - ivci.components.b = VK_COMPONENT_SWIZZLE_R; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-image-02401"); - // Also causes "unsupported format" - should be removed in future spec update - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-None-02273"); - vkCreateImageView(dev, &ivci, NULL, &image_view); - m_errorMonitor->VerifyFound(); - - reset_view(); - ivci.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - ivci.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - - // View with external format, when format is not UNDEFINED - ivci.format = VK_FORMAT_R5G6B5_UNORM_PACK16; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-image-02399"); - // Also causes "view format different from image format" - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-image-01019"); - vkCreateImageView(dev, &ivci, NULL, &image_view); - m_errorMonitor->VerifyFound(); - - reset_view(); - vkDestroySamplerYcbcrConversion(dev, ycbcr_conv, NULL); - vkDestroyImageView(dev, image_view, NULL); - vkDestroyImage(dev, img, NULL); - vkFreeMemory(dev, img_mem, NULL); -} - -TEST_F(VkLayerTest, AndroidHardwareBufferImportBuffer) { - TEST_DESCRIPTION("Verify AndroidHardwareBuffer import as buffer."); - - SetTargetApiVersion(VK_API_VERSION_1_1); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if ((DeviceExtensionSupported(gpu(), nullptr, VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME)) && - // Also skip on devices that advertise AHB, but not the pre-requisite foreign_queue extension - (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME))) { - m_device_extension_names.push_back(VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME); - m_device_extension_names.push_back(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME); - } else { - printf("%s %s extension not supported, skipping tests\n", kSkipPrefix, - VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - VkDevice dev = m_device->device(); - - VkDeviceMemory mem_handle = VK_NULL_HANDLE; - auto reset_mem = [&mem_handle, dev]() { - if (VK_NULL_HANDLE != mem_handle) vkFreeMemory(dev, mem_handle, NULL); - mem_handle = VK_NULL_HANDLE; - }; - - PFN_vkGetAndroidHardwareBufferPropertiesANDROID pfn_GetAHBProps = - (PFN_vkGetAndroidHardwareBufferPropertiesANDROID)vkGetDeviceProcAddr(dev, "vkGetAndroidHardwareBufferPropertiesANDROID"); - ASSERT_TRUE(pfn_GetAHBProps != nullptr); - - // AHB structs - AHardwareBuffer *ahb = nullptr; - AHardwareBuffer_Desc ahb_desc = {}; - VkAndroidHardwareBufferPropertiesANDROID ahb_props = {}; - ahb_props.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID; - VkImportAndroidHardwareBufferInfoANDROID iahbi = {}; - iahbi.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID; - - // Allocate an AHardwareBuffer - ahb_desc.format = AHARDWAREBUFFER_FORMAT_BLOB; - ahb_desc.usage = AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA; - ahb_desc.width = 512; - ahb_desc.height = 1; - ahb_desc.layers = 1; - AHardwareBuffer_allocate(&ahb_desc, &ahb); - m_errorMonitor->SetUnexpectedError("VUID-vkGetAndroidHardwareBufferPropertiesANDROID-buffer-01884"); - pfn_GetAHBProps(dev, ahb, &ahb_props); - iahbi.buffer = ahb; - - // Create export and import buffers - VkExternalMemoryBufferCreateInfo ext_buf_info = {}; - ext_buf_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR; - ext_buf_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; - - VkBufferCreateInfo bci = {}; - bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bci.pNext = &ext_buf_info; - bci.size = ahb_props.allocationSize; - bci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - - VkBuffer buf = VK_NULL_HANDLE; - vkCreateBuffer(dev, &bci, NULL, &buf); - VkMemoryRequirements mem_reqs; - vkGetBufferMemoryRequirements(dev, buf, &mem_reqs); - - // Allocation info - VkMemoryAllocateInfo mai = vk_testing::DeviceMemory::get_resource_alloc_info(*m_device, mem_reqs, 0); - mai.pNext = &iahbi; // Chained import struct - VkPhysicalDeviceMemoryProperties memory_info; - vkGetPhysicalDeviceMemoryProperties(gpu(), &memory_info); - unsigned int i; - for (i = 0; i < memory_info.memoryTypeCount; i++) { - if ((ahb_props.memoryTypeBits & (1 << i))) { - mai.memoryTypeIndex = i; - break; - } - } - if (i >= memory_info.memoryTypeCount) { - printf("%s No invalid memory type index could be found; skipped.\n", kSkipPrefix); - AHardwareBuffer_release(ahb); - reset_mem(); - vkDestroyBuffer(dev, buf, NULL); - return; - } - - // Import as buffer requires format AHB_FMT_BLOB and usage AHB_USAGE_GPU_DATA_BUFFER - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkImportAndroidHardwareBufferInfoANDROID-buffer-01881"); - // Also causes "non-dedicated allocation format/usage" error - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkMemoryAllocateInfo-pNext-02384"); - vkAllocateMemory(dev, &mai, NULL, &mem_handle); - m_errorMonitor->VerifyFound(); - - AHardwareBuffer_release(ahb); - reset_mem(); - vkDestroyBuffer(dev, buf, NULL); -} - -TEST_F(VkLayerTest, AndroidHardwareBufferExporttBuffer) { - TEST_DESCRIPTION("Verify AndroidHardwareBuffer export memory as AHB."); - - SetTargetApiVersion(VK_API_VERSION_1_1); - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if ((DeviceExtensionSupported(gpu(), nullptr, VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME)) && - // Also skip on devices that advertise AHB, but not the pre-requisite foreign_queue extension - (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME))) { - m_device_extension_names.push_back(VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME); - m_device_extension_names.push_back(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME); - } else { - printf("%s %s extension not supported, skipping tests\n", kSkipPrefix, - VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - VkDevice dev = m_device->device(); - - VkDeviceMemory mem_handle = VK_NULL_HANDLE; - - // Allocate device memory, no linked export struct indicating AHB handle type - VkMemoryAllocateInfo mai = {}; - mai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mai.allocationSize = 65536; - mai.memoryTypeIndex = 0; - vkAllocateMemory(dev, &mai, NULL, &mem_handle); - - PFN_vkGetMemoryAndroidHardwareBufferANDROID pfn_GetMemAHB = - (PFN_vkGetMemoryAndroidHardwareBufferANDROID)vkGetDeviceProcAddr(dev, "vkGetMemoryAndroidHardwareBufferANDROID"); - ASSERT_TRUE(pfn_GetMemAHB != nullptr); - - VkMemoryGetAndroidHardwareBufferInfoANDROID mgahbi = {}; - mgahbi.sType = VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID; - mgahbi.memory = mem_handle; - AHardwareBuffer *ahb = nullptr; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkMemoryGetAndroidHardwareBufferInfoANDROID-handleTypes-01882"); - pfn_GetMemAHB(dev, &mgahbi, &ahb); - m_errorMonitor->VerifyFound(); - - if (ahb) AHardwareBuffer_release(ahb); - ahb = nullptr; - if (VK_NULL_HANDLE != mem_handle) vkFreeMemory(dev, mem_handle, NULL); - mem_handle = VK_NULL_HANDLE; - - // Add an export struct with AHB handle type to allocation info - VkExportMemoryAllocateInfo emai = {}; - emai.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO; - emai.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; - mai.pNext = &emai; - - // Create an image, do not bind memory - VkImage img = VK_NULL_HANDLE; - VkImageCreateInfo ici = {}; - ici.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ici.imageType = VK_IMAGE_TYPE_2D; - ici.arrayLayers = 1; - ici.extent = {128, 128, 1}; - ici.format = VK_FORMAT_R8G8B8A8_UNORM; - ici.mipLevels = 1; - ici.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - ici.samples = VK_SAMPLE_COUNT_1_BIT; - ici.tiling = VK_IMAGE_TILING_OPTIMAL; - ici.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - vkCreateImage(dev, &ici, NULL, &img); - ASSERT_TRUE(VK_NULL_HANDLE != img); - - // Add image to allocation chain as dedicated info, re-allocate - VkMemoryDedicatedAllocateInfo mdai = {VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO}; - mdai.image = img; - emai.pNext = &mdai; - mai.allocationSize = 0; - vkAllocateMemory(dev, &mai, NULL, &mem_handle); - mgahbi.memory = mem_handle; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkMemoryGetAndroidHardwareBufferInfoANDROID-pNext-01883"); - pfn_GetMemAHB(dev, &mgahbi, &ahb); - m_errorMonitor->VerifyFound(); - - if (ahb) AHardwareBuffer_release(ahb); - if (VK_NULL_HANDLE != mem_handle) vkFreeMemory(dev, mem_handle, NULL); - vkDestroyImage(dev, img, NULL); -} - -#endif // VK_USE_PLATFORM_ANDROID_KHR - -TEST_F(VkLayerTest, ViewportSwizzleNV) { - TEST_DESCRIPTION("Verify VK_NV_viewprot_swizzle."); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if (DeviceExtensionSupported(gpu(), nullptr, VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkViewportSwizzleNV invalid_swizzles = { - VkViewportCoordinateSwizzleNV(-1), - VkViewportCoordinateSwizzleNV(-1), - VkViewportCoordinateSwizzleNV(-1), - VkViewportCoordinateSwizzleNV(-1), - }; - - VkPipelineViewportSwizzleStateCreateInfoNV vp_swizzle_state = { - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV}; - vp_swizzle_state.viewportCount = 1; - vp_swizzle_state.pViewportSwizzles = &invalid_swizzles; - - const std::vector<std::string> expected_vuids = {"VUID-VkViewportSwizzleNV-x-parameter", "VUID-VkViewportSwizzleNV-y-parameter", - "VUID-VkViewportSwizzleNV-z-parameter", - "VUID-VkViewportSwizzleNV-w-parameter"}; - - auto break_swizzles = [&vp_swizzle_state](CreatePipelineHelper &helper) { helper.vp_state_ci_.pNext = &vp_swizzle_state; }; - - CreatePipelineHelper::OneshotTest(*this, break_swizzles, VK_DEBUG_REPORT_ERROR_BIT_EXT, expected_vuids); - - struct TestCase { - VkBool32 rasterizerDiscardEnable; - uint32_t vp_count; - uint32_t swizzel_vp_count; - bool positive; - }; - - const std::array<TestCase, 3> test_cases = {{{VK_TRUE, 1, 2, true}, {VK_FALSE, 1, 1, true}, {VK_FALSE, 1, 2, false}}}; - - std::array<VkViewportSwizzleNV, 2> swizzles = { - {{VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV, VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV, - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV, VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV}, - {VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV, VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV, - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV, VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV}}}; - - for (const auto &test_case : test_cases) { - assert(test_case.vp_count <= swizzles.size()); - - vp_swizzle_state.viewportCount = test_case.swizzel_vp_count; - vp_swizzle_state.pViewportSwizzles = swizzles.data(); - - auto break_vp_count = [&vp_swizzle_state, &test_case](CreatePipelineHelper &helper) { - helper.rs_state_ci_.rasterizerDiscardEnable = test_case.rasterizerDiscardEnable; - helper.vp_state_ci_.viewportCount = test_case.vp_count; - - helper.vp_state_ci_.pNext = &vp_swizzle_state; - }; - - CreatePipelineHelper::OneshotTest(*this, break_vp_count, VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineViewportSwizzleStateCreateInfoNV-viewportCount-01215", - test_case.positive); - } -} - -TEST_F(VkLayerTest, BufferDeviceAddressEXT) { - TEST_DESCRIPTION("Test VK_EXT_buffer_device_address."); - - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - std::array<const char *, 1> required_device_extensions = {{VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME}}; - for (auto device_extension : required_device_extensions) { - if (DeviceExtensionSupported(gpu(), nullptr, device_extension)) { - m_device_extension_names.push_back(device_extension); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension); - return; - } - } - - if (DeviceIsMockICD() || DeviceSimulation()) { - printf("%s MockICD does not support this feature, skipping tests\n", kSkipPrefix); - return; - } - - PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = - (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR"); - ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr); - - // Create a device that enables buffer_device_address - auto buffer_device_address_features = lvl_init_struct<VkPhysicalDeviceBufferAddressFeaturesEXT>(); - auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&buffer_device_address_features); - vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2); - buffer_device_address_features.bufferDeviceAddressCaptureReplay = VK_FALSE; - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - PFN_vkGetBufferDeviceAddressEXT vkGetBufferDeviceAddressEXT = - (PFN_vkGetBufferDeviceAddressEXT)vkGetInstanceProcAddr(instance(), "vkGetBufferDeviceAddressEXT"); - - VkBufferCreateInfo buffer_create_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; - buffer_create_info.size = sizeof(uint32_t); - buffer_create_info.usage = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT; - buffer_create_info.flags = VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_EXT; - VkBuffer buffer; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferCreateInfo-flags-02605"); - VkResult result = vkCreateBuffer(m_device->device(), &buffer_create_info, nullptr, &buffer); - m_errorMonitor->VerifyFound(); - if (result == VK_SUCCESS) { - vkDestroyBuffer(m_device->device(), buffer, NULL); - } - - buffer_create_info.flags = 0; - VkBufferDeviceAddressCreateInfoEXT addr_ci = {VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT}; - addr_ci.deviceAddress = 1; - buffer_create_info.pNext = &addr_ci; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferCreateInfo-deviceAddress-02604"); - result = vkCreateBuffer(m_device->device(), &buffer_create_info, nullptr, &buffer); - m_errorMonitor->VerifyFound(); - if (result == VK_SUCCESS) { - vkDestroyBuffer(m_device->device(), buffer, NULL); - } - - buffer_create_info.pNext = nullptr; - result = vkCreateBuffer(m_device->device(), &buffer_create_info, nullptr, &buffer); - ASSERT_VK_SUCCESS(result); - - VkBufferDeviceAddressInfoEXT info = {VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_EXT}; - info.buffer = buffer; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferDeviceAddressInfoEXT-buffer-02600"); - vkGetBufferDeviceAddressEXT(m_device->device(), &info); - m_errorMonitor->VerifyFound(); - - vkDestroyBuffer(m_device->device(), buffer, NULL); -} - -TEST_F(VkLayerTest, BufferDeviceAddressEXTDisabled) { - TEST_DESCRIPTION("Test VK_EXT_buffer_device_address."); - - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - std::array<const char *, 1> required_device_extensions = {{VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME}}; - for (auto device_extension : required_device_extensions) { - if (DeviceExtensionSupported(gpu(), nullptr, device_extension)) { - m_device_extension_names.push_back(device_extension); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension); - return; - } - } - - if (DeviceIsMockICD() || DeviceSimulation()) { - printf("%s MockICD does not support this feature, skipping tests\n", kSkipPrefix); - return; - } - - PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = - (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR"); - ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr); - - // Create a device that disables buffer_device_address - auto buffer_device_address_features = lvl_init_struct<VkPhysicalDeviceBufferAddressFeaturesEXT>(); - auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&buffer_device_address_features); - vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2); - buffer_device_address_features.bufferDeviceAddress = VK_FALSE; - buffer_device_address_features.bufferDeviceAddressCaptureReplay = VK_FALSE; - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - PFN_vkGetBufferDeviceAddressEXT vkGetBufferDeviceAddressEXT = - (PFN_vkGetBufferDeviceAddressEXT)vkGetInstanceProcAddr(instance(), "vkGetBufferDeviceAddressEXT"); - - VkBufferCreateInfo buffer_create_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; - buffer_create_info.size = sizeof(uint32_t); - buffer_create_info.usage = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT; - VkBuffer buffer; - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferCreateInfo-usage-02606"); - VkResult result = vkCreateBuffer(m_device->device(), &buffer_create_info, nullptr, &buffer); - m_errorMonitor->VerifyFound(); - if (result == VK_SUCCESS) { - vkDestroyBuffer(m_device->device(), buffer, NULL); - } - - buffer_create_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; - result = vkCreateBuffer(m_device->device(), &buffer_create_info, nullptr, &buffer); - ASSERT_VK_SUCCESS(result); - - VkBufferDeviceAddressInfoEXT info = {VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_EXT}; - info.buffer = buffer; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkGetBufferDeviceAddressEXT-None-02598"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferDeviceAddressInfoEXT-buffer-02601"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferDeviceAddressInfoEXT-buffer-02600"); - vkGetBufferDeviceAddressEXT(m_device->device(), &info); - m_errorMonitor->VerifyFound(); - - vkDestroyBuffer(m_device->device(), buffer, NULL); -} - -TEST_F(VkLayerTest, CreateImageYcbcrArrayLayers) { - TEST_DESCRIPTION("Creating images with out-of-range arrayLayers "); - - // Enable KHR multiplane req'd extensions - bool mp_extensions = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION); - if (mp_extensions) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - mp_extensions = mp_extensions && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - if (mp_extensions) { - m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); - m_device_extension_names.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); - } else { - printf("%s test requires KHR multiplane extensions, not available. Skipping.\n", kSkipPrefix); - return; - } - - ASSERT_NO_FATAL_FAILURE(InitState()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - // Create ycbcr image with unsupported arrayLayers - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; - image_create_info.extent.width = 32; - image_create_info.extent.height = 32; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - - bool supported = ImageFormatAndFeaturesSupported(instance(), gpu(), image_create_info, VK_FORMAT_FEATURE_TRANSFER_SRC_BIT); - if (!supported) { - printf("%s Multiplane image format not supported. Skipping test.\n", kSkipPrefix); - return; - } - - VkImageFormatProperties img_limits; - ASSERT_VK_SUCCESS(GPDIFPHelper(gpu(), &image_create_info, &img_limits)); - if (img_limits.maxArrayLayers == 1) { - return; - } - image_create_info.arrayLayers = img_limits.maxArrayLayers; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-format-02653"); - - VkImage image; - vkCreateImage(m_device->handle(), &image_create_info, NULL, &image); - m_errorMonitor->VerifyFound(); -} - -TEST_F(VkLayerTest, CooperativeMatrixNV) { - TEST_DESCRIPTION("Test VK_NV_cooperative_matrix."); - - if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } else { - printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - std::array<const char *, 2> required_device_extensions = { - {VK_NV_COOPERATIVE_MATRIX_EXTENSION_NAME, VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME}}; - for (auto device_extension : required_device_extensions) { - if (DeviceExtensionSupported(gpu(), nullptr, device_extension)) { - m_device_extension_names.push_back(device_extension); - } else { - printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension); - return; - } - } - - if (DeviceIsMockICD() || DeviceSimulation()) { - printf("%s Test not supported by MockICD, skipping tests\n", kSkipPrefix); - return; - } - - PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = - (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR"); - ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr); - - auto float16_features = lvl_init_struct<VkPhysicalDeviceFloat16Int8FeaturesKHR>(); - auto cooperative_matrix_features = lvl_init_struct<VkPhysicalDeviceCooperativeMatrixFeaturesNV>(&float16_features); - auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&cooperative_matrix_features); - vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2); - - ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); - - std::vector<VkDescriptorSetLayoutBinding> bindings(0); - const VkDescriptorSetLayoutObj dsl(m_device, bindings); - const VkPipelineLayoutObj pl(m_device, {&dsl}); - - char const *csSource = - "#version 450\n" - "#extension GL_NV_cooperative_matrix : enable\n" - "#extension GL_KHR_shader_subgroup_basic : enable\n" - "#extension GL_KHR_memory_scope_semantics : enable\n" - "#extension GL_EXT_shader_explicit_arithmetic_types_float16 : enable\n" - "layout(local_size_x = 32) in;\n" - "layout(constant_id = 0) const uint C0 = 1;" - "layout(constant_id = 1) const uint C1 = 1;" - "void main() {\n" - // Bad type - " fcoopmatNV<16, gl_ScopeSubgroup, 3, 5> badSize = fcoopmatNV<16, gl_ScopeSubgroup, 3, 5>(float16_t(0.0));\n" - // Not a valid multiply when C0 != C1 - " fcoopmatNV<16, gl_ScopeSubgroup, C0, C1> A;\n" - " fcoopmatNV<16, gl_ScopeSubgroup, C0, C1> B;\n" - " fcoopmatNV<16, gl_ScopeSubgroup, C0, C1> C;\n" - " coopMatMulAddNV(A, B, C);\n" - "}\n"; - VkShaderObj cs(m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT, this); - - const uint32_t specData[] = { - 16, - 8, - }; - VkSpecializationMapEntry entries[] = { - {0, sizeof(uint32_t) * 0, sizeof(uint32_t)}, - {1, sizeof(uint32_t) * 1, sizeof(uint32_t)}, - }; - - VkSpecializationInfo specInfo = { - 2, - entries, - sizeof(specData), - specData, - }; - - VkComputePipelineCreateInfo cpci = {VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - nullptr, - 0, - {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0, - VK_SHADER_STAGE_COMPUTE_BIT, cs.handle(), "main", &specInfo}, - pl.handle(), - VK_NULL_HANDLE, - -1}; - - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "UNASSIGNED-CoreValidation-Shader-CooperativeMatrixType"); - m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "UNASSIGNED-CoreValidation-Shader-CooperativeMatrixMulAdd"); - - VkPipeline pipe = VK_NULL_HANDLE; - vkCreateComputePipelines(m_device->device(), VK_NULL_HANDLE, 1, &cpci, nullptr, &pipe); - - m_errorMonitor->VerifyFound(); - - vkDestroyPipeline(m_device->device(), pipe, nullptr); -} - -TEST_F(VkLayerTest, GraphicsPipelineStageCreationFeedbackCount) { - TEST_DESCRIPTION("Test graphics pipeline feedback stage count check."); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME); - } else { - printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - auto feedback_info = lvl_init_struct<VkPipelineCreationFeedbackCreateInfoEXT>(); - VkPipelineCreationFeedbackEXT feedbacks[3] = {}; - - feedback_info.pPipelineCreationFeedback = &feedbacks[0]; - feedback_info.pipelineStageCreationFeedbackCount = 2; - feedback_info.pPipelineStageCreationFeedbacks = &feedbacks[1]; - - auto set_feedback = [&feedback_info](CreatePipelineHelper &helper) { helper.gp_ci_.pNext = &feedback_info; }; - - CreatePipelineHelper::OneshotTest(*this, set_feedback, VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineCreationFeedbackCreateInfoEXT-pipelineStageCreationFeedbackCount-02668", - true); - - feedback_info.pipelineStageCreationFeedbackCount = 1; - CreatePipelineHelper::OneshotTest(*this, set_feedback, VK_DEBUG_REPORT_ERROR_BIT_EXT, - "VUID-VkPipelineCreationFeedbackCreateInfoEXT-pipelineStageCreationFeedbackCount-02668", - false); -} - -TEST_F(VkLayerTest, ComputePipelineStageCreationFeedbackCount) { - TEST_DESCRIPTION("Test compute pipeline feedback stage count check."); - - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME); - } else { - printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME); - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); - - VkDescriptorSetObj descriptorSet(m_device); - descriptorSet.AppendDummy(); - descriptorSet.CreateVKDescriptorSet(m_commandBuffer); - - // Create a minimal compute pipeline - const char *cs_text = "#version 450\nvoid main() {}\n"; // minimal no-op shader - VkShaderObj cs_obj(m_device, cs_text, VK_SHADER_STAGE_COMPUTE_BIT, this); - - VkPipelineCreationFeedbackCreateInfoEXT feedback_info = {}; - VkPipelineCreationFeedbackEXT feedbacks[3] = {}; - feedback_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT; - - feedback_info.pPipelineCreationFeedback = &feedbacks[0]; - feedback_info.pipelineStageCreationFeedbackCount = 1; - feedback_info.pPipelineStageCreationFeedbacks = &feedbacks[1]; - - VkComputePipelineCreateInfo pipeline_info = {}; - pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; - pipeline_info.pNext = &feedback_info; - pipeline_info.layout = descriptorSet.GetPipelineLayout(); - pipeline_info.basePipelineHandle = VK_NULL_HANDLE; - pipeline_info.basePipelineIndex = -1; - pipeline_info.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - pipeline_info.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; - pipeline_info.stage.pName = "main"; - pipeline_info.stage.module = cs_obj.handle(); - - { - m_errorMonitor->ExpectSuccess(VK_DEBUG_REPORT_ERROR_BIT_EXT); - VkPipeline cs_pipeline = VK_NULL_HANDLE; - vkCreateComputePipelines(device(), VK_NULL_HANDLE, 1, &pipeline_info, nullptr, &cs_pipeline); - vkDestroyPipeline(device(), cs_pipeline, nullptr); - m_errorMonitor->VerifyNotFound(); - } - - { - m_errorMonitor->SetDesiredFailureMsg( - VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineCreationFeedbackCreateInfoEXT-pipelineStageCreationFeedbackCount-02669"); - feedback_info.pipelineStageCreationFeedbackCount = 2; - - VkPipeline cs_pipeline = VK_NULL_HANDLE; - vkCreateComputePipelines(device(), VK_NULL_HANDLE, 1, &pipeline_info, nullptr, &cs_pipeline); - vkDestroyPipeline(device(), cs_pipeline, nullptr); - m_errorMonitor->VerifyFound(); - } -} - -TEST_F(VkLayerTest, NVRayTracingPipelineStageCreationFeedbackCount) { - TEST_DESCRIPTION("Test NV ray tracing pipeline feedback stage count check."); - - if (!CreateNVRayTracingPipelineHelper::InitInstanceExtensions(*this, m_instance_extension_names)) { - return; - } - ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); - - if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME)) { - m_device_extension_names.push_back(VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME); - } else { - printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME); - return; - } - - if (!CreateNVRayTracingPipelineHelper::InitDeviceExtensions(*this, m_device_extension_names)) { - return; - } - ASSERT_NO_FATAL_FAILURE(InitState()); - - auto feedback_info = lvl_init_struct<VkPipelineCreationFeedbackCreateInfoEXT>(); - VkPipelineCreationFeedbackEXT feedbacks[4] = {}; - - feedback_info.pPipelineCreationFeedback = &feedbacks[0]; - feedback_info.pipelineStageCreationFeedbackCount = 2; - feedback_info.pPipelineStageCreationFeedbacks = &feedbacks[1]; - - auto set_feedback = [&feedback_info](CreateNVRayTracingPipelineHelper &helper) { helper.rp_ci_.pNext = &feedback_info; }; - - feedback_info.pipelineStageCreationFeedbackCount = 3; - CreateNVRayTracingPipelineHelper::OneshotPositiveTest(*this, set_feedback); - - feedback_info.pipelineStageCreationFeedbackCount = 2; - CreateNVRayTracingPipelineHelper::OneshotTest( - *this, set_feedback, "VUID-VkPipelineCreationFeedbackCreateInfoEXT-pipelineStageCreationFeedbackCount-02670"); -} +#include "vklayertest.h" #if defined(ANDROID) && defined(VALIDATION_APK) const char *appTag = "VulkanLayerValidationTests"; |