From 96c2323011148d843f0935d713ead08be407fb67 Mon Sep 17 00:00:00 2001 From: Mark Lobodzinski Date: Thu, 9 Feb 2017 10:33:46 -0700 Subject: [PATCH] layers: Move CreateBuffer/BufferView routines Moved out of core_validation, refactored for pre/post calls. Moved ValidateImageUsageFlags, ValidateBufferUsageFlags, CreateBuffer, and CreateBufferView, along with a couple of helper routines. Change-Id: I7157369982d93b2327121406c208df36c15bcab4 --- layers/buffer_validation.cpp | 85 +++++++++++++++++++++++++++++++ layers/buffer_validation.h | 14 +++++ layers/core_validation.cpp | 93 +++++++--------------------------- layers/core_validation_types.h | 4 +- 4 files changed, 118 insertions(+), 78 deletions(-) diff --git a/layers/buffer_validation.cpp b/layers/buffer_validation.cpp index e1b2eac2..45e07744 100644 --- a/layers/buffer_validation.cpp +++ b/layers/buffer_validation.cpp @@ -1801,3 +1801,88 @@ bool ValidateMapImageLayouts(core_validation::layer_data *device_data, VkDevice } return skip; } + +// Helper function to validate correct usage bits set for buffers or images. Verify that (actual & desired) flags != 0 or, if strict +// is true, verify that (actual & desired) flags == desired +static bool validate_usage_flags(layer_data *dev_data, VkFlags actual, VkFlags desired, VkBool32 strict, uint64_t obj_handle, + VkDebugReportObjectTypeEXT obj_type, int32_t const msgCode, char const *ty_str, + char const *func_name, char const *usage_str) { + const debug_report_data *report_data = core_validation::GetReportData(dev_data); + + bool correct_usage = false; + bool skip_call = false; + if (strict) { + correct_usage = ((actual & desired) == desired); + } else { + correct_usage = ((actual & desired) != 0); + } + if (!correct_usage) { + if (msgCode == -1) { + // TODO: Fix callers with msgCode == -1 to use correct validation checks. + skip_call = log_msg( + report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj_type, obj_handle, __LINE__, MEMTRACK_INVALID_USAGE_FLAG, "MEM", + "Invalid usage flag for %s 0x%" PRIxLEAST64 " used by %s. In this case, %s should have %s set during creation.", + ty_str, obj_handle, func_name, ty_str, usage_str); + } else { + const char *valid_usage = (msgCode == -1) ? "" : validation_error_map[msgCode]; + skip_call = log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj_type, obj_handle, __LINE__, msgCode, "MEM", + "Invalid usage flag for %s 0x%" PRIxLEAST64 + " used by %s. In this case, %s should have %s set during creation. %s", + ty_str, obj_handle, func_name, ty_str, usage_str, valid_usage); + } + } + return skip_call; +} + +// Helper function to validate usage flags for buffers. For given buffer_state send actual vs. desired usage off to helper above +// where an error will be flagged if usage is not correct +bool ValidateImageUsageFlags(layer_data *dev_data, IMAGE_STATE const *image_state, VkFlags desired, VkBool32 strict, + int32_t const msgCode, char const *func_name, char const *usage_string) { + return validate_usage_flags(dev_data, image_state->createInfo.usage, desired, strict, + reinterpret_cast(image_state->image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + msgCode, "image", func_name, usage_string); +} + +// Helper function to validate usage flags for buffers. For given buffer_state send actual vs. desired usage off to helper above +// where an error will be flagged if usage is not correct +bool ValidateBufferUsageFlags(layer_data *dev_data, BUFFER_STATE const *buffer_state, VkFlags desired, VkBool32 strict, + int32_t const msgCode, char const *func_name, char const *usage_string) { + return validate_usage_flags(dev_data, buffer_state->createInfo.usage, desired, strict, + reinterpret_cast(buffer_state->buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, + msgCode, "buffer", func_name, usage_string); +} + +bool PreCallValidateCreateBuffer(layer_data *dev_data, const VkBufferCreateInfo *pCreateInfo) { + bool skip = false; + // TODO: Add check for VALIDATION_ERROR_00658 + // TODO: Add check for VALIDATION_ERROR_00666 + // TODO: Add check for VALIDATION_ERROR_00667 + // TODO: Add check for VALIDATION_ERROR_00668 + // TODO: Add check for VALIDATION_ERROR_00669 + return skip; +} + +void PostCallRecordCreateBuffer(layer_data *device_data, const VkBufferCreateInfo *pCreateInfo, VkBuffer *pBuffer) { + // TODO : This doesn't create deep copy of pQueueFamilyIndices so need to fix that if/when we want that data to be valid + GetBufferMap(device_data) + ->insert(std::make_pair(*pBuffer, std::unique_ptr(new BUFFER_STATE(*pBuffer, pCreateInfo)))); +} + +bool PreCallValidateCreateBufferView(layer_data *dev_data, const VkBufferViewCreateInfo *pCreateInfo) { + bool skip_call = false; + BUFFER_STATE *buffer_state = GetBufferState(dev_data, pCreateInfo->buffer); + // If this isn't a sparse buffer, it needs to have memory backing it at CreateBufferView time + if (buffer_state) { + skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCreateBufferView()", VALIDATION_ERROR_02522); + // In order to create a valid buffer view, the buffer must have been created with at least one of the following flags: + // UNIFORM_TEXEL_BUFFER_BIT or STORAGE_TEXEL_BUFFER_BIT + skip_call |= ValidateBufferUsageFlags( + dev_data, buffer_state, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, false, + VALIDATION_ERROR_00694, "vkCreateBufferView()", "VK_BUFFER_USAGE_[STORAGE|UNIFORM]_TEXEL_BUFFER_BIT"); + } + return skip_call; +} + +void PostCallRecordCreateBufferView(layer_data *device_data, const VkBufferViewCreateInfo *pCreateInfo, VkBufferView *pView) { + (*GetBufferViewMap(device_data))[*pView] = std::unique_ptr(new BUFFER_VIEW_STATE(*pView, pCreateInfo)); +} diff --git a/layers/buffer_validation.h b/layers/buffer_validation.h index 90fb9067..004cdb73 100644 --- a/layers/buffer_validation.h +++ b/layers/buffer_validation.h @@ -139,4 +139,18 @@ bool ValidateLayouts(core_validation::layer_data *dev_data, VkDevice device, con bool ValidateMapImageLayouts(core_validation::layer_data *dev_data, VkDevice device, DEVICE_MEM_INFO const *mem_info, VkDeviceSize offset, VkDeviceSize end_offset); +bool ValidateImageUsageFlags(layer_data *dev_data, IMAGE_STATE const *image_state, VkFlags desired, VkBool32 strict, + int32_t const msgCode, char const *func_name, char const *usage_string); + +bool ValidateBufferUsageFlags(layer_data *dev_data, BUFFER_STATE const *buffer_state, VkFlags desired, VkBool32 strict, + int32_t const msgCode, char const *func_name, char const *usage_string); + +bool PreCallValidateCreateBuffer(layer_data *dev_data, const VkBufferCreateInfo *pCreateInfo); + +void PostCallRecordCreateBuffer(layer_data *device_data, const VkBufferCreateInfo *pCreateInfo, VkBuffer *pBuffer); + +bool PreCallValidateCreateBufferView(layer_data *dev_data, const VkBufferViewCreateInfo *pCreateInfo); + +void PostCallRecordCreateBufferView(layer_data *device_data, const VkBufferViewCreateInfo *pCreateInfo, VkBufferView *pView); + #endif // CORE_VALIDATION_BUFFER_VALIDATION_H_ diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 7594ca11..0f696585 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -428,58 +428,6 @@ static BINDABLE *GetObjectMemBinding(layer_data *dev_data, uint64_t handle, VkDe // prototype GLOBAL_CB_NODE *GetCBNode(layer_data const *, const VkCommandBuffer); -// Helper function to validate correct usage bits set for buffers or images -// Verify that (actual & desired) flags != 0 or, -// if strict is true, verify that (actual & desired) flags == desired -// In case of error, report it via dbg callbacks -static bool validate_usage_flags(layer_data *dev_data, VkFlags actual, VkFlags desired, VkBool32 strict, uint64_t obj_handle, - VkDebugReportObjectTypeEXT obj_type, int32_t const msgCode, char const *ty_str, - char const *func_name, char const *usage_str) { - bool correct_usage = false; - bool skip_call = false; - if (strict) - correct_usage = ((actual & desired) == desired); - else - correct_usage = ((actual & desired) != 0); - if (!correct_usage) { - if (msgCode == -1) { - // TODO: Fix callers with msgCode == -1 to use correct validation checks. - skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj_type, obj_handle, __LINE__, - MEMTRACK_INVALID_USAGE_FLAG, "MEM", - "Invalid usage flag for %s 0x%" PRIxLEAST64 - " used by %s. In this case, %s should have %s set during creation.", - ty_str, obj_handle, func_name, ty_str, usage_str); - } else { - const char *valid_usage = (msgCode == -1) ? "" : validation_error_map[msgCode]; - skip_call = log_msg( - dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj_type, obj_handle, __LINE__, msgCode, "MEM", - "Invalid usage flag for %s 0x%" PRIxLEAST64 " used by %s. In this case, %s should have %s set during creation. %s", - ty_str, obj_handle, func_name, ty_str, usage_str, valid_usage); - } - } - return skip_call; -} - -// Helper function to validate usage flags for buffers -// For given buffer_state send actual vs. desired usage off to helper above where -// an error will be flagged if usage is not correct -bool ValidateImageUsageFlags(layer_data *dev_data, IMAGE_STATE const *image_state, VkFlags desired, VkBool32 strict, - int32_t const msgCode, char const *func_name, char const *usage_string) { - return validate_usage_flags(dev_data, image_state->createInfo.usage, desired, strict, - reinterpret_cast(image_state->image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, - msgCode, "image", func_name, usage_string); -} - -// Helper function to validate usage flags for buffers -// For given buffer_state send actual vs. desired usage off to helper above where -// an error will be flagged if usage is not correct -static bool ValidateBufferUsageFlags(layer_data *dev_data, BUFFER_STATE const *buffer_state, VkFlags desired, VkBool32 strict, - int32_t const msgCode, char const *func_name, char const *usage_string) { - return validate_usage_flags(dev_data, buffer_state->createInfo.usage, desired, strict, - reinterpret_cast(buffer_state->buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, - msgCode, "buffer", func_name, usage_string); -} - // Return ptr to info in map container containing mem, or NULL if not found // Calls to this function should be wrapped in mutex DEVICE_MEM_INFO *GetMemObjInfo(const layer_data *dev_data, const VkDeviceMemory mem) { @@ -6030,36 +5978,21 @@ VKAPI_ATTR void VKAPI_CALL DestroyRenderPass(VkDevice device, VkRenderPass rende VKAPI_ATTR VkResult VKAPI_CALL CreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) { layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); - // TODO: Add check for VALIDATION_ERROR_00658 - // TODO: Add check for VALIDATION_ERROR_00666 - // TODO: Add check for VALIDATION_ERROR_00667 - // TODO: Add check for VALIDATION_ERROR_00668 - // TODO: Add check for VALIDATION_ERROR_00669 + std::unique_lock lock(global_lock); + bool skip = PreCallValidateCreateBuffer(dev_data, pCreateInfo); + lock.unlock(); + + if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; VkResult result = dev_data->dispatch_table.CreateBuffer(device, pCreateInfo, pAllocator, pBuffer); if (VK_SUCCESS == result) { - std::lock_guard lock(global_lock); - // TODO : This doesn't create deep copy of pQueueFamilyIndices so need to fix that if/when we want that data to be valid - dev_data->bufferMap.insert(std::make_pair(*pBuffer, unique_ptr(new BUFFER_STATE(*pBuffer, pCreateInfo)))); + lock.lock(); + PostCallRecordCreateBuffer(dev_data, pCreateInfo, pBuffer); + lock.unlock(); } return result; } -static bool PreCallValidateCreateBufferView(layer_data *dev_data, const VkBufferViewCreateInfo *pCreateInfo) { - bool skip_call = false; - BUFFER_STATE *buffer_state = GetBufferState(dev_data, pCreateInfo->buffer); - // If this isn't a sparse buffer, it needs to have memory backing it at CreateBufferView time - if (buffer_state) { - skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCreateBufferView()", VALIDATION_ERROR_02522); - // In order to create a valid buffer view, the buffer must have been created with at least one of the - // following flags: UNIFORM_TEXEL_BUFFER_BIT or STORAGE_TEXEL_BUFFER_BIT - skip_call |= ValidateBufferUsageFlags( - dev_data, buffer_state, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, false, - VALIDATION_ERROR_00694, "vkCreateBufferView()", "VK_BUFFER_USAGE_[STORAGE|UNIFORM]_TEXEL_BUFFER_BIT"); - } - return skip_call; -} - VKAPI_ATTR VkResult VKAPI_CALL CreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkBufferView *pView) { layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); @@ -6070,7 +6003,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateBufferView(VkDevice device, const VkBufferV VkResult result = dev_data->dispatch_table.CreateBufferView(device, pCreateInfo, pAllocator, pView); if (VK_SUCCESS == result) { lock.lock(); - dev_data->bufferViewMap[*pView] = unique_ptr(new BUFFER_VIEW_STATE(*pView, pCreateInfo)); + PostCallRecordCreateBufferView(dev_data, pCreateInfo, pView); lock.unlock(); } return result; @@ -6107,6 +6040,14 @@ std::unordered_map *GetImageLayoutMap(l return &device_data->imageLayoutMap; } +std::unordered_map> *GetBufferMap(layer_data *device_data) { + return &device_data->bufferMap; +} + +std::unordered_map> *GetBufferViewMap(layer_data *device_data) { + return &device_data->bufferViewMap; +} + VKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkImage *pImage) { VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index e08a7890..28757be1 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -766,8 +766,6 @@ VkPhysicalDeviceLimits GetPhysicalDeviceLimits(layer_data const *); bool ValidateImageMemoryIsValid(layer_data *dev_data, IMAGE_STATE *image_state, const char *functionName); bool ValidateImageSampleCount(layer_data *dev_data, IMAGE_STATE *image_state, VkSampleCountFlagBits sample_count, const char *location, UNIQUE_VALIDATION_ERROR_CODE msgCode); -bool ValidateImageUsageFlags(layer_data *dev_data, IMAGE_STATE const *image_state, VkFlags desired, VkBool32 strict, - int32_t const msgCode, char const *func_name, char const *usage_string); bool ValidateImageSubrangeLevelLayerCounts(layer_data *dev_data, const VkImageSubresourceRange &subresourceRange, const char *func_name, UNIQUE_VALIDATION_ERROR_CODE layer_msg_code, UNIQUE_VALIDATION_ERROR_CODE level_msg_code); @@ -783,6 +781,8 @@ const CHECK_DISABLED *GetDisables(layer_data *); std::unordered_map> *GetImageMap(core_validation::layer_data *); std::unordered_map> *GetImageSubresourceMap(layer_data *); std::unordered_map *GetImageLayoutMap(layer_data *); +std::unordered_map> *GetBufferMap(layer_data *device_data); +std::unordered_map> *GetBufferViewMap(layer_data *device_data); } #endif // CORE_VALIDATION_TYPES_H_ -- 2.34.1