aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--layers/device_limits.cpp64
-rw-r--r--layers/image.cpp59
-rw-r--r--layers/image.h18
-rw-r--r--layers/vk_validation_layer_details.md5
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