aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Lobodzinski <mark@lunarg.com>2015-11-12 15:14:35 -0700
committerMark Lobodzinski <mark@lunarg.com>2015-11-20 08:49:14 -0700
commita9a34aa70ececc2f38b4cfe0f0434b3563af67eb (patch)
tree65f774d110fc5d0a995006af1afb2b8fabd75a85
parent1047d2eb742521b57b7fbf9f9a7108fc10428b6e (diff)
downloadusermoji-a9a34aa70ececc2f38b4cfe0f0434b3563af67eb.tar.xz
layers: LX196, validate createImage paramters against format limits
Relocated some validation from DeviceLimits layer to Image layer, added additional per-format limit validation for CreateImage parameters.
-rw-r--r--layers/device_limits.cpp57
-rw-r--r--layers/image.cpp106
-rw-r--r--layers/image.h1
-rw-r--r--layers/vk_validation_layer_details.md1
4 files changed, 93 insertions, 72 deletions
diff --git a/layers/device_limits.cpp b/layers/device_limits.cpp
index a08fb26a..7dbca10f 100644
--- a/layers/device_limits.cpp
+++ b/layers/device_limits.cpp
@@ -490,61 +490,6 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue(VkDevice device, uin
dev_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(
- VkDevice device,
- const VkImageCreateInfo *pCreateInfo,
- const VkAllocationCallbacks* pAllocator,
- VkImage *pImage)
-{
- VkBool32 skipCall = VK_FALSE;
- VkResult result = VK_ERROR_VALIDATION_FAILED;
- VkImageFormatProperties ImageFormatProperties = {0};
-
- layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- VkPhysicalDevice physicalDevice = dev_data->physicalDevice;
- layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
- // Internal call to get format info. Still goes through layers, could potentially go directly to ICD.
- phy_dev_data->instance_dispatch_table->GetPhysicalDeviceImageFormatProperties(
- physicalDevice, pCreateInfo->format, pCreateInfo->imageType, pCreateInfo->tiling,
- pCreateInfo->usage, pCreateInfo->flags, &ImageFormatProperties);
-
- VkDeviceSize imageGranularity = phy_dev_data->physicalDeviceProperties.limits.bufferImageGranularity;
- imageGranularity = imageGranularity == 1 ? 0 : imageGranularity;
-
- if ((pCreateInfo->extent.depth > ImageFormatProperties.maxExtent.depth) ||
- (pCreateInfo->extent.width > ImageFormatProperties.maxExtent.width) ||
- (pCreateInfo->extent.height > ImageFormatProperties.maxExtent.height)) {
- skipCall |= log_msg(phy_dev_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, (uint64_t)pImage, 0,
- DEVLIMITS_LIMITS_VIOLATION, "DL",
- "CreateImage extents exceed allowable limits for format: "
- "Width = %d Height = %d Depth = %d: Limits for Width = %d Height = %d Depth = %d for format %s.",
- pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth,
- ImageFormatProperties.maxExtent.width, ImageFormatProperties.maxExtent.height, ImageFormatProperties.maxExtent.depth,
- string_VkFormat(pCreateInfo->format));
-
- }
-
- uint64_t totalSize = ((uint64_t)pCreateInfo->extent.width *
- (uint64_t)pCreateInfo->extent.height *
- (uint64_t)pCreateInfo->extent.depth *
- (uint64_t)pCreateInfo->arrayLayers *
- (uint64_t)pCreateInfo->samples *
- (uint64_t)vk_format_get_size(pCreateInfo->format) +
- (uint64_t)imageGranularity ) & ~(uint64_t)imageGranularity;
-
- if (totalSize > ImageFormatProperties.maxResourceSize) {
- skipCall |= log_msg(phy_dev_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, (uint64_t)pImage, 0,
- DEVLIMITS_LIMITS_VIOLATION, "DL",
- "CreateImage resource size exceeds allowable maximum "
- "Image resource size = %#" PRIxLEAST64 ", maximum resource size = %#" PRIxLEAST64 " ",
- totalSize, ImageFormatProperties.maxResourceSize);
- }
- if (VK_FALSE == skipCall) {
- result = dev_data->device_dispatch_table->CreateImage(device, pCreateInfo, pAllocator, pImage);
- }
- return result;
-}
-
VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdUpdateBuffer(
VkCommandBuffer commandBuffer,
VkBuffer dstBuffer,
@@ -651,8 +596,6 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD
return (PFN_vkVoidFunction) vkDestroyDevice;
if (!strcmp(funcName, "vkGetDeviceQueue"))
return (PFN_vkVoidFunction) vkGetDeviceQueue;
- if (!strcmp(funcName, "vkCreateImage"))
- return (PFN_vkVoidFunction) vkCreateImage;
if (!strcmp(funcName, "CreateCommandPool"))
return (PFN_vkVoidFunction) vkCreateCommandPool;
if (!strcmp(funcName, "DestroyCommandPool"))
diff --git a/layers/image.cpp b/layers/image.cpp
index 59bd108e..3a37530e 100644
--- a/layers/image.cpp
+++ b/layers/image.cpp
@@ -52,18 +52,21 @@ using namespace std;
using namespace std;
struct layer_data {
- debug_report_data *report_data;
- std::vector<VkDbgMsgCallback> logging_callback;
- VkLayerDispatchTable* device_dispatch_table;
- VkLayerInstanceDispatchTable* instance_dispatch_table;
- VkPhysicalDevice physicalDevice;
+ debug_report_data *report_data;
+ vector<VkDbgMsgCallback> logging_callback;
+ VkLayerDispatchTable* device_dispatch_table;
+ VkLayerInstanceDispatchTable *instance_dispatch_table;
+ VkPhysicalDevice physicalDevice;
+ VkPhysicalDeviceProperties physicalDeviceProperties;
+
unordered_map<VkImage, IMAGE_STATE> imageMap;
layer_data() :
report_data(nullptr),
device_dispatch_table(nullptr),
instance_dispatch_table(nullptr),
- physicalDevice(0)
+ physicalDevice(0),
+ physicalDeviceProperties()
{};
};
@@ -163,6 +166,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice p
device_data->physicalDevice = physicalDevice;
}
+ instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice, &(device_data->physicalDeviceProperties));
+
return result;
}
@@ -263,26 +268,89 @@ static inline uint32_t validate_VkImageLayoutKHR(VkImageLayout input_value)
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage)
{
- VkBool32 skipCall = VK_FALSE;
- layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- if(pCreateInfo->format != VK_FORMAT_UNDEFINED)
+ VkBool32 skipCall = VK_FALSE;
+ VkResult result = VK_ERROR_VALIDATION_FAILED;
+ VkImageFormatProperties ImageFormatProperties = {0};
+
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ VkPhysicalDevice physicalDevice = device_data->physicalDevice;
+ layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
+
+ if (pCreateInfo->format != VK_FORMAT_UNDEFINED)
{
VkFormatProperties properties;
- get_my_data_ptr(get_dispatch_key(device_data->physicalDevice), layer_data_map)->instance_dispatch_table->GetPhysicalDeviceFormatProperties(
+ phy_dev_data->instance_dispatch_table->GetPhysicalDeviceFormatProperties(
device_data->physicalDevice, pCreateInfo->format, &properties);
- if((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0))
+ if ((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0))
{
char const str[] = "vkCreateImage parameter, VkFormat pCreateInfo->format, contains unsupported format";
skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_WARN_BIT, (VkDbgObjectType)0, 0, 0, IMAGE_FORMAT_UNSUPPORTED, "IMAGE", str);
}
}
- if (skipCall)
- return VK_ERROR_VALIDATION_FAILED;
- VkResult result = device_data->device_dispatch_table->CreateImage(device, pCreateInfo, pAllocator, pImage);
+ // Internal call to get format info. Still goes through layers, could potentially go directly to ICD.
+ phy_dev_data->instance_dispatch_table->GetPhysicalDeviceImageFormatProperties(
+ physicalDevice, pCreateInfo->format, pCreateInfo->imageType, pCreateInfo->tiling,
+ pCreateInfo->usage, pCreateInfo->flags, &ImageFormatProperties);
+
+ VkDeviceSize imageGranularity = device_data->physicalDeviceProperties.limits.bufferImageGranularity;
+ imageGranularity = imageGranularity == 1 ? 0 : imageGranularity;
+
+ if ((pCreateInfo->extent.depth > ImageFormatProperties.maxExtent.depth) ||
+ (pCreateInfo->extent.width > ImageFormatProperties.maxExtent.width) ||
+ (pCreateInfo->extent.height > ImageFormatProperties.maxExtent.height)) {
+ skipCall |= log_msg(phy_dev_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, (uint64_t)pImage, 0,
+ IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
+ "CreateImage extents exceed allowable limits for format: "
+ "Width = %d Height = %d Depth = %d: Limits for Width = %d Height = %d Depth = %d for format %s.",
+ pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth,
+ ImageFormatProperties.maxExtent.width, ImageFormatProperties.maxExtent.height, ImageFormatProperties.maxExtent.depth,
+ string_VkFormat(pCreateInfo->format));
+
+ }
+
+ uint64_t totalSize = ((uint64_t)pCreateInfo->extent.width *
+ (uint64_t)pCreateInfo->extent.height *
+ (uint64_t)pCreateInfo->extent.depth *
+ (uint64_t)pCreateInfo->arrayLayers *
+ (uint64_t)pCreateInfo->samples *
+ (uint64_t)vk_format_get_size(pCreateInfo->format) +
+ (uint64_t)imageGranularity ) & ~(uint64_t)imageGranularity;
+
+ if (totalSize > ImageFormatProperties.maxResourceSize) {
+ skipCall |= log_msg(phy_dev_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, (uint64_t)pImage, 0,
+ IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
+ "CreateImage resource size exceeds allowable maximum "
+ "Image resource size = %#" PRIxLEAST64 ", maximum resource size = %#" PRIxLEAST64 " ",
+ totalSize, ImageFormatProperties.maxResourceSize);
+ }
+
+ if (pCreateInfo->mipLevels > ImageFormatProperties.maxMipLevels) {
+ skipCall |= log_msg(phy_dev_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, (uint64_t)pImage, 0,
+ IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
+ "CreateImage mipLevels=%d exceeds allowable maximum supported by format of %d",
+ pCreateInfo->mipLevels, ImageFormatProperties.maxMipLevels);
+ }
+
+ if (pCreateInfo->arrayLayers > ImageFormatProperties.maxArrayLayers) {
+ skipCall |= log_msg(phy_dev_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, (uint64_t)pImage, 0,
+ IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
+ "CreateImage arrayLayers=%d exceeds allowable maximum supported by format of %d",
+ pCreateInfo->arrayLayers, ImageFormatProperties.maxArrayLayers);
+ }
+
+ if ((pCreateInfo->samples & ImageFormatProperties.sampleCounts) == 0) {
+ skipCall |= log_msg(phy_dev_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_IMAGE, (uint64_t)pImage, 0,
+ IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
+ "CreateImage samples %s is not supported by format 0x%.8X",
+ string_VkSampleCountFlagBits(pCreateInfo->samples), ImageFormatProperties.sampleCounts);
+ }
- if(result == VK_SUCCESS) {
+ if (VK_FALSE == skipCall) {
+ result = device_data->device_dispatch_table->CreateImage(device, pCreateInfo, pAllocator, pImage);
+ }
+ if (result == VK_SUCCESS) {
device_data->imageMap[*pImage] = IMAGE_STATE(pCreateInfo);
}
return result;
@@ -988,6 +1056,12 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout(
}
}
+VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties)
+{
+ layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
+ phy_dev_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice, pProperties);
+}
+
VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)
{
if (device == NULL) {
@@ -1075,6 +1149,8 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(V
return (PFN_vkVoidFunction) vkEnumerateDeviceLayerProperties;
if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
return (PFN_vkVoidFunction) vkEnumerateDeviceExtensionProperties;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceProperties"))
+ return (PFN_vkVoidFunction) vkGetPhysicalDeviceProperties;
PFN_vkVoidFunction fptr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
if(fptr)
diff --git a/layers/image.h b/layers/image.h
index 2ddd4eba..cbe61f81 100644
--- a/layers/image.h
+++ b/layers/image.h
@@ -45,6 +45,7 @@ typedef enum _IMAGE_ERROR
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_INVALID_FORMAT_LIMITS_VIOLATION, // Device limits for this format have been exceeded
} IMAGE_ERROR;
typedef struct _IMAGE_STATE
diff --git a/layers/vk_validation_layer_details.md b/layers/vk_validation_layer_details.md
index 4e06cb20..e6588d4a 100644
--- a/layers/vk_validation_layer_details.md
+++ b/layers/vk_validation_layer_details.md
@@ -141,6 +141,7 @@ DETAILS TABLE PENDING
| 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 |
+| Verify Image Format Limits | Verifies that image creation parameters are with the device format limits | INVALID_FORMAT_LIMITS_VIOLATION | vkCreateImage | TBD | NA |
| NA | Enum used for informational messages | NONE | | NA | None |
### Image Pending Work