diff options
| -rw-r--r-- | layers/device_limits.cpp | 64 | ||||
| -rw-r--r-- | layers/image.cpp | 59 | ||||
| -rw-r--r-- | layers/image.h | 18 | ||||
| -rw-r--r-- | 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 |
