From 8a5ab8aadfd719f8d57858aeb6d5370ad0e89095 Mon Sep 17 00:00:00 2001 From: Mike Stroyan Date: Fri, 25 Sep 2015 13:39:21 -0600 Subject: intel,layers,tests: move cmd_meta errors to validation Add checks for alignment in DeviceLimits layer. Add checks for type, format and sample count in Images layer. Remove such checks from intel icd. Add new validations to layer_validation_tests. --- layers/device_limits.cpp | 64 +++++++++++++++++++++++++++++++++++ layers/image.cpp | 59 ++++++++++++++++++++++++++++++-- layers/image.h | 18 ++++++++-- layers/vk_validation_layer_details.md | 5 +++ 4 files changed, 140 insertions(+), 6 deletions(-) diff --git a/layers/device_limits.cpp b/layers/device_limits.cpp index b991a86a..12ec4835 100644 --- a/layers/device_limits.cpp +++ b/layers/device_limits.cpp @@ -552,6 +552,66 @@ VK_LAYER_EXPORT VkResult VKAPI vkCreateImage( return result; } +VK_LAYER_EXPORT void VKAPI vkCmdUpdateBuffer( + VkCmdBuffer cmdBuffer, + VkBuffer destBuffer, + VkDeviceSize destOffset, + VkDeviceSize dataSize, + const uint32_t* pData) +{ + layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); + + // destOffset is the byte offset into the buffer to start updating and must be a multiple of 4. + if (destOffset & 3) { + layer_data *my_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); + if (log_msg(my_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType)0, 0, 0, 1, "DL", + "vkCmdUpdateBuffer parameter, VkDeviceSize destOffset, is not a multiple of 4")) { + return; + } + } + + // dataSize is the number of bytes to update, which must be a multiple of 4. + if (dataSize & 3) { + layer_data *my_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); + if (log_msg(my_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType)0, 0, 0, 1, "DL", + "vkCmdUpdateBuffer parameter, VkDeviceSize dataSize, is not a multiple of 4")) { + return; + } + } + + dev_data->device_dispatch_table->CmdUpdateBuffer(cmdBuffer, destBuffer, destOffset, dataSize, pData); +} + +VK_LAYER_EXPORT void VKAPI vkCmdFillBuffer( + VkCmdBuffer cmdBuffer, + VkBuffer destBuffer, + VkDeviceSize destOffset, + VkDeviceSize fillSize, + uint32_t data) +{ + layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); + + // destOffset is the byte offset into the buffer to start filling and must be a multiple of 4. + if (destOffset & 3) { + layer_data *my_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); + if (log_msg(my_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType)0, 0, 0, 1, "DL", + "vkCmdFillBuffer parameter, VkDeviceSize destOffset, is not a multiple of 4")) { + return; + } + } + + // fillSize is the number of bytes to fill, which must be a multiple of 4. + if (fillSize & 3) { + layer_data *my_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); + if (log_msg(my_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType)0, 0, 0, 1, "DL", + "vkCmdFillBuffer parameter, VkDeviceSize fillSize, is not a multiple of 4")) { + return; + } + } + + dev_data->device_dispatch_table->CmdFillBuffer(cmdBuffer, destBuffer, destOffset, fillSize, data); +} + VK_LAYER_EXPORT VkResult VKAPI vkDbgCreateMsgCallback( VkInstance instance, VkFlags msgFlags, @@ -610,6 +670,10 @@ VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice dev, const return (PFN_vkVoidFunction) vkCreateCommandBuffer; if (!strcmp(funcName, "vkDestroyCommandBuffer")) return (PFN_vkVoidFunction) vkDestroyCommandBuffer; + if (!strcmp(funcName, "vkCmdUpdateBuffer")) + return (PFN_vkVoidFunction) vkCmdUpdateBuffer; + if (!strcmp(funcName, "vkCmdFillBuffer")) + return (PFN_vkVoidFunction) vkCmdFillBuffer; VkLayerDispatchTable* pTable = my_data->device_dispatch_table; { diff --git a/layers/image.cpp b/layers/image.cpp index 912c23f4..93579c72 100644 --- a/layers/image.cpp +++ b/layers/image.cpp @@ -43,6 +43,7 @@ #include "vk_layer_table.h" #include "vk_layer_data.h" #include "vk_layer_extension_utils.h" +#include "vk_layer_utils.h" using namespace std; @@ -518,25 +519,51 @@ VK_LAYER_EXPORT void VKAPI vkCmdCopyImage( const VkImageCopy *pRegions) { 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); // For each region, src aspect mask must match dest aspect mask // For each region, color aspects cannot be mixed with depth/stencil aspects for (uint32_t i = 0; i < regionCount; i++) { if (pRegions[i].srcSubresource.aspect != pRegions[i].destSubresource.aspect) { - layer_data *device_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); char const str[] = "vkCmdCopyImage: Src and dest aspectMasks for each region must match"; skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)cmdBuffer, 0, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str); } if ((pRegions[i].srcSubresource.aspect & VK_IMAGE_ASPECT_COLOR) && (pRegions[i].srcSubresource.aspect & (VK_IMAGE_ASPECT_DEPTH | VK_IMAGE_ASPECT_STENCIL))) { - layer_data *device_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); char const str[] = "vkCmdCopyImage aspectMask cannot specify both COLOR and DEPTH/STENCIL aspects"; 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", str); } } + if ((srcImageEntry != device_data->imageMap.end()) + && (destImageEntry != device_data->imageMap.end())) { + if (srcImageEntry->second->imageType != destImageEntry->second->imageType) { + char const str[] = "vkCmdCopyImage called with unmatched source and dest image types."; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, + (uint64_t)cmdBuffer, 0, IMAGE_MISMATCHED_IMAGE_TYPE, "IMAGE", str); + } + // Check that format is same size or exact stencil/depth + if (is_depth_format(srcImageEntry->second->format)) { + if (srcImageEntry->second->format != destImageEntry->second->format) { + char const str[] = "vkCmdCopyImage called with unmatched source and dest image depth/stencil formats."; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, + (uint64_t)cmdBuffer, 0, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str); + } + } else { + size_t srcSize = vk_format_get_size(srcImageEntry->second->format); + size_t destSize = vk_format_get_size(destImageEntry->second->format); + if (srcSize != destSize) { + char const str[] = "vkCmdCopyImage called with unmatched source and dest image format sizes."; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, + (uint64_t)cmdBuffer, 0, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str); + } + } + } + if (VK_FALSE == skipCall) { get_dispatch_table(image_device_table_map, cmdBuffer)->CmdCopyImage(cmdBuffer, srcImage, srcImageLayout, destImage, destImageLayout, regionCount, pRegions); @@ -634,18 +661,44 @@ VK_LAYER_EXPORT void VKAPI vkCmdResolveImage( const VkImageResolve *pRegions) { 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); // For each region, src and dest image aspect must be color only for (uint32_t i = 0; i < regionCount; i++) { if ((pRegions[i].srcSubresource.aspect != VK_IMAGE_ASPECT_COLOR) || (pRegions[i].destSubresource.aspect != VK_IMAGE_ASPECT_COLOR)) { - layer_data *device_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); char const str[] = "vkCmdResolveImage: src and dest aspectMasks for each region must specify only VK_IMAGE_ASPECT_COLOR_BIT"; 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", str); } } + 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, + (uint64_t)cmdBuffer, 0, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str); + } + if (srcImageEntry->second->imageType != destImageEntry->second->imageType) { + char const str[] = "vkCmdResolveImage called with unmatched source and dest image types."; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, + (uint64_t)cmdBuffer, 0, IMAGE_MISMATCHED_IMAGE_TYPE, "IMAGE", str); + } + if (srcImageEntry->second->samples <= 1) { + char const str[] = "vkCmdResolveImage called with source sample count less than 2."; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, + (uint64_t)cmdBuffer, 0, IMAGE_INVALID_RESOLVE_SAMPLES, "IMAGE", str); + } + if (destImageEntry->second->samples > 1) { + char const str[] = "vkCmdResolveImage called with dest sample count greater than 1."; + skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, + (uint64_t)cmdBuffer, 0, IMAGE_INVALID_RESOLVE_SAMPLES, "IMAGE", str); + } + } + if (VK_FALSE == skipCall) { get_dispatch_table(image_device_table_map, cmdBuffer)->CmdResolveImage(cmdBuffer, srcImage, srcImageLayout, destImage, destImageLayout, regionCount, pRegions); diff --git a/layers/image.h b/layers/image.h index 79c49280..e1738c84 100644 --- a/layers/image.h +++ b/layers/image.h @@ -27,7 +27,7 @@ #include "vk_layer_config.h" #include "vk_layer_logging.h" -// Draw State ERROR codes +// Image ERROR codes typedef enum _IMAGE_ERROR { IMAGE_NONE, // Used for INFO & other non-error messages @@ -37,14 +37,26 @@ typedef enum _IMAGE_ERROR IMAGE_INVALID_IMAGE_ASPECT, // Image aspect mask bits are invalid for this API call IMAGE_MISMATCHED_IMAGE_ASPECT, // Image aspect masks for source and dest images do not match IMAGE_VIEW_CREATE_ERROR, // Error occurred trying to create Image View + 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_ERROR; typedef struct _IMAGE_STATE { uint32_t mipLevels; uint32_t arraySize; - _IMAGE_STATE():mipLevels(0), arraySize(0) {}; - _IMAGE_STATE(const VkImageCreateInfo* pCreateInfo):mipLevels(pCreateInfo->mipLevels), arraySize(pCreateInfo->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) {}; + _IMAGE_STATE(const VkImageCreateInfo* pCreateInfo): + mipLevels(pCreateInfo->mipLevels), + arraySize(pCreateInfo->arraySize), + format(pCreateInfo->format), + samples(pCreateInfo->samples), + imageType(pCreateInfo->imageType) + {}; } IMAGE_STATE; #endif // IMAGE_H diff --git a/layers/vk_validation_layer_details.md b/layers/vk_validation_layer_details.md index e3d1d697..d40f52e7 100644 --- a/layers/vk_validation_layer_details.md +++ b/layers/vk_validation_layer_details.md @@ -124,6 +124,9 @@ DETAILS TABLE PENDING | 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 vkCmdClearDepthStencilAttachment vkCmdCopyImage vkCmdCopyImageToBuffer vkCmdCopyBufferToImage vkCmdResolveImage | TBD | 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 | | NA | Enum used for informational messages | NONE | | NA | None | ### Image Pending Work @@ -290,6 +293,8 @@ For the second category of errors, DeviceLimits stores its own internal record o | Feature Request | Attempting to vkCreateDevice with a feature that is not supported by the underlying physical device. | INVALID_FEATURE_REQUESTED | vkCreateDevice | NA | Add validation test | | Valid Image Extents | When creating an Image, ensure that image extents are within device limits for the specified format | LIMITS_VIOLATION | vkCreateImage | CreateImageLimitsViolationWidth | NA | | Valid Image Resource Size | When creating an image, ensure the the total image resource size is less than the queried device maximum resource size | LIMITS_VIOLATION | vkCreateImage | CreateImageResourceSizeViolation | NA | +| Alignment | When updating a buffer, data should be aligned on 4 byte boundaries | LIMITS_VIOLATION | vkCmdUpdateBuffer | UpdateBufferAlignment | NA | +| Alignment | When filling a buffer, data should be aligned on 4 byte boundaries | LIMITS_VIOLATION | vkCmdFillBuffer | UpdateBufferAlignment | NA | | NA | Enum used for informational messages | NONE | | NA | None | ### Device Limitations Pending Work -- cgit v1.2.3