blob: 300392de8a8cbf62b6cb11601c38913c41ae9e3e [file] [log] [blame]
/*
* 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 <olvaffe@gmail.com>
* Author: Chris Forbes <chrisf@ijw.co.nz>
* Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
* Author: Mark Lobodzinski <mark@lunarg.com>
* Author: Mike Stroyan <mike@LunarG.com>
* Author: Tobin Ehlis <tobine@google.com>
* Author: Tony Barbour <tony@LunarG.com>
* Author: Cody Northrop <cnorthrop@google.com>
* Author: Dave Houlton <daveh@lunarg.com>
* Author: Jeremy Kniager <jeremyk@lunarg.com>
* Author: Shannon McPherson <shannon@lunarg.com>
* Author: John Zulauf <jzulauf@lunarg.com>
*/
#include "cast_utils.h"
#include "layer_validation_tests.h"
TEST_F(VkLayerTest, BufferExtents) {
TEST_DESCRIPTION("Perform copies across a buffer, provoking out-of-range errors.");
ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
ASSERT_NO_FATAL_FAILURE(InitState());
const VkDeviceSize buffer_size = 2048;
VkBufferObj buffer_one;
VkBufferObj buffer_two;
VkMemoryPropertyFlags reqs = 0;
buffer_one.init_as_src_and_dst(*m_device, buffer_size, reqs);
buffer_two.init_as_src_and_dst(*m_device, buffer_size, reqs);
m_commandBuffer->begin();
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyBuffer-srcOffset-00113");
VkBufferCopy copy_info = {4096, 256, 256};
vk::CmdCopyBuffer(m_commandBuffer->handle(), buffer_one.handle(), buffer_two.handle(), 1, &copy_info);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyBuffer-dstOffset-00114");
copy_info = {256, 4096, 256};
vk::CmdCopyBuffer(m_commandBuffer->handle(), buffer_one.handle(), buffer_two.handle(), 1, &copy_info);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyBuffer-size-00115");
copy_info = {1024, 256, 1280};
vk::CmdCopyBuffer(m_commandBuffer->handle(), buffer_one.handle(), buffer_two.handle(), 1, &copy_info);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyBuffer-size-00116");
copy_info = {256, 1024, 1280};
vk::CmdCopyBuffer(m_commandBuffer->handle(), buffer_one.handle(), buffer_two.handle(), 1, &copy_info);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdCopyBuffer-pRegions-00117");
copy_info = {256, 512, 512};
vk::CmdCopyBuffer(m_commandBuffer->handle(), buffer_two.handle(), buffer_two.handle(), 1, &copy_info);
m_errorMonitor->VerifyFound();
m_commandBuffer->end();
}
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;
vk::CreateSampler(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 = vk::CreateSampler(m_device->device(), &sampler_info, NULL, &sampler);
m_errorMonitor->VerifyFound();
if (VK_SUCCESS == err) {
vk::DestroySampler(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<VkSamplerAddressMode, 4> kAddressModes = {{
VK_SAMPLER_ADDRESS_MODE_REPEAT,
VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
}};
for (const auto umode : kAddressModes) {
for (const auto vmode : kAddressModes) {
if ((umode != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE && umode != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) ||
(vmode != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE && vmode != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)) {
sampler_info.addressModeU = umode;
sampler_info.addressModeV = vmode;
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, FillBufferAlignmentAndSize) {
TEST_DESCRIPTION("Check alignment and size 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 greater than bufferSize
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdFillBuffer-dstOffset-00024");
m_commandBuffer->FillBuffer(buffer.handle(), 40, 4, 0x11111111);
m_errorMonitor->VerifyFound();
// Introduce failure by using size <= buffersize minus dstoffset
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdFillBuffer-size-00027");
m_commandBuffer->FillBuffer(buffer.handle(), 16, 12, 0x11111111);
m_errorMonitor->VerifyFound();
// 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 = vk::CreateBuffer(m_device->device(), &buf_info, NULL, &buffer);
ASSERT_VK_SUCCESS(err);
vk::GetBufferMemoryRequirements(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);
vk::DestroyBuffer(m_device->device(), buffer, NULL);
return;
}
err = vk::AllocateMemory(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 = vk::MapMemory(m_device->device(), mem, 0, 0, 0, (void **)&pData);
m_errorMonitor->VerifyFound();
// Map memory twice
err = vk::MapMemory(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 = vk::MapMemory(m_device->device(), mem, 0, mem_reqs.size, 0, (void **)&pData);
m_errorMonitor->VerifyFound();
// Unmap the memory to avoid re-map error
vk::UnmapMemory(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 = vk::MapMemory(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 = vk::MapMemory(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: ");
vk::UnmapMemory(m_device->device(), mem);
m_errorMonitor->VerifyFound();
// Now map memory and cause errors due to flushing invalid ranges
err = vk::MapMemory(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");
vk::FlushMappedMemoryRanges(m_device->device(), 1, &mmr);
m_errorMonitor->VerifyFound();
// Now flush range that oversteps mapped range
vk::UnmapMemory(m_device->device(), mem);
err = vk::MapMemory(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");
vk::FlushMappedMemoryRanges(m_device->device(), 1, &mmr);
m_errorMonitor->VerifyFound();
// Now flush range with VK_WHOLE_SIZE that oversteps offset
vk::UnmapMemory(m_device->device(), mem);
err = vk::MapMemory(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");
vk::FlushMappedMemoryRanges(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
vk::UnmapMemory(m_device->device(), mem);
err = vk::MapMemory(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");
vk::FlushMappedMemoryRanges(m_device->device(), 1, &mmr);
m_errorMonitor->VerifyFound();
// Now with a size NOT a multiple of the device limit
vk::UnmapMemory(m_device->device(), mem);
err = vk::MapMemory(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");
vk::FlushMappedMemoryRanges(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);
vk::FreeMemory(m_device->device(), mem, NULL);
vk::DestroyBuffer(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()
vk::DestroyBuffer(m_device->device(), buffer, NULL);
vk::FreeMemory(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 = vk::AllocateMemory(m_device->device(), &mem_alloc, NULL, &mem);
ASSERT_VK_SUCCESS(err);
void *mappedAddress = NULL;
err = vk::MapMemory(m_device->device(), mem, 0, VK_WHOLE_SIZE, 0, &mappedAddress);
m_errorMonitor->VerifyFound();
vk::FreeMemory(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 = vk::CreateImage(m_device->device(), &image_create_info, NULL, &image);
ASSERT_VK_SUCCESS(err);
vk::GetImageMemoryRequirements(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 = vk::AllocateMemory(m_device->device(), &mem_alloc, NULL, &mem1);
ASSERT_VK_SUCCESS(err);
err = vk::AllocateMemory(m_device->device(), &mem_alloc, NULL, &mem2);
ASSERT_VK_SUCCESS(err);
// Bind first memory object to Image object
err = vk::BindImageMemory(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 = vk::BindImageMemory(m_device->device(), image, mem2, 0);
m_errorMonitor->VerifyFound();
vk::DestroyImage(m_device->device(), image, NULL);
vk::FreeMemory(m_device->device(), mem1, NULL);
vk::FreeMemory(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;
vk::GetDeviceMemoryCommitment(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");
vk::CreateImageView(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");
vk::CmdCopyBufferToImage(m_commandBuffer->handle(), buffer.handle(), image.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
&region);
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");
vk::CmdCopyBufferToImage(m_commandBuffer->handle(), buffer.handle(), width_image.handle(), VK_IMAGE_LAYOUT_GENERAL, 1, &region);
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 = vk::CreateImage(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;
vk::GetImageMemoryRequirements(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 = vk::AllocateMemory(m_device->device(), &mem_alloc, NULL, &mem1);
ASSERT_VK_SUCCESS(err);
err = vk::BindImageMemory(m_device->device(), depth_image, mem1, 0);
region.imageExtent.depth = 2;
vk::CmdCopyBufferToImage(m_commandBuffer->handle(), buffer.handle(), depth_image, VK_IMAGE_LAYOUT_GENERAL, 1, &region);
m_errorMonitor->VerifyFound();
vk::DestroyImage(m_device->device(), depth_image, NULL);
vk::FreeMemory(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<VkImage &>(fakeImageHandle);
vk::GetImageMemoryRequirements(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 = vk::CreateImage(m_device->device(), &image_create_info, NULL, &image);
ASSERT_VK_SUCCESS(err);
vk::GetImageMemoryRequirements(m_device->device(), image, &mem_reqs);
mem_alloc.allocationSize = mem_reqs.size;
// Introduce Failure, select invalid TypeIndex
VkPhysicalDeviceMemoryProperties memory_info;
vk::GetPhysicalDeviceMemoryProperties(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);
vk::DestroyImage(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 = vk::AllocateMemory(m_device->device(), &mem_alloc, NULL, &mem);
ASSERT_VK_SUCCESS(err);
err = vk::BindImageMemory(m_device->device(), image, mem, 0);
(void)err;
m_errorMonitor->VerifyFound();
vk::DestroyImage(m_device->device(), image, NULL);
vk::FreeMemory(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 = vk::CreateImage(device(), &image_create_info, NULL, &image);
ASSERT_VK_SUCCESS(err);
err = vk::CreateBuffer(device(), &buffer_create_info, NULL, &buffer);
ASSERT_VK_SUCCESS(err);
VkMemoryRequirements image_mem_reqs = {}, buffer_mem_reqs = {};
vk::GetImageMemoryRequirements(device(), image, &image_mem_reqs);
vk::GetBufferMemoryRequirements(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 = vk::AllocateMemory(device(), &image_mem_alloc, NULL, &image_mem);
ASSERT_VK_SUCCESS(err);
err = vk::AllocateMemory(device(), &buffer_mem_alloc, NULL, &buffer_mem);
ASSERT_VK_SUCCESS(err);
vk::FreeMemory(device(), image_mem, NULL);
vk::FreeMemory(device(), buffer_mem, NULL);
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindImageMemory-memory-parameter");
err = vk::BindImageMemory(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 = vk::BindBufferMemory(device(), buffer, buffer_mem, 0);
(void)err; // This may very well return an error.
m_errorMonitor->VerifyFound();
vk::DestroyImage(m_device->device(), image, NULL);
vk::DestroyBuffer(m_device->device(), buffer, NULL);
}
// Try to bind memory to an object that already has a memory binding
{
VkImage image = VK_NULL_HANDLE;
err = vk::CreateImage(device(), &image_create_info, NULL, &image);
ASSERT_VK_SUCCESS(err);
VkBuffer buffer = VK_NULL_HANDLE;
err = vk::CreateBuffer(device(), &buffer_create_info, NULL, &buffer);
ASSERT_VK_SUCCESS(err);
VkMemoryRequirements image_mem_reqs = {}, buffer_mem_reqs = {};
vk::GetImageMemoryRequirements(device(), image, &image_mem_reqs);
vk::GetBufferMemoryRequirements(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 = vk::AllocateMemory(device(), &image_alloc_info, NULL, &image_mem);
ASSERT_VK_SUCCESS(err);
err = vk::AllocateMemory(device(), &buffer_alloc_info, NULL, &buffer_mem);
ASSERT_VK_SUCCESS(err);
err = vk::BindImageMemory(device(), image, image_mem, 0);
ASSERT_VK_SUCCESS(err);
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindImageMemory-image-01044");
err = vk::BindImageMemory(device(), image, image_mem, 0);
(void)err; // This may very well return an error.
m_errorMonitor->VerifyFound();
err = vk::BindBufferMemory(device(), buffer, buffer_mem, 0);
ASSERT_VK_SUCCESS(err);
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkBindBufferMemory-buffer-01029");
err = vk::BindBufferMemory(device(), buffer, buffer_mem, 0);
(void)err; // This may very well return an error.
m_errorMonitor->VerifyFound();
vk::FreeMemory(device(), image_mem, NULL);
vk::FreeMemory(device(), buffer_mem, NULL);
vk::DestroyImage(device(), image, NULL);
vk::DestroyBuffer(device(), buffer, NULL);
}
// Try to bind memory to an object with an invalid memoryOffset
{
VkImage image = VK_NULL_HANDLE;
err = vk::CreateImage(device(), &image_create_info, NULL, &image);
ASSERT_VK_SUCCESS(err);
VkBuffer buffer = VK_NULL_HANDLE;
err = vk::CreateBuffer(device(), &buffer_create_info, NULL, &buffer);
ASSERT_VK_SUCCESS(err);
VkMemoryRequirements image_mem_reqs = {}, buffer_mem_reqs = {};
vk::GetImageMemoryRequirements(device(), image, &image_mem_reqs);
vk::GetBufferMemoryRequirements(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 = vk::AllocateMemory(device(), &image_alloc_info, NULL, &image_mem);
ASSERT_VK_SUCCESS(err);
err = vk::AllocateMemory(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 = vk::BindImageMemory(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 = vk::BindBufferMemory(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 = vk::BindImageMemory(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 = vk::BindBufferMemory(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 = vk::BindImageMemory(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 = vk::BindBufferMemory(device(), buffer, buffer_mem, buffer_offset);
(void)err; // This may very well return an error.
m_errorMonitor->VerifyFound();
}
}
vk::FreeMemory(device(), image_mem, NULL);
vk::FreeMemory(device(), buffer_mem, NULL);
vk::DestroyImage(device(), image, NULL);
vk::DestroyBuffer(device(), buffer, NULL);
}
// Try to bind memory to an object with an invalid memory type
{
VkImage image = VK_NULL_HANDLE;
err = vk::CreateImage(device(), &image_create_info, NULL, &image);
ASSERT_VK_SUCCESS(err);
VkBuffer buffer = VK_NULL_HANDLE;
err = vk::CreateBuffer(device(), &buffer_create_info, NULL, &buffer);
ASSERT_VK_SUCCESS(err);
VkMemoryRequirements image_mem_reqs = {}, buffer_mem_reqs = {};
vk::GetImageMemoryRequirements(device(), image, &image_mem_reqs);
vk::GetBufferMemoryRequirements(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 = {};
vk::GetPhysicalDeviceMemoryProperties(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 = vk::AllocateMemory(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 = vk::BindImageMemory(device(), image, image_mem, 0);
(void)err; // This may very well return an error.
m_errorMonitor->VerifyFound();
vk::FreeMemory(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 = vk::AllocateMemory(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 = vk::BindBufferMemory(device(), buffer, buffer_mem, 0);
(void)err; // This may very well return an error.
m_errorMonitor->VerifyFound();
vk::FreeMemory(device(), buffer_mem, NULL);
}
vk::DestroyImage(device(), image, NULL);
vk::DestroyBuffer(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 = vk::GetPhysicalDeviceImageFormatProperties(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 = vk::CreateImage(m_device->device(), &sparse_image_create_info, NULL, &sparse_image);
ASSERT_VK_SUCCESS(err);
VkMemoryRequirements sparse_mem_reqs = {};
vk::GetImageMemoryRequirements(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 = vk::AllocateMemory(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 = vk::BindImageMemory(m_device->device(), sparse_image, sparse_mem, 0);
// This may very well return an error.
(void)err;
m_errorMonitor->VerifyFound();
vk::FreeMemory(m_device->device(), sparse_mem, NULL);
}
vk::DestroyImage(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 = vk::CreateBuffer(m_device->device(), &sparse_buffer_create_info, NULL, &sparse_buffer);
ASSERT_VK_SUCCESS(err);
VkMemoryRequirements sparse_mem_reqs = {};
vk::GetBufferMemoryRequirements(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 = vk::AllocateMemory(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 = vk::BindBufferMemory(m_device->device(), sparse_buffer, sparse_mem, 0);
// This may very well return an error.
(void)err;
m_errorMonitor->VerifyFound();
vk::FreeMemory(m_device->device(), sparse_mem, NULL);
}
vk::DestroyBuffer(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 = vk::CreateImage(m_device->device(), &image_create_info, NULL, &image);
ASSERT_VK_SUCCESS(err);
vk::GetImageMemoryRequirements(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 = vk::AllocateMemory(m_device->device(), &mem_alloc, NULL, &mem);
ASSERT_VK_SUCCESS(err);
// Introduce validation failure, destroy Image object before binding
vk::DestroyImage(m_device->device(), image, NULL);
ASSERT_VK_SUCCESS(err);
// Now Try to bind memory to this destroyed object
err = vk::BindImageMemory(m_device->device(), image, mem, 0);
// This may very well return an error.
(void)err;
m_errorMonitor->VerifyFound();
vk::FreeMemory(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)vk::GetInstanceProcAddr(instance(), "vkSetPhysicalDeviceLimitsEXT");
PFN_vkGetOriginalPhysicalDeviceLimitsEXT fpvkGetOriginalPhysicalDeviceLimitsEXT =
(PFN_vkGetOriginalPhysicalDeviceLimitsEXT)vk::GetInstanceProcAddr(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 = vk::AllocateMemory(m_device->device(), &mem_alloc, NULL, &mems[i]);
if (err != VK_SUCCESS) {
break;
}
}
m_errorMonitor->VerifyFound();
for (int j = 0; j < i; j++) {
vk::FreeMemory(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");
vk::CmdBlitImage(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");
vk::CmdBlitImage(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");
vk::CmdCopyBufferToImage(m_commandBuffer->handle(), src_buffer.handle(), dst_image.handle(),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy_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");
vk::CmdCopyImageToBuffer(m_commandBuffer->handle(), src_image.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dst_buffer.handle(), 1, &copy_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");
vk::CmdBlitImage(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");
vk::CmdBlitImage(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");
vk::CmdBlitImage(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");
vk::CmdBlitImage(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");
vk::CmdBlitImage(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");
vk::CmdBlitImage(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");
vk::CmdBlitImage(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");
vk::CmdBlitImage(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");
vk::CmdBlitImage(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");
vk::CmdBlitImage(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");
vk::CmdBlitImage(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");
vk::CmdBlitImage(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();
vk::QueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
err = vk::QueueWaitIdle(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");
vk::CmdBlitImage(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();
vk::QueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
err = vk::QueueWaitIdle(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");
vk::CmdBlitImage(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();
vk::QueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
err = vk::QueueWaitIdle(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;
vk::CmdPipelineBarrier(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");
vk::CmdBlitImage(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();
vk::QueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
err = vk::QueueWaitIdle(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();
vk::CmdPipelineBarrier(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");
vk::CmdBlitImage(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();
vk::QueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
err = vk::QueueWaitIdle(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");
vk::CmdBlitImage(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");
vk::CmdBlitImage(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");
vk::CmdBlitImage(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");
vk::CmdBlitImage(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
vk::CmdBlitImage(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
vk::CmdBlitImage(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
vk::CmdBlitImage(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
vk::CmdBlitImage(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
vk::CmdBlitImage(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
vk::CmdBlitImage(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");
vk::CmdBlitImage(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
vk::CmdBlitImage(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
vk::CmdBlitImage(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
vk::CmdBlitImage(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
vk::CmdBlitImage(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");
vk::CmdBlitImage(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
vk::CmdBlitImage(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
vk::CmdBlitImage(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");
vk::CmdBlitImage(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 =