/* * Copyright (c) 2015-2019 The Khronos Group Inc. * Copyright (c) 2015-2019 Valve Corporation * Copyright (c) 2015-2019 LunarG, Inc. * Copyright (c) 2015-2019 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Author: Chia-I Wu * Author: Chris Forbes * Author: Courtney Goeltzenleuchter * Author: Mark Lobodzinski * Author: Mike Stroyan * Author: Tobin Ehlis * Author: Tony Barbour * Author: Cody Northrop * Author: Dave Houlton * Author: Jeremy Kniager * Author: Shannon McPherson * Author: John Zulauf */ #include "cast_utils.h" #include "layer_validation_tests.h" 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()); // maxAnisotropy out-of-bounds low. sampler_info.maxAnisotropy = NearestSmaller(1.0F); CreateSamplerTest(*this, &sampler_info, "VUID-VkSamplerCreateInfo-anisotropyEnable-01071"); sampler_info.maxAnisotropy = sampler_info_ref.maxAnisotropy; // maxAnisotropy out-of-bounds high. sampler_info.maxAnisotropy = NearestGreater(m_device->phy().properties().limits.maxSamplerAnisotropy); CreateSamplerTest(*this, &sampler_info, "VUID-VkSamplerCreateInfo-anisotropyEnable-01071"); 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; CreateSamplerTest(*this, &sampler_info, "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01076"); sampler_info.unnormalizedCoordinates = sampler_info_ref.unnormalizedCoordinates; // Both anisotropy and cubic filtering enabled if (cubic_support) { sampler_info.minFilter = VK_FILTER_CUBIC_IMG; CreateSamplerTest(*this, &sampler_info, "VUID-VkSamplerCreateInfo-magFilter-01081"); sampler_info.minFilter = sampler_info_ref.minFilter; sampler_info.magFilter = VK_FILTER_CUBIC_IMG; CreateSamplerTest(*this, &sampler_info, "VUID-VkSamplerCreateInfo-magFilter-01081"); 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()); // min and mag filters must be the same sampler_info.minFilter = VK_FILTER_NEAREST; sampler_info.magFilter = VK_FILTER_LINEAR; CreateSamplerTest(*this, &sampler_info, "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01072"); std::swap(sampler_info.minFilter, sampler_info.magFilter); CreateSamplerTest(*this, &sampler_info, "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01072"); sampler_info = sampler_info_ref; // mipmapMode must be NEAREST sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; CreateSamplerTest(*this, &sampler_info, "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01073"); sampler_info = sampler_info_ref; // minlod and maxlod must be zero sampler_info.maxLod = 3.14159f; CreateSamplerTest(*this, &sampler_info, "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01074"); sampler_info.minLod = 2.71828f; CreateSamplerTest(*this, &sampler_info, "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01074"); 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 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; CreateSamplerTest(*this, &sampler_info, "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01075"); } } } 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; CreateSamplerTest(*this, &sampler_info, "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01077"); sampler_info = sampler_info_ref; } 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, SparseBindingImageBufferCreate) { TEST_DESCRIPTION("Create buffer/image with sparse attributes but without the sparse_binding bit set"); ASSERT_NO_FATAL_FAILURE(Init()); 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) { buf_info.flags = VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT; CreateBufferTest(*this, &buf_info, "VUID-VkBufferCreateInfo-flags-00918"); } else { printf("%s Test requires unsupported sparseResidencyBuffer feature. Skipped.\n", kSkipPrefix); return; } if (m_device->phy().features().sparseResidencyAliased) { buf_info.flags = VK_BUFFER_CREATE_SPARSE_ALIASED_BIT; CreateBufferTest(*this, &buf_info, "VUID-VkBufferCreateInfo-flags-00918"); } else { printf("%s Test requires unsupported sparseResidencyAliased feature. Skipped.\n", kSkipPrefix); 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 = 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; CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-flags-00987"); } 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; CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-flags-00987"); } 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; } 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 CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-imageType-00970"); // 2D image w/ sparse residency when feature isn't available image_create_info.imageType = VK_IMAGE_TYPE_2D; image_create_info.extent.height = 64; CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-imageType-00971"); // 3D image w/ sparse residency when feature isn't available image_create_info.imageType = VK_IMAGE_TYPE_3D; image_create_info.extent.depth = 8; CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-imageType-00972"); } 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)); 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 CreateImageTest(*this, &image_create_info, "VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT then image tiling of VK_IMAGE_TILING_LINEAR is not supported"); 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; CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-imageType-00973"); image_create_info.samples = VK_SAMPLE_COUNT_4_BIT; CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-imageType-00974"); image_create_info.samples = VK_SAMPLE_COUNT_8_BIT; CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-imageType-00975"); image_create_info.samples = VK_SAMPLE_COUNT_16_BIT; CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-imageType-00976"); } 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, "UNASSIGNED-CoreValidation-MemTrack-InvalidMap"); 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, "VUID-vkBindImageMemory-image-01044"); 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; VkImageObj image(m_device); 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, 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, "UNASSIGNED-CoreValidation-MemTrack-InvalidUsageFlag"); 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, CopyBufferToCompressedImage) { TEST_DESCRIPTION("Copy buffer to compressed image when buffer is larger than image."); ASSERT_NO_FATAL_FAILURE(Init()); // Verify format support if (!ImageFormatAndFeaturesSupported(gpu(), VK_FORMAT_BC1_RGBA_SRGB_BLOCK, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR)) { printf("%s Required formats/features not supported - CopyBufferToCompressedImage skipped.\n", kSkipPrefix); return; } VkImageObj width_image(m_device); VkImageObj height_image(m_device); VkBufferObj buffer; VkMemoryPropertyFlags reqs = 0; buffer.init_as_src(*m_device, 8 * 4 * 2, reqs); VkBufferImageCopy region = {}; region.bufferRowLength = 0; region.bufferImageHeight = 0; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.imageSubresource.layerCount = 1; region.imageExtent.width = 8; region.imageExtent.height = 4; region.imageExtent.depth = 1; width_image.Init(5, 4, 1, VK_FORMAT_BC1_RGBA_SRGB_BLOCK, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL); height_image.Init(8, 3, 1, VK_FORMAT_BC1_RGBA_SRGB_BLOCK, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL); if (!width_image.initialized() || (!height_image.initialized())) { printf("%s Unable to initialize surfaces - UncompressedToCompressedImageCopy skipped.\n", kSkipPrefix); return; } m_commandBuffer->begin(); m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferImageCopy-imageOffset-00197"); vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer.handle(), width_image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); m_errorMonitor->VerifyFound(); m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBufferImageCopy-imageOffset-00200"); m_errorMonitor->SetUnexpectedError("VUID-vkCmdCopyBufferToImage-pRegions-00172"); VkResult err; VkImageCreateInfo depth_image_create_info = {}; depth_image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; depth_image_create_info.pNext = NULL; depth_image_create_info.imageType = VK_IMAGE_TYPE_3D; depth_image_create_info.format = VK_FORMAT_BC1_RGBA_SRGB_BLOCK; depth_image_create_info.extent.width = 8; depth_image_create_info.extent.height = 4; depth_image_create_info.extent.depth = 1; depth_image_create_info.mipLevels = 1; depth_image_create_info.arrayLayers = 1; depth_image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; depth_image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; depth_image_create_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; depth_image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; depth_image_create_info.queueFamilyIndexCount = 0; depth_image_create_info.pQueueFamilyIndices = NULL; VkImage depth_image = VK_NULL_HANDLE; err = vkCreateImage(m_device->handle(), &depth_image_create_info, NULL, &depth_image); ASSERT_VK_SUCCESS(err); VkDeviceMemory mem1; VkMemoryRequirements mem_reqs; mem_reqs.memoryTypeBits = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; 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.memoryTypeIndex = 1; vkGetImageMemoryRequirements(m_device->device(), depth_image, &mem_reqs); mem_alloc.allocationSize = mem_reqs.size; bool pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &mem_alloc, 0); ASSERT_TRUE(pass); err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &mem1); ASSERT_VK_SUCCESS(err); err = vkBindImageMemory(m_device->device(), depth_image, mem1, 0); region.imageExtent.depth = 2; vkCmdCopyBufferToImage(m_commandBuffer->handle(), buffer.handle(), depth_image, VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); m_errorMonitor->VerifyFound(); vkDestroyImage(m_device->device(), depth_image, NULL); vkFreeMemory(m_device->device(), mem1, NULL); m_commandBuffer->end(); } 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(fakeImageHandle); vkGetImageMemoryRequirements(m_device->device(), fauxImage, &mem_reqs); 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, 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, 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, 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, "UNASSIGNED-CoreValidation-DrawState-InvalidCommandBuffer-VkBuffer"); // 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()); OneOffDescriptorSet descriptor_set(m_device, { {0, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}, }); CreatePipelineHelper pipe(*this); VkBufferCreateInfo buffer_create_info = {}; VkBufferViewCreateInfo bvci = {}; VkBufferView view; { uint32_t queue_family_index = 0; 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; VkBufferObj buffer; buffer.init(*m_device, buffer_create_info); bvci.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; bvci.buffer = buffer.handle(); bvci.format = VK_FORMAT_R32_SFLOAT; bvci.range = VK_WHOLE_SIZE; VkResult err = vkCreateBufferView(m_device->device(), &bvci, NULL, &view); ASSERT_VK_SUCCESS(err); descriptor_set.WriteDescriptorBufferView(0, view); descriptor_set.UpdateDescriptorSets(); 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, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this); VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this); pipe.InitInfo(); pipe.InitState(); pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; pipe.pipeline_layout_ = VkPipelineLayoutObj(m_device, {&descriptor_set.layout_}); pipe.CreateGraphicsPipeline(); 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.pipeline_); vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_layout_.handle(), 0, 1, &descriptor_set.set_, 0, nullptr); } // buffer is released. 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(); VkBufferObj buffer; buffer.init(*m_device, buffer_create_info); bvci.buffer = buffer.handle(); VkResult err = vkCreateBufferView(m_device->device(), &bvci, NULL, &view); ASSERT_VK_SUCCESS(err); descriptor_set.descriptor_writes.clear(); descriptor_set.WriteDescriptorBufferView(0, view); descriptor_set.UpdateDescriptorSets(); vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_layout_.handle(), 0, 1, &descriptor_set.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, "UNASSIGNED-CoreValidation-DrawState-InvalidCommandBuffer-VkBufferView"); vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); m_errorMonitor->VerifyFound(); } 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()); { 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; VkImageObj image(m_device); image.init(&image_create_info); 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.handle(), VK_IMAGE_LAYOUT_GENERAL, &ccv, 1, &isr); m_commandBuffer->end(); } // Destroy image dependency prior to submit to cause ERROR m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "UNASSIGNED-CoreValidation-DrawState-InvalidCommandBuffer-VkImage"); m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "UNASSIGNED-CoreValidation-DrawState-InvalidCommandBuffer-VkDeviceMemory"); 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, 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; } VkFramebuffer fb; VkImageView view; 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; VkImageObj image(m_device); image.init(&image_ci); 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_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}, {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}, }; 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}; 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 // Now attempt to submit cmd buffer and verify error m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "UNASSIGNED-CoreValidation-DrawState-InvalidCommandBuffer-VkImage"); m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "UNASSIGNED-CoreValidation-DrawState-InvalidCommandBuffer-VkDeviceMemory"); m_commandBuffer->QueueCommandBuffer(false); m_errorMonitor->VerifyFound(); vkDestroyFramebuffer(m_device->device(), fb, nullptr); vkDestroyImageView(m_device->device(), view, 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, 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(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()); OneOffDescriptorSet descriptor_set(m_device, { {0, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, }); VkBufferView view; { // Create a valid bufferView to start with 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; VkBufferObj buffer; buffer.init(*m_device, buffer_create_info); VkBufferViewCreateInfo bvci = {}; bvci.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; bvci.buffer = buffer.handle(); 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 VkWriteDescriptorSet descriptor_write; memset(&descriptor_write, 0, sizeof(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_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(); } 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; CreateBufferViewTest(*this, &buff_view_ci, {"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; CreateBufferViewTest(*this, &buff_view_ci, {"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; CreateBufferViewTest(*this, &buff_view_ci, {"VUID-VkBufferViewCreateInfo-offset-02749"}); // 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; CreateBufferViewTest(*this, &buff_view_ci, {"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; CreateBufferViewTest(*this, &buff_view_ci, {"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; CreateBufferViewTest(*this, &buff_view_ci, {"VUID-VkBufferViewCreateInfo-range-00930", "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 CreateBufferViewTest(*this, &buff_view_ci, {"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(); CreateBufferViewTest(*this, &buff_view_ci, {"VUID-VkBufferViewCreateInfo-buffer-00934"}); } TEST_F(VkLayerTest, InvalidTexelBufferAlignment) { TEST_DESCRIPTION("Test VK_EXT_texel_buffer_alignment."); 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 required_device_extensions = {{VK_EXT_TEXEL_BUFFER_ALIGNMENT_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 texel_buffer_alignment auto texel_buffer_alignment_features = lvl_init_struct(); auto features2 = lvl_init_struct(&texel_buffer_alignment_features); vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2); texel_buffer_alignment_features.texelBufferAlignment = VK_TRUE; VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT align_props = {}; align_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT; VkPhysicalDeviceProperties2 pd_props2 = {}; pd_props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; pd_props2.pNext = &align_props; vkGetPhysicalDeviceProperties2(gpu(), &pd_props2); ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); const VkFormat format_with_uniform_texel_support = VK_FORMAT_R8G8B8A8_UNORM; const VkDeviceSize resource_size = 1024; VkBufferCreateInfo buffer_info = VkBufferObj::create_info( resource_size, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT); VkBufferObj buffer; buffer.init(*m_device, 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 = buffer.handle(); buff_view_ci.format = format_with_uniform_texel_support; buff_view_ci.range = VK_WHOLE_SIZE; buff_view_ci.offset = 1; std::vector expectedErrors; if (buff_view_ci.offset < align_props.storageTexelBufferOffsetAlignmentBytes) { expectedErrors.push_back("VUID-VkBufferViewCreateInfo-buffer-02750"); } if (buff_view_ci.offset < align_props.uniformTexelBufferOffsetAlignmentBytes) { expectedErrors.push_back("VUID-VkBufferViewCreateInfo-buffer-02751"); } CreateBufferViewTest(*this, &buff_view_ci, expectedErrors); expectedErrors.clear(); buff_view_ci.offset = 4; if (buff_view_ci.offset < align_props.storageTexelBufferOffsetAlignmentBytes && !align_props.storageTexelBufferOffsetSingleTexelAlignment) { expectedErrors.push_back("VUID-VkBufferViewCreateInfo-buffer-02750"); } if (buff_view_ci.offset < align_props.uniformTexelBufferOffsetAlignmentBytes && !align_props.uniformTexelBufferOffsetSingleTexelAlignment) { expectedErrors.push_back("VUID-VkBufferViewCreateInfo-buffer-02751"); } CreateBufferViewTest(*this, &buff_view_ci, expectedErrors); expectedErrors.clear(); // Test a 3-component format VkFormatProperties format_properties; vkGetPhysicalDeviceFormatProperties(gpu(), VK_FORMAT_R32G32B32_SFLOAT, &format_properties); if (format_properties.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) { buffer_info.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; VkBufferObj buffer2; buffer2.init(*m_device, buffer_info, (VkMemoryPropertyFlags)VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); // Create a test buffer view buff_view_ci.buffer = buffer2.handle(); buff_view_ci.format = VK_FORMAT_R32G32B32_SFLOAT; buff_view_ci.offset = 1; if (buff_view_ci.offset < align_props.uniformTexelBufferOffsetAlignmentBytes) { expectedErrors.push_back("VUID-VkBufferViewCreateInfo-buffer-02751"); } CreateBufferViewTest(*this, &buff_view_ci, expectedErrors); expectedErrors.clear(); buff_view_ci.offset = 4; if (buff_view_ci.offset < align_props.uniformTexelBufferOffsetAlignmentBytes && !align_props.uniformTexelBufferOffsetSingleTexelAlignment) { expectedErrors.push_back("VUID-VkBufferViewCreateInfo-buffer-02751"); } CreateBufferViewTest(*this, &buff_view_ci, expectedErrors); expectedErrors.clear(); } } TEST_F(VkLayerTest, FillBufferWithinRenderPass) { // Call CmdFillBuffer within an active renderpass m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdFillBuffer-renderpass"); 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, UpdateBufferWithinRenderPass) { // Call CmdUpdateBuffer within an active renderpass m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdUpdateBuffer-renderpass"); 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, "VUID-vkCmdClearColorImage-renderpass"); 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; VkImageObj dstImage(m_device); dstImage.init(&image_create_info); const VkImageSubresourceRange range = VkImageObj::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}; VkImageCreateInfo image_create_info = VkImageObj::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; VkImageObj dst_image_bad_usage(m_device); dst_image_bad_usage.init(&image_create_info); const VkImageSubresourceRange range = VkImageObj::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; VkImageObj dst_image(m_device); dst_image.init(&image_create_info); 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, 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()); const uint32_t submit_family = m_device->graphics_queue_node_index_; const uint32_t invalid = static_cast(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 qf_indices{{submit_family, other_family}}; if (only_one_family) { qf_indices.resize(1); } BarrierQueueFamilyTestHelper::Context test_context(this, qf_indices); // Use image unbound to memory in barrier // Use buffer unbound to memory in barrier BarrierQueueFamilyTestHelper conc_test(&test_context); conc_test.Init(nullptr, false, false); conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; conc_test(" used with no memory bound. Memory should be bound by calling vkBindImageMemory()", " used with no memory bound. Memory should be bound by calling vkBindBufferMemory()"); VkBufferObj buffer; VkMemoryPropertyFlags mem_reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; buffer.init_as_src_and_dst(*m_device, 256, mem_reqs); conc_test.buffer_barrier_.buffer = buffer.handle(); VkImageObj image(m_device); image.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); conc_test.image_barrier_.image = image.handle(); // New layout can't be UNDEFINED conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_UNDEFINED; conc_test("VUID-VkImageMemoryBarrier-newLayout-01198", ""); // Transition image to color attachment optimal conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; conc_test(""); // TODO: this looks vestigal or incomplete... m_commandBuffer->begin(); m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); // Can't send buffer memory barrier during a render pass vkCmdEndRenderPass(m_commandBuffer->handle()); // Duplicate barriers that change layout VkImageMemoryBarrier img_barrier = {}; img_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; img_barrier.pNext = NULL; img_barrier.image = image.handle(); img_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; img_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; img_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; 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; 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(); // Exceed the buffer size conc_test.buffer_barrier_.offset = conc_test.buffer_.create_info().size + 1; conc_test("", "VUID-VkBufferMemoryBarrier-offset-01187"); conc_test.buffer_barrier_.offset = 0; conc_test.buffer_barrier_.size = conc_test.buffer_.create_info().size + 1; // Size greater than total size conc_test("", "VUID-VkBufferMemoryBarrier-size-01189"); conc_test.buffer_barrier_.size = VK_WHOLE_SIZE; // Now exercise barrier aspect bit errors, first DS VkDepthStencilObj ds_image(m_device); ds_image.Init(m_device, 128, 128, depth_format); ASSERT_TRUE(ds_image.initialized()); conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL; conc_test.image_barrier_.image = ds_image.handle(); // Not having DEPTH or STENCIL set is an error conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT; m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageSubresource-aspectMask-parameter"); conc_test("VUID-VkImageMemoryBarrier-image-01207"); // Having only one of depth or stencil set for DS image is an error conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; conc_test("VUID-VkImageMemoryBarrier-image-01207"); // Having anything other than DEPTH and STENCIL is an error conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_COLOR_BIT; conc_test("VUID-VkImageSubresource-aspectMask-parameter"); // 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()); conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL; conc_test.image_barrier_.image = d_image.handle(); // DEPTH bit must be set conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT; conc_test("Depth-only image formats must have the VK_IMAGE_ASPECT_DEPTH_BIT set."); // No bits other than DEPTH may be set conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_COLOR_BIT; conc_test("Depth-only image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT set."); } // 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()); conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL; conc_test.image_barrier_.image = s_image.handle(); // Use of COLOR aspect on depth image is error conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; conc_test("Stencil-only image formats must have the VK_IMAGE_ASPECT_STENCIL_BIT set."); } // 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()); conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL; conc_test.image_barrier_.image = c_image.handle(); // COLOR bit must be set conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT; conc_test("Color image formats must have the VK_IMAGE_ASPECT_COLOR_BIT set."); // No bits other than COLOR may be set conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT; conc_test("Color image formats must have ONLY the VK_IMAGE_ASPECT_COLOR_BIT set."); // 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) { conc_test.image_barrier_.image = bad_buffer_layouts[i].image_obj.handle(); const VkImageUsageFlags usage = bad_buffer_layouts[i].image_obj.usage(); conc_test.image_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; conc_test.image_barrier_.oldLayout = bad_buffer_layouts[i].bad_layout; conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL; conc_test(bad_buffer_layouts[i].msg_code); conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_GENERAL; conc_test.image_barrier_.newLayout = bad_buffer_layouts[i].bad_layout; conc_test(bad_buffer_layouts[i].msg_code); } conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_GENERAL; conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL; conc_test.image_barrier_.image = image.handle(); } // Attempt barrier where srcAccessMask is not supported by srcStageMask // Have lower-order bit that's supported (shader write), but higher-order bit not supported to verify multi-bit validation conc_test.buffer_barrier_.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT; conc_test.buffer_barrier_.offset = 0; conc_test.buffer_barrier_.size = VK_WHOLE_SIZE; conc_test("", "VUID-vkCmdPipelineBarrier-pMemoryBarriers-01184"); // Attempt barrier where dstAccessMask is not supported by dstStageMask conc_test.buffer_barrier_.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; conc_test.buffer_barrier_.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; conc_test("", "VUID-vkCmdPipelineBarrier-pMemoryBarriers-01185"); // Attempt to mismatch barriers/waitEvents calls with incompatible queues // Create command pool with incompatible queueflags const std::vector 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! } 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-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); } 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(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 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 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 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(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 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 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()); 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; // 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; const uint32_t submit_family = m_device->graphics_queue_node_index_; const uint32_t invalid = static_cast(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 qf_indices{{submit_family, other_family}}; if (only_one_family) { qf_indices.resize(1); } BarrierQueueFamilyTestHelper::Context test_context(this, qf_indices); // Use image unbound to memory in barrier // Use buffer unbound to memory in barrier BarrierQueueFamilyTestHelper conc_test(&test_context); conc_test.Init(nullptr); img_barrier_template.image = conc_test.image_.handle(); conc_test.image_barrier_ = img_barrier_template; // Nested scope here confuses clang-format, somehow // clang-format off // try for vkCmdPipelineBarrier { // Try baseMipLevel >= image.mipLevels with VK_REMAINING_MIP_LEVELS { conc_test.image_barrier_.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 1, VK_REMAINING_MIP_LEVELS, 0, 1}; conc_test("VUID-VkImageMemoryBarrier-subresourceRange-01486"); } // Try baseMipLevel >= image.mipLevels without VK_REMAINING_MIP_LEVELS { conc_test.image_barrier_.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 0, 1}; m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01724"); conc_test("VUID-VkImageMemoryBarrier-subresourceRange-01486"); } // Try levelCount = 0 { conc_test.image_barrier_.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 0, 1}; conc_test("VUID-VkImageMemoryBarrier-subresourceRange-01724"); } // Try baseMipLevel + levelCount > image.mipLevels { conc_test.image_barrier_.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 2, 0, 1}; conc_test("VUID-VkImageMemoryBarrier-subresourceRange-01724"); } // Try baseArrayLayer >= image.arrayLayers with VK_REMAINING_ARRAY_LAYERS { conc_test.image_barrier_.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 1, VK_REMAINING_ARRAY_LAYERS}; conc_test("VUID-VkImageMemoryBarrier-subresourceRange-01488"); } // Try baseArrayLayer >= image.arrayLayers without VK_REMAINING_ARRAY_LAYERS { conc_test.image_barrier_.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 1, 1}; m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageMemoryBarrier-subresourceRange-01725"); conc_test("VUID-VkImageMemoryBarrier-subresourceRange-01488"); } // Try layerCount = 0 { conc_test.image_barrier_.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 0}; conc_test("VUID-VkImageMemoryBarrier-subresourceRange-01725"); } // Try baseArrayLayer + layerCount > image.arrayLayers { conc_test.image_barrier_.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 2}; conc_test("VUID-VkImageMemoryBarrier-subresourceRange-01725"); } } m_commandBuffer->begin(); // 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, 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; VkBufferObj buffer; buffer.init(*m_device, buf_info); m_commandBuffer->begin(); // 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.handle(), 7, VK_INDEX_TYPE_UINT16); 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}; CreateImageTest(*this, &ici, "VUID-VkImageCreateInfo-flags-00950"); } 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"); ASSERT_NO_FATAL_FAILURE(Init()); ASSERT_NO_FATAL_FAILURE(InitViewport()); ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); CreatePipelineHelper pipe(*this); pipe.InitInfo(); pipe.InitState(); pipe.CreateGraphicsPipeline(); m_commandBuffer->begin(); m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_); m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "CoreValidation-DrawState-InvalidCommandBuffer-VkBuffer"); m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "CoreValidation-DrawState-InvalidCommandBuffer-VkDeviceMemory"); { // 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.AddVertexInputToPipeHelpr(&pipe); m_commandBuffer->Draw(1, 0, 0, 0); m_commandBuffer->EndRenderPass(); } vkEndCommandBuffer(m_commandBuffer->handle()); 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, "VUID-vkBindBufferMemory-memoryOffset-01036"); 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(); } // 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 VkImageObj src_image(m_device); VkImageObj dst_image(m_device); VkImageObj depth_image(m_device); 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; src_image.init(&image_create_info); image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; dst_image.init(&image_create_info); image_create_info.format = VK_FORMAT_D16_UNORM; image_create_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; depth_image.init(&image_create_info); 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.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), 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.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), 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.handle(), VK_IMAGE_LAYOUT_UNDEFINED, dst_image.handle(), 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.handle(), VK_IMAGE_LAYOUT_UNDEFINED, dst_image.handle(), 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.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), 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.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), 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.handle(), VK_IMAGE_LAYOUT_GENERAL, dst_image.handle(), 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.handle(); 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.handle(); 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.handle(), 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.handle(), 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.handle(), 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.handle(), 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.handle(); 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(); } 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 descriptor_set(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); descriptor_set.WriteDescriptorImageInfo(0, view, VK_NULL_HANDLE, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); 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 "); descriptor_set.UpdateDescriptorSets(); m_errorMonitor->VerifyFound(); } 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 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 CreateImageViewTest(*this, &ivci, "vkCreateImageView(): pCreateInfo->viewType VK_IMAGE_VIEW_TYPE_2D is not compatible with image"); // 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 CreateImageViewTest(*this, &ivci, "vkCreateImageView(): pCreateInfo->viewType VK_IMAGE_VIEW_TYPE_3D is not compatible with image"); // Change VkImageViewCreateInfo to different mismatched viewType ivci.viewType = VK_IMAGE_VIEW_TYPE_CUBE; ivci.subresourceRange.layerCount = 6; // Test for error message CreateImageViewTest(*this, &ivci, "VUID-VkImageViewCreateInfo-image-01003"); // 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 CreateImageViewTest(*this, &ivci, "vkCreateImageView(): pCreateInfo->viewType VK_IMAGE_VIEW_TYPE_1D is not compatible with image"); // 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)) { CreateImageViewTest(*this, &ivci, "VUID-VkImageViewCreateInfo-image-01005"); } else { CreateImageViewTest(*this, &ivci, "VUID-VkImageViewCreateInfo-subResourceRange-01021"); } // 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 CreateImageViewTest(*this, &ivci, " when the VK_IMAGE_CREATE_SPARSE_BINDING_BIT, VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT, or " "VK_IMAGE_CREATE_SPARSE_ALIASED_BIT flags are enabled."); // 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()); // 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 CreateImageViewTest(*this, &ivci, optimal_error_codes[i]); } // 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()); // 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 CreateImageViewTest(*this, &ivci, optimal_error_codes[i]); } 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 CreateImageViewTest(*this, &ivci, "VUID-VkImageViewCreateInfo-usage-02275"); // 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 CreateImageViewTest(*this, &ivci); // Try a zero usage field usage_ci.usage = 0; CreateImageViewTest(*this, &ivci, "VUID-VkImageViewUsageCreateInfo-usage-requiredbitmask"); // Try an illegal bit in usage field usage_ci.usage = 0x10000000 | VK_IMAGE_USAGE_SAMPLED_BIT; CreateImageViewTest(*this, &ivci, "VUID-VkImageViewUsageCreateInfo-usage-parameter"); } TEST_F(VkLayerTest, CreateImageViewNoMemoryBoundToImage) { VkResult err; 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; CreateImageViewTest(*this, &image_view_create_info, " used with no memory bound. Memory should be bound by calling vkBindImageMemory()."); vkDestroyImage(m_device->device(), image, NULL); } TEST_F(VkLayerTest, InvalidImageViewAspect) { TEST_DESCRIPTION("Create an image and try to create a view with an invalid aspectMask"); 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; CreateImageViewTest(*this, &image_view_create_info, "VUID-VkImageSubresource-aspectMask-parameter"); 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, 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; CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-format-00943"); } 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()); 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 CreateImageViewTest(*this, &imgViewInfo, "Formats MUST be IDENTICAL unless VK_IMAGE_CREATE_MUTABLE_FORMAT BIT was set on image creation."); } 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); 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 CreateImageViewTest(*this, &imgViewInfo, "VUID-VkImageViewCreateInfo-image-01019"); } 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()); 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(); CreateImageViewTest(*this, &imgViewInfo, "VUID-VkImageViewCreateInfo-image-01018"); } 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 CreateImageViewTest(*this, &ivci, "VUID-VkImageViewCreateInfo-image-01586"); // Correct format succeeds ivci.format = VK_FORMAT_R8_UNORM; CreateImageViewTest(*this, &ivci); // Try a multiplane imageview ivci.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; CreateImageViewTest(*this, &ivci); } 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()); 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 { 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; CreateImageViewTest(*this, &img_view_info, "VUID-VkImageViewCreateInfo-subresourceRange-01478"); } // Try baseMipLevel >= image.mipLevels without VK_REMAINING_MIP_LEVELS { 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; m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-subresourceRange-01718"); CreateImageViewTest(*this, &img_view_info, "VUID-VkImageViewCreateInfo-subresourceRange-01478"); } // Try levelCount = 0 { 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; CreateImageViewTest(*this, &img_view_info, "VUID-VkImageViewCreateInfo-subresourceRange-01718"); } // Try baseMipLevel + levelCount > image.mipLevels { 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; CreateImageViewTest(*this, &img_view_info, "VUID-VkImageViewCreateInfo-subresourceRange-01718"); } // 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 { 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; CreateImageViewTest(*this, &img_view_info, "VUID-VkImageViewCreateInfo-subresourceRange-01480"); } // Try baseArrayLayer >= image.arrayLayers without VK_REMAINING_ARRAY_LAYERS { 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; m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageViewCreateInfo-subresourceRange-01719"); CreateImageViewTest(*this, &img_view_info, "VUID-VkImageViewCreateInfo-subresourceRange-01480"); } // Try layerCount = 0 { 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; CreateImageViewTest(*this, &img_view_info, "VUID-VkImageViewCreateInfo-subresourceRange-01719"); } // Try baseArrayLayer + layerCount > image.arrayLayers { 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; CreateImageViewTest(*this, &img_view_info, "VUID-VkImageViewCreateInfo-subresourceRange-01719"); } } } TEST_F(VkLayerTest, CreateImageMiscErrors) { TEST_DESCRIPTION("Misc leftover valid usage errors in VkImageCreateInfo struct"); VkPhysicalDeviceFeatures features{}; ASSERT_NO_FATAL_FAILURE(Init(&features)); 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; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-sharingMode-00941"); } { 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; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-sharingMode-00942"); } { VkImageCreateInfo image_ci = safe_image_ci; image_ci.format = VK_FORMAT_UNDEFINED; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-format-00943"); } { 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; m_errorMonitor->SetUnexpectedError("VUID-VkImageCreateInfo-imageType-00954"); image_ci.extent = {64, 1, 1}; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-flags-00949"); image_ci = safe_image_ci; image_ci.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; image_ci.imageType = VK_IMAGE_TYPE_3D; m_errorMonitor->SetUnexpectedError("VUID-VkImageCreateInfo-imageType-00954"); image_ci.extent = {4, 4, 4}; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-flags-00949"); image_ci = safe_image_ci; image_ci.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; image_ci.imageType = VK_IMAGE_TYPE_2D; image_ci.extent = {8, 6, 1}; image_ci.arrayLayers = 6; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-imageType-00954"); image_ci = safe_image_ci; image_ci.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; image_ci.imageType = VK_IMAGE_TYPE_2D; image_ci.extent = {8, 8, 1}; image_ci.arrayLayers = 4; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-imageType-00954"); } { 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}; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-samples-02257"); 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; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-samples-02257"); 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; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-samples-02257"); 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; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-samples-02257"); } { 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; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-usage-00963"); image_ci.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-usage-00966"); 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"); CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-usage-00966"); } { VkImageCreateInfo image_ci = safe_image_ci; image_ci.flags = VK_IMAGE_CREATE_SPARSE_BINDING_BIT; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-flags-00969"); } // 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; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-initialLayout-00993"); } } 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::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; CreateImageTest(*this, &bad_image_ci, "VUID-VkImageCreateInfo-mipLevels-00947"); } { VkImageCreateInfo bad_image_ci = safe_image_ci; bad_image_ci.arrayLayers = 0; CreateImageTest(*this, &bad_image_ci, "VUID-VkImageCreateInfo-arrayLayers-00948"); } { VkImageCreateInfo bad_image_ci = safe_image_ci; bad_image_ci.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; bad_image_ci.arrayLayers = 5; CreateImageTest(*this, &bad_image_ci, "VUID-VkImageCreateInfo-imageType-00954"); bad_image_ci.arrayLayers = 6; bad_image_ci.extent = {64, 63, 1}; CreateImageTest(*this, &bad_image_ci, "VUID-VkImageCreateInfo-imageType-00954"); } { VkImageCreateInfo bad_image_ci = safe_image_ci; bad_image_ci.imageType = VK_IMAGE_TYPE_1D; bad_image_ci.extent = {64, 2, 1}; CreateImageTest(*this, &bad_image_ci, "VUID-VkImageCreateInfo-imageType-00956"); bad_image_ci.imageType = VK_IMAGE_TYPE_1D; bad_image_ci.extent = {64, 1, 2}; CreateImageTest(*this, &bad_image_ci, "VUID-VkImageCreateInfo-imageType-00956"); bad_image_ci.imageType = VK_IMAGE_TYPE_2D; bad_image_ci.extent = {64, 64, 2}; CreateImageTest(*this, &bad_image_ci, "VUID-VkImageCreateInfo-imageType-00957"); 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}; CreateImageTest(*this, &bad_image_ci, "VUID-VkImageCreateInfo-imageType-00957"); } { VkImageCreateInfo bad_image_ci = safe_image_ci; bad_image_ci.imageType = VK_IMAGE_TYPE_3D; bad_image_ci.arrayLayers = 2; CreateImageTest(*this, &bad_image_ci, "VUID-VkImageCreateInfo-imageType-00961"); } } TEST_F(VkLayerTest, CreateImageMaxLimitsViolation) { TEST_DESCRIPTION("Create invalid image with invalid parameters exceeding physical device limits."); // Check for VK_KHR_get_physical_device_properties2 bool push_physical_device_properties_2_support = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); if (push_physical_device_properties_2_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 push_fragment_density_support = false; if (push_physical_device_properties_2_support) { push_fragment_density_support = DeviceExtensionSupported(gpu(), nullptr, VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME); if (push_fragment_density_support) m_device_extension_names.push_back(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME); } ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, 0)); 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 CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-mipLevels-00958"); image_ci.extent = {8, 15, 1}; image_ci.mipLevels = 4 + 1; // 4 = floor(log2(15)) + 1 CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-mipLevels-00958"); } { 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) { CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-mipLevels-02255"); } 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; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-arrayLayers-02256"); } 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) { CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-samples-02258"); } 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}; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-usage-00964"); } 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}; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-usage-00965"); } else { printf("%s VkPhysicalDeviceLimits::maxFramebufferHeight is already UINT32_MAX; skipping part of test.\n", kSkipPrefix); } } { if (!push_fragment_density_support) { printf("%s VK_EXT_fragment_density_map Extension not supported, skipping tests\n", kSkipPrefix); } else { VkImageCreateInfo image_ci = safe_image_ci; image_ci.usage = VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT; VkImageFormatProperties img_limits; ASSERT_VK_SUCCESS(GPDIFPHelper(gpu(), &image_ci, &img_limits)); image_ci.extent = {dev_limits.maxFramebufferWidth + 1, 64, 1}; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-usage-02559"); image_ci.extent = {64, dev_limits.maxFramebufferHeight + 1, 1}; CreateImageTest(*this, &image_ci, "VUID-VkImageCreateInfo-usage-02560"); } } } 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)); PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionFunction = nullptr; PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionFunction = nullptr; if (DeviceValidationVersion() >= VK_API_VERSION_1_1) { vkCreateSamplerYcbcrConversionFunction = vkCreateSamplerYcbcrConversion; vkDestroySamplerYcbcrConversionFunction = vkDestroySamplerYcbcrConversion; } else { vkCreateSamplerYcbcrConversionFunction = (PFN_vkCreateSamplerYcbcrConversionKHR)vkGetDeviceProcAddr(m_device->handle(), "vkCreateSamplerYcbcrConversionKHR"); vkDestroySamplerYcbcrConversionFunction = (PFN_vkDestroySamplerYcbcrConversionKHR)vkGetDeviceProcAddr(m_device->handle(), "vkDestroySamplerYcbcrConversionKHR"); } if (!vkCreateSamplerYcbcrConversionFunction || !vkDestroySamplerYcbcrConversionFunction) { printf("%s Did not find required device extension %s; test skipped.\n", kSkipPrefix, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); return; } 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]; vkCreateSamplerYcbcrConversionFunction(m_device->handle(), &ycbcr_create_info, nullptr, &conversions[0]); ycbcr_create_info.components.r = VK_COMPONENT_SWIZZLE_ZERO; // Just anything different than above vkCreateSamplerYcbcrConversionFunction(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 view; 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, &view); // Use the image and sampler together in a descriptor set OneOffDescriptorSet descriptor_set(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 = view; 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 = descriptor_set.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-VkWriteDescriptorSet-descriptorType-02738. // Because if pNext chains a VkSamplerYcbcrConversionInfo, the sampler has to be a immutable sampler. OneOffDescriptorSet descriptor_set_1947(m_device, { {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr}, }); descriptor_write.dstSet = descriptor_set_1947.set_; descriptor_write.descriptorCount = 1; descriptor_write.pImageInfo = &image_infos[0]; m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-02738"); vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); m_errorMonitor->VerifyFound(); vkDestroySamplerYcbcrConversionFunction(m_device->device(), conversions[0], nullptr); vkDestroySamplerYcbcrConversionFunction(m_device->device(), conversions[1], nullptr); vkDestroyImageView(m_device->device(), view, NULL); vkDestroySampler(m_device->device(), samplers[0], nullptr); vkDestroySampler(m_device->device(), samplers[1], nullptr); } 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 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; } VkImageObj image_bad(m_device); VkImageObj image_good(m_device); // 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; image_bad.init(&image_create_info); image_create_info.format = tex_format_good; image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; image_good.init(&image_create_info); VkImageViewCreateInfo image_view_create_info = {}; image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; image_view_create_info.image = image_bad.handle(); 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; vkCreateImageView(m_device->device(), &image_view_create_info, NULL, &view); m_errorMonitor->VerifyFound(); } 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 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, 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; info.size = 0; CreateBufferTest(*this, &info, "VUID-VkBufferCreateInfo-size-00912"); } 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; CreateBufferTest(*this, &buffer_create_info, "chain contains duplicate structure types"); } 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(); 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... VkImageObj image(m_device); VkImageObj wrong_image(m_device); auto image_info = VkImageObj::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(); 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(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 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(); auto features2 = lvl_init_struct(&corner_sampled_image_features); vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2); ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); 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 CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-flags-02050"); // 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; CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-flags-02051"); 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; CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-flags-02052"); // 3D width/height/depth must be > 1 image_create_info.imageType = VK_IMAGE_TYPE_3D; image_create_info.extent.height = 2; CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-flags-02053"); 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)) CreateImageTest(*this, &image_create_info); image_create_info.extent = {8, 8, 1}; image_create_info.mipLevels = 3; // 3 = ceil(log2(8)) CreateImageTest(*this, &image_create_info); image_create_info.extent = {9, 9, 1}; image_create_info.mipLevels = 3; // 4 = ceil(log2(9)) CreateImageTest(*this, &image_create_info); // Invalid # of mip levels image_create_info.extent = {8, 8, 1}; image_create_info.mipLevels = 4; // 3 = ceil(log2(8)) CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-mipLevels-00958"); } 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(); PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionFunction = nullptr; if (DeviceValidationVersion() >= VK_API_VERSION_1_1) { vkCreateSamplerYcbcrConversionFunction = vkCreateSamplerYcbcrConversion; } else { vkCreateSamplerYcbcrConversionFunction = (PFN_vkCreateSamplerYcbcrConversionKHR)vkGetDeviceProcAddr(m_device->handle(), "vkCreateSamplerYcbcrConversionKHR"); } if (!vkCreateSamplerYcbcrConversionFunction) { printf("%s Did not find required device support for YcbcrSamplerConversion; test skipped.\n", kSkipPrefix); return; } // 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"); vkCreateSamplerYcbcrConversionFunction(dev, &sycci, NULL, &ycbcr_conv); m_errorMonitor->VerifyFound(); } 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 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(); auto features2 = lvl_init_struct(&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; CreateBufferTest(*this, &buffer_create_info, "VUID-VkBufferCreateInfo-flags-02605"); 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; CreateBufferTest(*this, &buffer_create_info, "VUID-VkBufferCreateInfo-deviceAddress-02604"); buffer_create_info.pNext = nullptr; VkBuffer buffer; VkResult err = vkCreateBuffer(m_device->device(), &buffer_create_info, NULL, &buffer); ASSERT_VK_SUCCESS(err); 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 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(); auto features2 = lvl_init_struct(&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; CreateBufferTest(*this, &buffer_create_info, "VUID-VkBufferCreateInfo-usage-02606"); buffer_create_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; VkBuffer buffer; VkResult err = vkCreateBuffer(m_device->device(), &buffer_create_info, NULL, &buffer); ASSERT_VK_SUCCESS(err); 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; CreateImageTest(*this, &image_create_info, "VUID-VkImageCreateInfo-format-02653"); m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkImageCreateInfo-format-02653"); } TEST_F(VkLayerTest, BindImageMemorySwapchain) { TEST_DESCRIPTION("Invalid bind image with a swapchain"); SetTargetApiVersion(VK_API_VERSION_1_1); if (!AddSurfaceInstanceExtension()) { printf("%s surface extensions not supported, skipping BindSwapchainImageMemory test\n", kSkipPrefix); return; } ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); if (!AddSwapchainDeviceExtension()) { printf("%s swapchain extensions not supported, skipping BindSwapchainImageMemory test\n", kSkipPrefix); return; } if (DeviceValidationVersion() < VK_API_VERSION_1_1) { printf("%s VkBindImageMemoryInfo requires Vulkan 1.1+, skipping test\n", kSkipPrefix); return; } ASSERT_NO_FATAL_FAILURE(InitState()); ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); if (!InitSwapchain()) { printf("%s Cannot create surface or swapchain, skipping BindSwapchainImageMemory test\n", kSkipPrefix); return; } auto image_create_info = lvl_init_struct(); 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_OPTIMAL; image_create_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; auto image_swapchain_create_info = lvl_init_struct(); image_swapchain_create_info.swapchain = m_swapchain; image_create_info.pNext = &image_swapchain_create_info; VkImage image_from_swapchain; vkCreateImage(device(), &image_create_info, NULL, &image_from_swapchain); VkMemoryRequirements mem_reqs = {}; vkGetImageMemoryRequirements(device(), image_from_swapchain, &mem_reqs); auto alloc_info = lvl_init_struct(); alloc_info.memoryTypeIndex = 0; alloc_info.allocationSize = mem_reqs.size; bool pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &alloc_info, 0); ASSERT_TRUE(pass); VkDeviceMemory mem; VkResult err = vkAllocateMemory(m_device->device(), &alloc_info, NULL, &mem); ASSERT_VK_SUCCESS(err); auto bind_info = lvl_init_struct(); bind_info.image = image_from_swapchain; bind_info.memory = VK_NULL_HANDLE; bind_info.memoryOffset = 0; m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBindImageMemoryInfo-image-01630"); m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBindImageMemoryInfo-pNext-01632"); vkBindImageMemory2(m_device->device(), 1, &bind_info); m_errorMonitor->VerifyFound(); auto bind_swapchain_info = lvl_init_struct(); bind_swapchain_info.swapchain = VK_NULL_HANDLE; bind_swapchain_info.imageIndex = 0; bind_info.pNext = &bind_swapchain_info; m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "UNASSIGNED-GeneralParameterError-RequiredParameter"); vkBindImageMemory2(m_device->device(), 1, &bind_info); m_errorMonitor->VerifyFound(); bind_info.memory = mem; bind_swapchain_info.swapchain = m_swapchain; bind_swapchain_info.imageIndex = UINT32_MAX; m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBindImageMemoryInfo-pNext-01631"); m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkBindImageMemorySwapchainInfoKHR-imageIndex-01644"); vkBindImageMemory2(m_device->device(), 1, &bind_info); m_errorMonitor->VerifyFound(); vkDestroyImage(m_device->device(), image_from_swapchain, NULL); vkFreeMemory(m_device->device(), mem, NULL); DestroySwapchain(); } TEST_F(VkLayerTest, TransferImageToSwapchainWithInvalidLayoutDeviceGroup) { TEST_DESCRIPTION("Transfer an image to a swapchain's image with a invalid layout between device group"); #if defined(VK_USE_PLATFORM_ANDROID_KHR) printf( "%s According to VUID-01631, VkBindImageMemoryInfo-memory should be NULL. But Android will crash if memory is NULL, " "skipping test\n", kSkipPrefix); return; #endif SetTargetApiVersion(VK_API_VERSION_1_1); if (!AddSurfaceInstanceExtension()) { printf("%s surface extensions not supported, skipping test\n", kSkipPrefix); return; } ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor)); if (!AddSwapchainDeviceExtension()) { printf("%s swapchain extensions not supported, skipping test\n", kSkipPrefix); return; } if (DeviceValidationVersion() < VK_API_VERSION_1_1) { printf("%s VkBindImageMemoryInfo 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; } std::vector 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)); ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); if (!InitSwapchain(VK_IMAGE_USAGE_TRANSFER_DST_BIT)) { printf("%s Cannot create surface or swapchain, skipping test\n", kSkipPrefix); return; } auto image_create_info = lvl_init_struct(); 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_OPTIMAL; image_create_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; VkImageObj src_Image(m_device); src_Image.init(&image_create_info); image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; image_create_info.flags = VK_IMAGE_CREATE_ALIAS_BIT; auto image_swapchain_create_info = lvl_init_struct(); image_swapchain_create_info.swapchain = m_swapchain; image_create_info.pNext = &image_swapchain_create_info; VkImage peer_image; vkCreateImage(device(), &image_create_info, NULL, &peer_image); auto bind_devicegroup_info = lvl_init_struct(); bind_devicegroup_info.deviceIndexCount = 2; std::array deviceIndices = {0, 0}; bind_devicegroup_info.pDeviceIndices = deviceIndices.data(); bind_devicegroup_info.splitInstanceBindRegionCount = 0; bind_devicegroup_info.pSplitInstanceBindRegions = nullptr; auto bind_swapchain_info = lvl_init_struct(&bind_devicegroup_info); bind_swapchain_info.swapchain = m_swapchain; bind_swapchain_info.imageIndex = 0; auto bind_info = lvl_init_struct(&bind_swapchain_info); bind_info.image = peer_image; bind_info.memory = VK_NULL_HANDLE; bind_info.memoryOffset = 0; vkBindImageMemory2(m_device->device(), 1, &bind_info); uint32_t swapchain_images_count = 0; vkGetSwapchainImagesKHR(device(), m_swapchain, &swapchain_images_count, nullptr); std::vector swapchain_images; swapchain_images.resize(swapchain_images_count); vkGetSwapchainImagesKHR(device(), m_swapchain, &swapchain_images_count, swapchain_images.data()); m_commandBuffer->begin(); 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}; copy_region.extent = {10, 10, 1}; vkCmdCopyImage(m_commandBuffer->handle(), src_Image.handle(), VK_IMAGE_LAYOUT_GENERAL, peer_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region); m_commandBuffer->end(); 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, "UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout"); vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE); m_errorMonitor->VerifyFound(); vkDestroyImage(m_device->device(), peer_image, NULL); DestroySwapchain(); }