diff options
| author | Mark Lobodzinski <mark@lunarg.com> | 2015-10-23 14:20:31 -0600 |
|---|---|---|
| committer | Mark Lobodzinski <mark@lunarg.com> | 2015-10-26 14:19:47 -0600 |
| commit | 6153e6bbcb88e2513e1b6ef9de3d905dbd289b81 (patch) | |
| tree | 455af7ff632d626ab60fa4a8b693021973258d12 | |
| parent | 822087f7b8bd8c40a9e6ca95eee64a01e000758c (diff) | |
| download | usermoji-6153e6bbcb88e2513e1b6ef9de3d905dbd289b81.tar.xz | |
layers: Add state-dependent image aspect/format checks
| -rw-r--r-- | layers/image.cpp | 225 | ||||
| -rw-r--r-- | layers/image.h | 16 | ||||
| -rw-r--r-- | layers/vk_layer_utils.cpp | 99 | ||||
| -rw-r--r-- | layers/vk_layer_utils.h | 9 | ||||
| -rw-r--r-- | layers/vk_validation_layer_details.md | 8 |
5 files changed, 294 insertions, 63 deletions
diff --git a/layers/image.cpp b/layers/image.cpp index a49ded8e..e03a1950 100644 --- a/layers/image.cpp +++ b/layers/image.cpp @@ -60,7 +60,7 @@ struct layer_data { }; static unordered_map<void*, layer_data*> layer_data_map; -static device_table_map image_device_table_map; +static device_table_map image_device_table_map; static instance_table_map image_instance_table_map; // "my device data" @@ -218,7 +218,7 @@ VK_LAYER_EXPORT VkResult VKAPI vkEnumerateInstanceExtensionProperties( uint32_t *pCount, VkExtensionProperties* pProperties) { - /* ParamChecker does not have any global extensions */ + // ParamChecker does not have any global extensions return util_GetExtensionProperties(0, NULL, pCount, pProperties); } @@ -237,7 +237,7 @@ VK_LAYER_EXPORT VkResult VKAPI vkEnumerateDeviceExtensionProperties( uint32_t* pCount, VkExtensionProperties* pProperties) { - /* ParamChecker does not have any physical device extensions */ + // ParamChecker does not have any physical device extensions return util_GetExtensionProperties(0, NULL, pCount, pProperties); } @@ -246,7 +246,7 @@ VK_LAYER_EXPORT VkResult VKAPI vkEnumerateDeviceLayerProperties( uint32_t* pCount, VkLayerProperties* pProperties) { - /* ParamChecker's physical device layers are the same as global */ + // ParamChecker's physical device layers are the same as global return util_GetLayerProperties(ARRAY_SIZE(pc_global_layers), pc_global_layers, pCount, pProperties); } @@ -392,12 +392,14 @@ VK_LAYER_EXPORT VkResult VKAPI vkCreateImageView(VkDevice device, const VkImageV if (imageEntry != device_data->imageMap.end()) { if (pCreateInfo->subresourceRange.baseMipLevel >= imageEntry->second->mipLevels) { std::stringstream ss; - ss << "vkCreateImageView called with baseMipLevel " << pCreateInfo->subresourceRange.baseMipLevel << " for image " << pCreateInfo->image.handle << " that only has " << imageEntry->second->mipLevels << " mip levels."; + ss << "vkCreateImageView called with baseMipLevel " << pCreateInfo->subresourceRange.baseMipLevel + << " for image " << pCreateInfo->image.handle << " that only has " << imageEntry->second->mipLevels << " mip levels."; skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType)0, 0, 0, IMAGE_VIEW_CREATE_ERROR, "IMAGE", ss.str().c_str()); } if (pCreateInfo->subresourceRange.baseArrayLayer >= imageEntry->second->arraySize) { std::stringstream ss; - ss << "vkCreateImageView called with baseArrayLayer " << pCreateInfo->subresourceRange.baseArrayLayer << " for image " << pCreateInfo->image.handle << " that only has " << imageEntry->second->arraySize << " mip levels."; + ss << "vkCreateImageView called with baseArrayLayer " << pCreateInfo->subresourceRange.baseArrayLayer << " for image " + << pCreateInfo->image.handle << " that only has " << imageEntry->second->arraySize << " mip levels."; skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType)0, 0, 0, IMAGE_VIEW_CREATE_ERROR, "IMAGE", ss.str().c_str()); } if (!pCreateInfo->subresourceRange.numLevels) { @@ -410,12 +412,77 @@ VK_LAYER_EXPORT VkResult VKAPI vkCreateImageView(VkDevice device, const VkImageV ss << "vkCreateImageView called with 0 in pCreateInfo->subresourceRange.arraySize."; skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType)0, 0, 0, IMAGE_VIEW_CREATE_ERROR, "IMAGE", ss.str().c_str()); } - } - // TODO: Image aspect mask must be only VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT - // if the format is a color, depth-only or stencil-only format respectively. If using a depth/stencil format, - // aspectMask must include at least one of VK_IMAGE_ASPECT_DEPTH_BIT and VK_IMAGE_ASPECT_STENCIL_BIT, and may include both. - // Add after image/buffer state tracking is implemented. + // Validate correct image aspect bits for desired formats and format consistency + VkFormat imageFormat = imageEntry->second->format; + VkFormat ivciFormat = pCreateInfo->format; + VkImageAspectFlags aspectMask = pCreateInfo->subresourceRange.aspectMask; + + if (vk_format_is_color(imageFormat)) { + if ((aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) { + std::stringstream ss; + ss << "vkCreateImageView: Color image formats must have the VK_IMAGE_ASPECT_COLOR_BIT set"; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, + (uint64_t)pCreateInfo->image.handle, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", ss.str().c_str()); + } + if ((aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != aspectMask) { + std::stringstream ss; + ss << "vkCreateImageView: Color image formats must have ONLY the VK_IMAGE_ASPECT_COLOR_BIT set"; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, + (uint64_t)pCreateInfo->image.handle, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", ss.str().c_str()); + } + if (VK_FALSE == vk_format_is_color(ivciFormat)) { + std::stringstream ss; + ss << "vkCreateImageView: The image view's format can differ from the parent image's format, but both must be " + << "color formats. ImageFormat is " << string_VkFormat(imageFormat) << " ImageViewFormat is " << string_VkFormat(ivciFormat); + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, + (uint64_t)pCreateInfo->image.handle, 0, IMAGE_INVALID_FORMAT, "IMAGE", ss.str().c_str()); + } + // TODO: Uncompressed formats are compatible if they occupy they same number of bits per pixel. + // Compressed formats are compatible if the only difference between them is the numerical type of + // the uncompressed pixels (e.g. signed vs. unsigned, or sRGB vs. UNORM encoding). + } else if (vk_format_is_depth_and_stencil(imageFormat)) { + if ((aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != + (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + std::stringstream ss; + ss << "vkCreateImageView: Combination depth/stencil image formats must have both VK_IMAGE_ASPECT_DEPTH_BIT and VK_IMAGE_ASPECT_STENCIL_BIT set"; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, + (uint64_t)pCreateInfo->image.handle, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", ss.str().c_str()); + } + if ((aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != aspectMask) { + std::stringstream ss; + ss << "vkCreateImageView: Combination depth/stencil image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT and VK_IMAGE_ASPECT_STENCIL_BIT set"; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, + (uint64_t)pCreateInfo->image.handle, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", ss.str().c_str()); + } + } else if (vk_format_is_depth_only(imageFormat)) { + if ((aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) { + std::stringstream ss; + ss << "vkCreateImageView: Depth-only image formats must have the VK_IMAGE_ASPECT_DEPTH_BIT set"; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, + (uint64_t)pCreateInfo->image.handle, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", ss.str().c_str()); + } + if ((aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != aspectMask) { + std::stringstream ss; + ss << "vkCreateImageView: Depth-only image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT set"; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, + (uint64_t)pCreateInfo->image.handle, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", ss.str().c_str()); + } + } else if (vk_format_is_stencil_only(imageFormat)) { + if ((aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT) { + std::stringstream ss; + ss << "vkCreateImageView: Stencil-only image formats must have the VK_IMAGE_ASPECT_STENCIL_BIT set"; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, + (uint64_t)pCreateInfo->image.handle, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", ss.str().c_str()); + } + if ((aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != aspectMask) { + std::stringstream ss; + ss << "vkCreateImageView: Stencil-only image formats can have only the VK_IMAGE_ASPECT_STENCIL_BIT set"; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, + (uint64_t)pCreateInfo->image.handle, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", ss.str().c_str()); + } + } + } if (skipCall) return VK_ERROR_VALIDATION_FAILED; @@ -608,7 +675,6 @@ VK_LAYER_EXPORT void VKAPI vkCmdCopyImageToBuffer( } } - VK_LAYER_EXPORT void VKAPI vkCmdCopyBufferToImage( VkCmdBuffer cmdBuffer, VkBuffer srcBuffer, @@ -648,13 +714,91 @@ VK_LAYER_EXPORT void VKAPI vkCmdBlitImage( const VkImageBlit *pRegions, VkTexFilter filter) { - // TODO: From the spec -- these validation items will require the image layer to maintain image/buffer state. - // If one of srcImage and destImage images has signed integer format, the other one must also have be signed integer format. - // If one of srcImage and destImage images has unsigned integer format, the other one must also have be an unsigned integer format. - // If the format of srcImage is a depth, stencil, depth stencil or integer-based format then filter must be VK_TEX_FILTER_NEAREST. - // If one of srcImage and destImage images has a format of depth, stencil or depth stencil, the other one must have exactly the same format. - // Additionally the allowed aspect bits in srcSubresource and destSubresource are only VK_IMAGE_ASPECT_DEPTH_BIT and - // VK_IMAGE_ASPECT_STENCIL_BIT and the given aspect must exist in the format of both srcImage and destImage images. + VkBool32 skipCall = VK_FALSE; + layer_data *device_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); + + auto srcImageEntry = device_data->imageMap.find(srcImage.handle); + auto destImageEntry = device_data->imageMap.find(destImage.handle); + + if ((srcImageEntry != device_data->imageMap.end()) && + (destImageEntry != device_data->imageMap.end())) { + + VkFormat srcFormat = srcImageEntry->second->format; + VkFormat dstFormat = destImageEntry->second->format; + + // Validate consistency for signed and unsigned formats + if ((vk_format_is_sint(srcFormat) && !vk_format_is_sint(dstFormat)) || + (vk_format_is_uint(srcFormat) && !vk_format_is_uint(dstFormat))) { + std::stringstream ss; + ss << "vkCmdBlitImage: If one of srcImage and destImage images has signed/unsigned integer format, " + << "the other one must also have signed/unsigned integer format. " + << "Source format is " << string_VkFormat(srcFormat) << " Destinatino format is " << string_VkFormat(dstFormat); + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, + (uint64_t)cmdBuffer, 0, IMAGE_INVALID_FORMAT, "IMAGE", ss.str().c_str()); + } + + // Validate aspect bits and formats for depth/stencil images + if (vk_format_is_depth_or_stencil(srcFormat) || + vk_format_is_depth_or_stencil(dstFormat)) { + if (srcFormat != dstFormat) { + std::stringstream ss; + ss << "vkCmdBlitImage: If one of srcImage and destImage images has a format of depth, stencil or depth " + << "stencil, the other one must have exactly the same format. " + << "Source format is " << string_VkFormat(srcFormat) << " Destinatino format is " << string_VkFormat(dstFormat); + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, + (uint64_t)cmdBuffer, 0, IMAGE_INVALID_FORMAT, "IMAGE", ss.str().c_str()); + } + + for (uint32_t i = 0; i < regionCount; i++) { + VkImageAspectFlags srcAspect = pRegions[i].srcSubresource.aspect; + VkImageAspectFlags dstAspect = pRegions[i].destSubresource.aspect; + + if (srcAspect != dstAspect) { + std::stringstream ss; + ss << "vkCmdBlitImage: Image aspects of depth/stencil images should match"; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_WARN_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, + (uint64_t)cmdBuffer, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", ss.str().c_str()); + } + if (vk_format_is_depth_and_stencil(srcFormat)) { + if (srcAspect != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + std::stringstream ss; + ss << "vkCmdBlitImage: Combination depth/stencil image formats must have both VK_IMAGE_ASPECT_DEPTH_BIT " + << "and VK_IMAGE_ASPECT_STENCIL_BIT set in both the srcImage and destImage"; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, + (uint64_t)cmdBuffer, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", ss.str().c_str()); + } + } else if (vk_format_is_stencil_only(srcFormat)) { + if (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT) { + std::stringstream ss; + ss << "vkCmdBlitImage: Stencil-only image formats must have only the VK_IMAGE_ASPECT_STENCIL_BIT " + << "set in both the srcImage and destImage"; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, + (uint64_t)cmdBuffer, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", ss.str().c_str()); + } + } else if (vk_format_is_depth_only(srcFormat)) { + if (srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) { + std::stringstream ss; + ss << "vkCmdBlitImage: Depth-only image formats must have only the VK_IMAGE_ASPECT_DEPTH " + << "set in both the srcImage and destImage"; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, + (uint64_t)cmdBuffer, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", ss.str().c_str()); + } + } + } + } + + // Validate filter + if (vk_format_is_depth_or_stencil(srcFormat) || + vk_format_is_int(srcFormat)) { + if (filter != VK_TEX_FILTER_NEAREST) { + std::stringstream ss; + ss << "vkCmdBlitImage: If the format of srcImage is a depth, stencil, depth stencil or integer-based format " + << "then filter must be VK_TEX_FILTER_NEAREST."; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, + (uint64_t)cmdBuffer, 0, IMAGE_INVALID_FILTER, "IMAGE", ss.str().c_str()); + } + } + } get_dispatch_table(image_device_table_map, cmdBuffer)->CmdBlitImage(cmdBuffer, srcImage, srcImageLayout, destImage, destImageLayout, regionCount, pRegions, filter); @@ -684,8 +828,8 @@ VK_LAYER_EXPORT void VKAPI vkCmdResolveImage( } } - if ((srcImageEntry != device_data->imageMap.end()) - && (destImageEntry != device_data->imageMap.end())) { + if ((srcImageEntry != device_data->imageMap.end()) && + (destImageEntry != device_data->imageMap.end())) { if (srcImageEntry->second->format != destImageEntry->second->format) { char const str[] = "vkCmdResolveImage called with unmatched source and dest formats."; skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, @@ -720,11 +864,38 @@ VK_LAYER_EXPORT void VKAPI vkGetImageSubresourceLayout( const VkImageSubresource *pSubresource, VkSubresourceLayout *pLayout) { - get_dispatch_table(image_device_table_map, device)->GetImageSubresourceLayout(device, - image, pSubresource, pLayout); + VkBool32 skipCall = VK_FALSE; + layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); + VkFormat format; + + auto imageEntry = device_data->imageMap.find(image.handle); + + // Validate that image aspects match formats + if (imageEntry != device_data->imageMap.end()) { + format = imageEntry->second->format; + if (vk_format_is_color(format)) { + if (pSubresource->aspect != VK_IMAGE_ASPECT_COLOR_BIT) { + std::stringstream ss; + ss << "vkGetImageSubresourceLayout: For color formats, the aspect field of VkImageSubresource must be VK_IMAGE_ASPECT_COLOR."; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, + (uint64_t)image.handle, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", ss.str().c_str()); + } + } else if (vk_format_is_depth_or_stencil(format)) { + if ((pSubresource->aspect != VK_IMAGE_ASPECT_DEPTH_BIT) && + (pSubresource->aspect != VK_IMAGE_ASPECT_STENCIL_BIT)) { + std::stringstream ss; + ss << "vkGetImageSubresourceLayout: For depth/stencil formats, the aspect selects either the depth or stencil image aspect."; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, + (uint64_t)image.handle, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", ss.str().c_str()); + } + } + } + + if (VK_FALSE == skipCall) { + get_dispatch_table(image_device_table_map, device)->GetImageSubresourceLayout(device, + image, pSubresource, pLayout); + } - // TODO: After state tracking for images/buffers is implemented, validate that returned aspects match - // the created formats -- color for color formats, depth|stencil for ds formats } VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice device, const char* funcName) @@ -733,7 +904,7 @@ VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice device, co return NULL; } - /* loader uses this to force layer initialization; device object is wrapped */ + // loader uses this to force layer initialization; device object is wrapped if (!strcmp(funcName, "vkGetDeviceProcAddr")) { initDeviceTable(image_device_table_map, (const VkBaseLayerObject *) device); return (PFN_vkVoidFunction) vkGetDeviceProcAddr; @@ -780,7 +951,7 @@ VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(VkInstance instan return NULL; } - /* loader uses this to force layer initialization; instance object is wrapped */ + // loader uses this to force layer initialization; instance object is wrapped if (!strcmp(funcName, "vkGetInstanceProcAddr")) { initInstanceTable(image_instance_table_map, (const VkBaseLayerObject *) instance); return (PFN_vkVoidFunction) vkGetInstanceProcAddr; diff --git a/layers/image.h b/layers/image.h index cce4b9cd..1392d519 100644 --- a/layers/image.h +++ b/layers/image.h @@ -40,22 +40,26 @@ typedef enum _IMAGE_ERROR IMAGE_MISMATCHED_IMAGE_TYPE, // Image types for source and dest images do not match IMAGE_MISMATCHED_IMAGE_FORMAT, // Image formats for source and dest images do not match IMAGE_INVALID_RESOLVE_SAMPLES, // Image resolve source samples less than two or dest samples greater than one + IMAGE_INVALID_FORMAT, // Operation specifies an invalid format, or there is a format mismatch + IMAGE_INVALID_FILTER, // Operation specifies an invalid filter setting } IMAGE_ERROR; typedef struct _IMAGE_STATE { - uint32_t mipLevels; - uint32_t arraySize; - VkFormat format; - uint32_t samples; + uint32_t mipLevels; + uint32_t arraySize; + VkFormat format; + uint32_t samples; VkImageType imageType; - _IMAGE_STATE():mipLevels(0), arraySize(0), format(VK_FORMAT_UNDEFINED), samples(0), imageType(VK_IMAGE_TYPE_NUM) {}; + VkExtent3D extent; + _IMAGE_STATE():mipLevels(0), arraySize(0), format(VK_FORMAT_UNDEFINED), samples(0), imageType(VK_IMAGE_TYPE_NUM), extent{0} {}; _IMAGE_STATE(const VkImageCreateInfo* pCreateInfo): mipLevels(pCreateInfo->mipLevels), arraySize(pCreateInfo->arrayLayers), format(pCreateInfo->format), samples(pCreateInfo->samples), - imageType(pCreateInfo->imageType) + imageType(pCreateInfo->imageType), + extent(pCreateInfo->extent) {}; } IMAGE_STATE; diff --git a/layers/vk_layer_utils.cpp b/layers/vk_layer_utils.cpp index c4d10f66..b0a483ad 100644 --- a/layers/vk_layer_utils.cpp +++ b/layers/vk_layer_utils.cpp @@ -210,16 +210,20 @@ static const VULKAN_FORMAT_INFO vk_format_table[VK_FORMAT_NUM] = { { 4, 4 }, // [VK_FORMAT_B10G10R10A2_SINT] }; -// Return true if format is a depth-stencil format -bool vk_format_is_ds(VkFormat format) +// Return true if format is a depth or stencil format +bool vk_format_is_depth_or_stencil(VkFormat format) +{ + return (vk_format_is_depth_and_stencil(format) || + vk_format_is_depth_only(format) || + vk_format_is_stencil_only(format)); +} + +// Return true if format contains depth and stencil information +bool vk_format_is_depth_and_stencil(VkFormat format) { bool is_ds = false; switch (format) { - case VK_FORMAT_D16_UNORM: - case VK_FORMAT_D24_UNORM_X8: - case VK_FORMAT_D32_SFLOAT: - case VK_FORMAT_S8_UINT: case VK_FORMAT_D16_UNORM_S8_UINT: case VK_FORMAT_D24_UNORM_S8_UINT: case VK_FORMAT_D32_SFLOAT_S8_UINT: @@ -228,10 +232,33 @@ bool vk_format_is_ds(VkFormat format) default: break; } - return is_ds; } +// Return true if format is a stencil-only format +bool vk_format_is_stencil_only(VkFormat format) +{ + return (format == VK_FORMAT_S8_UINT); +} + +// Return true if format is a depth-only format +bool vk_format_is_depth_only(VkFormat format) +{ + bool is_depth = false; + + switch (format) { + case VK_FORMAT_D16_UNORM: + case VK_FORMAT_D24_UNORM_X8: + case VK_FORMAT_D32_SFLOAT: + is_depth = true; + break; + default: + break; + } + + return is_depth; +} + // Return true if format is of time UNORM bool vk_format_is_norm(VkFormat format) { @@ -305,51 +332,73 @@ bool vk_format_is_norm(VkFormat format) return is_norm; }; + // Return true if format is an integer format bool vk_format_is_int(VkFormat format) { - bool is_int = false; + return (vk_format_is_sint(format) || vk_format_is_uint(format)); +} + +// Return true if format is an unsigned integer format +bool vk_format_is_uint(VkFormat format) +{ + bool is_uint = false; switch (format) { case VK_FORMAT_R8_UINT: - case VK_FORMAT_R8_SINT: case VK_FORMAT_R8G8_UINT: - case VK_FORMAT_R8G8_SINT: case VK_FORMAT_R8G8B8_UINT: - case VK_FORMAT_R8G8B8_SINT: case VK_FORMAT_R8G8B8A8_UINT: - case VK_FORMAT_R8G8B8A8_SINT: case VK_FORMAT_R10G10B10A2_UINT: - case VK_FORMAT_R10G10B10A2_SINT: case VK_FORMAT_R16_UINT: - case VK_FORMAT_R16_SINT: case VK_FORMAT_R16G16_UINT: - case VK_FORMAT_R16G16_SINT: case VK_FORMAT_R16G16B16_UINT: - case VK_FORMAT_R16G16B16_SINT: case VK_FORMAT_R16G16B16A16_UINT: - case VK_FORMAT_R16G16B16A16_SINT: case VK_FORMAT_R32_UINT: - case VK_FORMAT_R32_SINT: case VK_FORMAT_R32G32_UINT: - case VK_FORMAT_R32G32_SINT: case VK_FORMAT_R32G32B32_UINT: - case VK_FORMAT_R32G32B32_SINT: case VK_FORMAT_R32G32B32A32_UINT: - case VK_FORMAT_R32G32B32A32_SINT: case VK_FORMAT_B8G8R8_UINT: - case VK_FORMAT_B8G8R8_SINT: case VK_FORMAT_B8G8R8A8_UINT: - case VK_FORMAT_B8G8R8A8_SINT: case VK_FORMAT_B10G10R10A2_UINT: + is_uint = true; + break; + default: + break; + } + + return is_uint; +} + +// Return true if format is a signed integer format +bool vk_format_is_sint(VkFormat format) +{ + bool is_sint = false; + + switch (format) { + case VK_FORMAT_R8_SINT: + case VK_FORMAT_R8G8_SINT: + case VK_FORMAT_R8G8B8_SINT: + case VK_FORMAT_R8G8B8A8_SINT: + case VK_FORMAT_R10G10B10A2_SINT: + case VK_FORMAT_R16_SINT: + case VK_FORMAT_R16G16_SINT: + case VK_FORMAT_R16G16B16_SINT: + case VK_FORMAT_R16G16B16A16_SINT: + case VK_FORMAT_R32_SINT: + case VK_FORMAT_R32G32_SINT: + case VK_FORMAT_R32G32B32_SINT: + case VK_FORMAT_R32G32B32A32_SINT: + case VK_FORMAT_B8G8R8_SINT: + case VK_FORMAT_B8G8R8A8_SINT: case VK_FORMAT_B10G10R10A2_SINT: - is_int = true; + is_sint = true; break; default: break; } - return is_int; + return is_sint; } // Return true if format is a floating-point format diff --git a/layers/vk_layer_utils.h b/layers/vk_layer_utils.h index bd5eac86..376f81b2 100644 --- a/layers/vk_layer_utils.h +++ b/layers/vk_layer_utils.h @@ -37,15 +37,20 @@ static inline bool vk_format_is_undef(VkFormat format) return (format == VK_FORMAT_UNDEFINED); } -bool vk_format_is_ds(VkFormat format); +bool vk_format_is_depth_or_stencil(VkFormat format); +bool vk_format_is_depth_and_stencil(VkFormat format); +bool vk_format_is_depth_only(VkFormat format); +bool vk_format_is_stencil_only(VkFormat format); static inline bool vk_format_is_color(VkFormat format) { - return !(vk_format_is_undef(format) || vk_format_is_ds(format)); + return !(vk_format_is_undef(format) || vk_format_is_depth_or_stencil(format)); } bool vk_format_is_norm(VkFormat format); bool vk_format_is_int(VkFormat format); +bool vk_format_is_sint(VkFormat format); +bool vk_format_is_uint(VkFormat format); bool vk_format_is_float(VkFormat format); bool vk_format_is_srgb(VkFormat format); bool vk_format_is_compressed(VkFormat format); diff --git a/layers/vk_validation_layer_details.md b/layers/vk_validation_layer_details.md index 132bd6df..6fcbcd9d 100644 --- a/layers/vk_validation_layer_details.md +++ b/layers/vk_validation_layer_details.md @@ -112,11 +112,11 @@ Additional work to be done ## Image -### Image Overview +### Image Layer Overview The Image layer is responsible for validating format-related information and enforcing format restrictions. -### Image Details Table +### Image Layer Details Table DETAILS TABLE PENDING @@ -126,11 +126,13 @@ DETAILS TABLE PENDING | RenderPass Attachments | Validates that attachment image layouts, loadOps, and storeOps are valid Vulkan values | RENDERPASS_INVALID_ATTACHMENT | vkCreateRenderPass | TBD | NA | | Subpass DS Settings | Verifies that if there is no depth attachment then the subpass attachment is set to VK_ATTACHMENT_UNUSED | RENDERPASS_INVALID_DS_ATTACHMENT | vkCreateRenderPass | TBD | NA | | View Creation | Verify that requested Image View Creation parameters are reasonable for the image that the view is being created for | VIEW_CREATE_ERROR | vkCreateImageView | TBD | NA | -| Image Aspects | Verify that Image commands are using valid Image Aspect flags | INVALID_IMAGE_ASPECT | vkCmdClearColorImage vkCmdClearDepthStencilImage vkCmdClearAttachments vkCmdCopyImage vkCmdCopyImageToBuffer vkCmdCopyBufferToImage vkCmdResolveImage | TBD | NA | +| Image Aspects | Verify that Image commands are using valid Image Aspect flags | INVALID_IMAGE_ASPECT | vkCreateImageView vkCmdClearColorImage vkCmdClearDepthStencilImage vkCmdClearAttachments vkCmdCopyImage vkCmdCopyImageToBuffer vkCmdCopyBufferToImage vkCmdResolveImage vkCmdBlitImage | InvalidImageViewAspect | NA | | Image Aspect Mismatch | Verify that Image commands with source and dest images use matching aspect flags | MISMATCHED_IMAGE_ASPECT | vkCmdCopyImage | TBD | NA | | Image Type Mismatch | Verify that Image commands with source and dest images use matching types | MISMATCHED_IMAGE_TYPE | vkCmdCopyImage vkCmdResolveImage | CopyImageTypeMismatch ResolveImageTypeMismatch | NA | | Image Format Mismatch | Verify that Image commands with source and dest images use matching formats | MISMATCHED_IMAGE_FORMAT | vkCmdCopyImage vkCmdResolveImage | CopyImageDepthStencilFormatMismatch ResolveImageFormatMismatch | NA | | Resolve Sample Count | Verifies that source and dest images sample counts are valid | INVALID_RESOLVE_SAMPLES | vkCmdResolveImage | ResolveImageHighSampleCount ResolveImageLowSampleCount | NA | +| Verify Format | Verifies the formats are valid for this image operation | INVALID_FORMAT | vkCreateImageView vkCmdBlitImage | TBD | NA | +| Verify Correct Image Filter| Verifies that specified filter is valid | INVALID_FILTER | vkCmdBlitImage | TBD | NA | | NA | Enum used for informational messages | NONE | | NA | None | ### Image Pending Work |
