From 0ce7bb37372584dafecbd6a1de8a0e24dfdecddd Mon Sep 17 00:00:00 2001 From: Cort Stratton Date: Fri, 17 Feb 2017 12:50:01 -0800 Subject: layers: GH373 Add memory size/align tests&checks --- layers/core_validation.cpp | 71 ++++++++++++++++++++++++--------- layers/vk_validation_error_database.txt | 8 ++-- 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 2bc724d5..28bffcd9 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -5453,12 +5453,11 @@ static bool ValidateMemoryTypes(const layer_data *dev_data, const DEVICE_MEM_INF return skip_call; } -static bool PreCallValidateBindBufferMemory(layer_data *dev_data, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) { +static bool PreCallValidateBindBufferMemory(layer_data *dev_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VkDeviceMemory mem, + VkDeviceSize memoryOffset) { bool skip = false; - std::unique_lock lock(global_lock); - - auto buffer_state = GetBufferState(dev_data, buffer); if (buffer_state) { + std::unique_lock lock(global_lock); // Track objects tied to memory uint64_t buffer_handle = reinterpret_cast(buffer); skip = ValidateSetMemBinding(dev_data, mem, buffer_handle, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "vkBindBufferMemory()"); @@ -5497,6 +5496,18 @@ static bool PreCallValidateBindBufferMemory(layer_data *dev_data, VkBuffer buffe memoryOffset, buffer_state->requirements.alignment, validation_error_map[VALIDATION_ERROR_02174]); } + // Validate memory requirements size + if (buffer_state->requirements.size > (mem_info->alloc_info.allocationSize - memoryOffset)) { + skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, + buffer_handle, __LINE__, VALIDATION_ERROR_02175, "DS", + "vkBindBufferMemory(): memory size minus memoryOffset is 0x%" PRIxLEAST64 + " but must be at least as large as " + "VkMemoryRequirements::size value 0x%" PRIxLEAST64 + ", returned from a call to vkGetBufferMemoryRequirements with buffer. %s", + mem_info->alloc_info.allocationSize - memoryOffset, buffer_state->requirements.size, + validation_error_map[VALIDATION_ERROR_02175]); + } + // Validate device limits alignments static const VkBufferUsageFlagBits usage_list[3] = { static_cast(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT), @@ -5534,10 +5545,10 @@ static bool PreCallValidateBindBufferMemory(layer_data *dev_data, VkBuffer buffe return skip; } -static void PostCallRecordBindBufferMemory(layer_data *dev_data, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) { - std::unique_lock lock(global_lock); - auto buffer_state = GetBufferState(dev_data, buffer); +static void PostCallRecordBindBufferMemory(layer_data *dev_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VkDeviceMemory mem, + VkDeviceSize memoryOffset) { if (buffer_state) { + std::unique_lock lock(global_lock); // Track bound memory range information auto mem_info = GetMemObjInfo(dev_data, mem); if (mem_info) { @@ -5557,11 +5568,12 @@ static void PostCallRecordBindBufferMemory(layer_data *dev_data, VkBuffer buffer VKAPI_ATTR VkResult VKAPI_CALL BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) { layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; - bool skip = PreCallValidateBindBufferMemory(dev_data, buffer, mem, memoryOffset); + auto buffer_state = GetBufferState(dev_data, buffer); + bool skip = PreCallValidateBindBufferMemory(dev_data, buffer, buffer_state, mem, memoryOffset); if (!skip) { result = dev_data->dispatch_table.BindBufferMemory(device, buffer, mem, memoryOffset); if (result == VK_SUCCESS) { - PostCallRecordBindBufferMemory(dev_data, buffer, mem, memoryOffset); + PostCallRecordBindBufferMemory(dev_data, buffer, buffer_state, mem, memoryOffset); } } return result; @@ -10062,12 +10074,11 @@ VKAPI_ATTR VkResult VKAPI_CALL InvalidateMappedMemoryRanges(VkDevice device, uin return result; } -static bool PreCallValidateBindImageMemory(layer_data *dev_data, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) { +static bool PreCallValidateBindImageMemory(layer_data *dev_data, VkImage image, IMAGE_STATE *image_state, VkDeviceMemory mem, + VkDeviceSize memoryOffset) { bool skip = false; - std::unique_lock lock(global_lock); - - auto image_state = GetImageState(dev_data, image); if (image_state) { + std::unique_lock lock(global_lock); // Track objects tied to memory uint64_t image_handle = reinterpret_cast(image); skip = ValidateSetMemBinding(dev_data, mem, image_handle, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "vkBindImageMemory()"); @@ -10094,14 +10105,37 @@ static bool PreCallValidateBindImageMemory(layer_data *dev_data, VkImage image, skip |= ValidateMemoryTypes(dev_data, mem_info, image_state->requirements.memoryTypeBits, "vkBindImageMemory()", VALIDATION_ERROR_00806); } + + // Validate memory requirements alignment + if (vk_safe_modulo(memoryOffset, image_state->requirements.alignment) != 0) { + skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + image_handle, __LINE__, VALIDATION_ERROR_02178, "DS", + "vkBindImageMemory(): memoryOffset is 0x%" PRIxLEAST64 + " but must be an integer multiple of the " + "VkMemoryRequirements::alignment value 0x%" PRIxLEAST64 + ", returned from a call to vkGetImageMemoryRequirements with image. %s", + memoryOffset, image_state->requirements.alignment, validation_error_map[VALIDATION_ERROR_02178]); + } + + // Validate memory requirements size + if (image_state->requirements.size > mem_info->alloc_info.allocationSize - memoryOffset) { + skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + image_handle, __LINE__, VALIDATION_ERROR_02179, "DS", + "vkBindImageMemory(): memory size minus memoryOffset is 0x%" PRIxLEAST64 + " but must be at least as large as " + "VkMemoryRequirements::size value 0x%" PRIxLEAST64 + ", returned from a call to vkGetImageMemoryRequirements with image. %s", + mem_info->alloc_info.allocationSize - memoryOffset, image_state->requirements.size, + validation_error_map[VALIDATION_ERROR_02179]); + } } return skip; } -static void PostCallRecordBindImageMemory(layer_data *dev_data, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) { - std::unique_lock lock(global_lock); - auto image_state = GetImageState(dev_data, image); +static void PostCallRecordBindImageMemory(layer_data *dev_data, VkImage image, IMAGE_STATE *image_state, VkDeviceMemory mem, + VkDeviceSize memoryOffset) { if (image_state) { + std::unique_lock lock(global_lock); // Track bound memory range information auto mem_info = GetMemObjInfo(dev_data, mem); if (mem_info) { @@ -10122,11 +10156,12 @@ static void PostCallRecordBindImageMemory(layer_data *dev_data, VkImage image, V VKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) { layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; - bool skip = PreCallValidateBindImageMemory(dev_data, image, mem, memoryOffset); + auto image_state = GetImageState(dev_data, image); + bool skip = PreCallValidateBindImageMemory(dev_data, image, image_state, mem, memoryOffset); if (!skip) { result = dev_data->dispatch_table.BindImageMemory(device, image, mem, memoryOffset); if (result == VK_SUCCESS) { - PostCallRecordBindImageMemory(dev_data, image, mem, memoryOffset); + PostCallRecordBindImageMemory(dev_data, image, image_state, mem, memoryOffset); } } return result; diff --git a/layers/vk_validation_error_database.txt b/layers/vk_validation_error_database.txt index ad996dbd..2cb4d76c 100644 --- a/layers/vk_validation_error_database.txt +++ b/layers/vk_validation_error_database.txt @@ -2101,12 +2101,12 @@ VALIDATION_ERROR_02170~^~N~^~Unknown~^~vkCreateImageView~^~For more information VALIDATION_ERROR_02171~^~Y~^~ImageLayerViewTests~^~vkCreateImageView~^~For more information refer to Vulkan Spec Section '11.5. Image Views' which states 'If image was created with the VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT flag, format must be compatible with the format used to create image, as defined in Format Compatibility Classes' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageViewCreateInfo)~^~Multi-purposing this for some format compatibility checks, need unique enums. VALIDATION_ERROR_02172~^~Y~^~ImageLayerViewTests~^~vkCreateImageView~^~For more information refer to Vulkan Spec Section '11.5. Image Views' which states 'If image was not created with the VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT flag, format must be identical to the format used to create image' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageViewCreateInfo)~^~ VALIDATION_ERROR_02173~^~N~^~Unknown~^~vkCreateImageView~^~For more information refer to Vulkan Spec Section '11.5. Image Views' which states 'subResourceRange and viewType must be compatible with the image, as described in the compatibility table' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageViewCreateInfo)~^~ -VALIDATION_ERROR_02174~^~Y~^~Unknown~^~vkBindBufferMemory~^~For more information refer to Vulkan Spec Section '11.6. Resource Memory Association' which states 'memoryOffset must be an integer multiple of the alignment member of the VkMemoryRequirements structure returned from a call to vkGetBufferMemoryRequirements with buffer' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkBindBufferMemory)~^~ -VALIDATION_ERROR_02175~^~N~^~Unknown~^~vkBindBufferMemory~^~For more information refer to Vulkan Spec Section '11.6. Resource Memory Association' which states 'The size member of the VkMemoryRequirements structure returned from a call to vkGetBufferMemoryRequirements with buffer must be less than or equal to the size of memory minus memoryOffset' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkBindBufferMemory)~^~ +VALIDATION_ERROR_02174~^~Y~^~BindInvalidMemory~^~vkBindBufferMemory~^~For more information refer to Vulkan Spec Section '11.6. Resource Memory Association' which states 'memoryOffset must be an integer multiple of the alignment member of the VkMemoryRequirements structure returned from a call to vkGetBufferMemoryRequirements with buffer' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkBindBufferMemory)~^~ +VALIDATION_ERROR_02175~^~Y~^~BindInvalidMemory~^~vkBindBufferMemory~^~For more information refer to Vulkan Spec Section '11.6. Resource Memory Association' which states 'The size member of the VkMemoryRequirements structure returned from a call to vkGetBufferMemoryRequirements with buffer must be less than or equal to the size of memory minus memoryOffset' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkBindBufferMemory)~^~ VALIDATION_ERROR_02176~^~N~^~Unknown~^~vkBindBufferMemory~^~For more information refer to Vulkan Spec Section '11.6. Resource Memory Association' which states 'If buffer was created with VkDedicatedAllocationBufferCreateInfoNV::dedicatedAllocation equal to VK_TRUE, memory must have been created with VkDedicatedAllocationMemoryAllocateInfoNV::buffer equal to buffer and memoryOffset must be zero' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkBindBufferMemory)~^~ VALIDATION_ERROR_02177~^~N~^~Unknown~^~vkBindBufferMemory~^~For more information refer to Vulkan Spec Section '11.6. Resource Memory Association' which states 'If buffer was not created with VkDedicatedAllocationBufferCreateInfoNV::dedicatedAllocation equal to VK_TRUE, memory must not have been allocated dedicated for a specific buffer or image' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkBindBufferMemory)~^~ -VALIDATION_ERROR_02178~^~N~^~Unknown~^~vkBindImageMemory~^~For more information refer to Vulkan Spec Section '11.6. Resource Memory Association' which states 'memoryOffset must be an integer multiple of the alignment member of the VkMemoryRequirements structure returned from a call to vkGetImageMemoryRequirements with image' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkBindImageMemory)~^~ -VALIDATION_ERROR_02179~^~N~^~Unknown~^~vkBindImageMemory~^~For more information refer to Vulkan Spec Section '11.6. Resource Memory Association' which states 'The size member of the VkMemoryRequirements structure returned from a call to vkGetImageMemoryRequirements with image must be less than or equal to the size of memory minus memoryOffset' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkBindImageMemory)~^~ +VALIDATION_ERROR_02178~^~Y~^~BindInvalidMemory~^~vkBindImageMemory~^~For more information refer to Vulkan Spec Section '11.6. Resource Memory Association' which states 'memoryOffset must be an integer multiple of the alignment member of the VkMemoryRequirements structure returned from a call to vkGetImageMemoryRequirements with image' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkBindImageMemory)~^~ +VALIDATION_ERROR_02179~^~Y~^~BindInvalidMemory~^~vkBindImageMemory~^~For more information refer to Vulkan Spec Section '11.6. Resource Memory Association' which states 'The size member of the VkMemoryRequirements structure returned from a call to vkGetImageMemoryRequirements with image must be less than or equal to the size of memory minus memoryOffset' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkBindImageMemory)~^~ VALIDATION_ERROR_02180~^~N~^~Unknown~^~vkBindImageMemory~^~For more information refer to Vulkan Spec Section '11.6. Resource Memory Association' which states 'If image was created with VkDedicatedAllocationImageCreateInfoNV::dedicatedAllocation equal to VK_TRUE, memory must have been created with VkDedicatedAllocationMemoryAllocateInfoNV::image equal to image and memoryOffset must be zero' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkBindImageMemory)~^~ VALIDATION_ERROR_02181~^~N~^~Unknown~^~vkBindImageMemory~^~For more information refer to Vulkan Spec Section '11.6. Resource Memory Association' which states 'If image was not created with VkDedicatedAllocationImageCreateInfoNV::dedicatedAllocation equal to VK_TRUE, memory must not have been allocated dedicated for a specific buffer or image' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkBindImageMemory)~^~ VALIDATION_ERROR_02182~^~Y~^~None~^~vkCmdBlitImage~^~For more information refer to Vulkan Spec Section '18.5. Image Copies with Scaling' which states 'srcImage must have been created with VK_IMAGE_USAGE_TRANSFER_SRC_BIT usage flag' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#vkCmdBlitImage)~^~ -- cgit v1.2.3