layers: Move image validation support to buffer_val
Moved the new CmdClear[Color/DepthStencil]Image support routines
to the buffer_validation module, along with some related helper
functions.
Change-Id: I76a4b545e696bbc770ef0c672d14c92e4a941e49
diff --git a/layers/buffer_validation.cpp b/layers/buffer_validation.cpp
index 2dfbf40..e50d643 100644
--- a/layers/buffer_validation.cpp
+++ b/layers/buffer_validation.cpp
@@ -263,3 +263,172 @@
}
return skip;
}
+
+void ResolveRemainingLevelsLayers(core_validation::layer_data *dev_data, VkImageSubresourceRange *range, VkImage image) {
+ // Expects global_lock to be held by caller
+
+ auto image_state = getImageState(dev_data, image);
+ if (image_state) {
+ // If the caller used the special values VK_REMAINING_MIP_LEVELS and VK_REMAINING_ARRAY_LAYERS, resolve them now in our
+ // internal state to the actual values.
+ if (range->levelCount == VK_REMAINING_MIP_LEVELS) {
+ range->levelCount = image_state->createInfo.mipLevels - range->baseMipLevel;
+ }
+
+ if (range->layerCount == VK_REMAINING_ARRAY_LAYERS) {
+ range->layerCount = image_state->createInfo.arrayLayers - range->baseArrayLayer;
+ }
+ }
+}
+
+// Return the correct layer/level counts if the caller used the special values VK_REMAINING_MIP_LEVELS or VK_REMAINING_ARRAY_LAYERS.
+void ResolveRemainingLevelsLayers(core_validation::layer_data *dev_data, uint32_t *levels, uint32_t *layers,
+ VkImageSubresourceRange range, VkImage image) {
+ // Expects global_lock to be held by caller
+
+ *levels = range.levelCount;
+ *layers = range.layerCount;
+ auto image_state = getImageState(dev_data, image);
+ if (image_state) {
+ if (range.levelCount == VK_REMAINING_MIP_LEVELS) {
+ *levels = image_state->createInfo.mipLevels - range.baseMipLevel;
+ }
+ if (range.layerCount == VK_REMAINING_ARRAY_LAYERS) {
+ *layers = image_state->createInfo.arrayLayers - range.baseArrayLayer;
+ }
+ }
+}
+
+bool VerifyClearImageLayout(core_validation::layer_data *device_data, GLOBAL_CB_NODE *cb_node, VkImage image,
+ VkImageSubresourceRange range, VkImageLayout dest_image_layout, const char *func_name) {
+ bool skip = false;
+ const debug_report_data *report_data = core_validation::GetReportData(device_data);
+
+ VkImageSubresourceRange resolved_range = range;
+ ResolveRemainingLevelsLayers(device_data, &resolved_range, image);
+
+ if (dest_image_layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
+ if (dest_image_layout == VK_IMAGE_LAYOUT_GENERAL) {
+ auto image_state = getImageState(device_data, image);
+ if (image_state->createInfo.tiling != VK_IMAGE_TILING_LINEAR) {
+ // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning.
+ skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
+ __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
+ "%s: Layout for cleared image should be TRANSFER_DST_OPTIMAL instead of GENERAL.", func_name);
+ }
+ } else {
+ UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_01086;
+ if (strcmp(func_name, "vkCmdClearDepthStencilImage()") == 0) {
+ error_code = VALIDATION_ERROR_01101;
+ } else {
+ assert(strcmp(func_name, "vkCmdClearColorImage()") == 0);
+ }
+ skip |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, error_code, "DS",
+ "%s: Layout for cleared image is %s but can only be "
+ "TRANSFER_DST_OPTIMAL or GENERAL. %s",
+ func_name, string_VkImageLayout(dest_image_layout), validation_error_map[error_code]);
+ }
+ }
+
+ for (uint32_t level_index = 0; level_index < resolved_range.levelCount; ++level_index) {
+ uint32_t level = level_index + resolved_range.baseMipLevel;
+ for (uint32_t layer_index = 0; layer_index < resolved_range.layerCount; ++layer_index) {
+ uint32_t layer = layer_index + resolved_range.baseArrayLayer;
+ VkImageSubresource sub = {resolved_range.aspectMask, level, layer};
+ IMAGE_CMD_BUF_LAYOUT_NODE node;
+ if (core_validation::FindLayout(cb_node, image, sub, node)) {
+ if (node.layout != dest_image_layout) {
+ UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_01085;
+ if (strcmp(func_name, "vkCmdClearDepthStencilImage()") == 0) {
+ error_code = VALIDATION_ERROR_01100;
+ } else {
+ assert(strcmp(func_name, "vkCmdClearColorImage()") == 0);
+ }
+ skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
+ __LINE__, error_code, "DS",
+ "%s: Cannot clear an image whose layout is %s and "
+ "doesn't match the current layout %s. %s",
+ func_name, string_VkImageLayout(dest_image_layout), string_VkImageLayout(node.layout),
+ validation_error_map[error_code]);
+ }
+ }
+ }
+ }
+
+ return skip;
+}
+
+void RecordClearImageLayout(core_validation::layer_data *dev_data, GLOBAL_CB_NODE *cb_node, VkImage image,
+ VkImageSubresourceRange range, VkImageLayout dest_image_layout) {
+ VkImageSubresourceRange resolved_range = range;
+ ResolveRemainingLevelsLayers(dev_data, &resolved_range, image);
+
+ for (uint32_t level_index = 0; level_index < resolved_range.levelCount; ++level_index) {
+ uint32_t level = level_index + resolved_range.baseMipLevel;
+ for (uint32_t layer_index = 0; layer_index < resolved_range.layerCount; ++layer_index) {
+ uint32_t layer = layer_index + resolved_range.baseArrayLayer;
+ VkImageSubresource sub = {resolved_range.aspectMask, level, layer};
+ IMAGE_CMD_BUF_LAYOUT_NODE node;
+ if (!core_validation::FindLayout(cb_node, image, sub, node)) {
+ SetLayout(cb_node, image, sub, IMAGE_CMD_BUF_LAYOUT_NODE(dest_image_layout, dest_image_layout));
+ }
+ }
+ }
+}
+
+bool PreCallValidateCmdClearColorImage(core_validation::layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image,
+ VkImageLayout imageLayout, uint32_t rangeCount, const VkImageSubresourceRange *pRanges) {
+ bool skip = false;
+ // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state
+ auto cb_node = core_validation::getCBNode(dev_data, commandBuffer);
+ auto image_state = getImageState(dev_data, image);
+ if (cb_node && image_state) {
+ skip |= ValidateMemoryIsBoundToImage(dev_data, image_state, "vkCmdClearColorImage()", VALIDATION_ERROR_02527);
+ skip |= ValidateCmd(dev_data, cb_node, CMD_CLEARCOLORIMAGE, "vkCmdClearColorImage()");
+ skip |= insideRenderPass(dev_data, cb_node, "vkCmdClearColorImage()", VALIDATION_ERROR_01096);
+ for (uint32_t i = 0; i < rangeCount; ++i) {
+ skip |= ValidateImageAttributes(dev_data, image_state, pRanges[i]);
+ skip |= VerifyClearImageLayout(dev_data, cb_node, image, pRanges[i], imageLayout, "vkCmdClearColorImage()");
+ }
+ }
+ return skip;
+}
+
+// This state recording routine is shared between ClearColorImage and ClearDepthStencilImage
+void PreCallRecordCmdClearImage(core_validation::layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image,
+ VkImageLayout imageLayout, uint32_t rangeCount, const VkImageSubresourceRange *pRanges,
+ CMD_TYPE cmd_type) {
+ auto cb_node = getCBNode(dev_data, commandBuffer);
+ auto image_state = getImageState(dev_data, image);
+ if (cb_node && image_state) {
+ AddCommandBufferBindingImage(dev_data, cb_node, image_state);
+ std::function<bool()> function = [=]() {
+ SetImageMemoryValid(dev_data, image_state, true);
+ return false;
+ };
+ cb_node->validate_functions.push_back(function);
+ UpdateCmdBufferLastCmd(dev_data, cb_node, cmd_type);
+ for (uint32_t i = 0; i < rangeCount; ++i) {
+ RecordClearImageLayout(dev_data, cb_node, image, pRanges[i], imageLayout);
+ }
+ }
+}
+
+bool PreCallValidateCmdClearDepthStencilImage(core_validation::layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image,
+ VkImageLayout imageLayout, uint32_t rangeCount,
+ const VkImageSubresourceRange *pRanges) {
+ bool skip = false;
+ // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state
+ auto cb_node = getCBNode(dev_data, commandBuffer);
+ auto image_state = getImageState(dev_data, image);
+ if (cb_node && image_state) {
+ skip |= ValidateMemoryIsBoundToImage(dev_data, image_state, "vkCmdClearDepthStencilImage()", VALIDATION_ERROR_02528);
+ skip |= ValidateCmd(dev_data, cb_node, CMD_CLEARDEPTHSTENCILIMAGE, "vkCmdClearDepthStencilImage()");
+ skip |= insideRenderPass(dev_data, cb_node, "vkCmdClearDepthStencilImage()", VALIDATION_ERROR_01111);
+ for (uint32_t i = 0; i < rangeCount; ++i) {
+ skip |= VerifyClearImageLayout(dev_data, cb_node, image, pRanges[i], imageLayout, "vkCmdClearDepthStencilImage()");
+ }
+ }
+ return skip;
+}
diff --git a/layers/buffer_validation.h b/layers/buffer_validation.h
index 653057a..acdc8f1 100644
--- a/layers/buffer_validation.h
+++ b/layers/buffer_validation.h
@@ -42,4 +42,26 @@
bool ValidateImageAttributes(core_validation::layer_data *device_data, IMAGE_STATE *image_state, VkImageSubresourceRange range);
+void ResolveRemainingLevelsLayers(core_validation::layer_data *dev_data, VkImageSubresourceRange *range, VkImage image);
+
+void ResolveRemainingLevelsLayers(core_validation::layer_data *dev_data, uint32_t *levels, uint32_t *layers,
+ VkImageSubresourceRange range, VkImage image);
+
+bool VerifyClearImageLayout(core_validation::layer_data *device_data, GLOBAL_CB_NODE *cb_node, VkImage image,
+ VkImageSubresourceRange range, VkImageLayout dest_image_layout, const char *func_name);
+
+void RecordClearImageLayout(core_validation::layer_data *dev_data, GLOBAL_CB_NODE *cb_node, VkImage image,
+ VkImageSubresourceRange range, VkImageLayout dest_image_layout);
+
+bool PreCallValidateCmdClearColorImage(core_validation::layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image,
+ VkImageLayout imageLayout, uint32_t rangeCount, const VkImageSubresourceRange *pRanges);
+
+void PreCallRecordCmdClearImage(core_validation::layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image,
+ VkImageLayout imageLayout, uint32_t rangeCount, const VkImageSubresourceRange *pRanges,
+ CMD_TYPE cmd_type);
+
+bool PreCallValidateCmdClearDepthStencilImage(core_validation::layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image,
+ VkImageLayout imageLayout, uint32_t rangeCount,
+ const VkImageSubresourceRange *pRanges);
+
#endif // CORE_VALIDATION_BUFFER_VALIDATION_H_
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index a4cde25..4ab0038 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -418,7 +418,7 @@
return nullptr;
}
// prototype
-static GLOBAL_CB_NODE *getCBNode(layer_data const *, const VkCommandBuffer);
+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,
@@ -577,7 +577,7 @@
// For given image node
// If mem is special swapchain key, then set entire image_state to valid param value
// Else set the image's bound memory range to valid param value
-static void SetImageMemoryValid(layer_data *dev_data, IMAGE_STATE *image_state, bool valid) {
+void SetImageMemoryValid(layer_data *dev_data, IMAGE_STATE *image_state, bool valid) {
if (image_state->binding.mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) {
image_state->valid = valid;
} else {
@@ -3523,29 +3523,6 @@
}
}
-template <class OBJECT, class LAYOUT>
-void SetLayout(OBJECT *pObject, ImageSubresourcePair imgpair, const LAYOUT &layout, VkImageAspectFlags aspectMask) {
- if (imgpair.subresource.aspectMask & aspectMask) {
- imgpair.subresource.aspectMask = aspectMask;
- SetLayout(pObject, imgpair, layout);
- }
-}
-
-template <class OBJECT, class LAYOUT>
-void SetLayout(OBJECT *pObject, VkImage image, VkImageSubresource range, const LAYOUT &layout) {
- ImageSubresourcePair imgpair = {image, true, range};
- SetLayout(pObject, imgpair, layout, VK_IMAGE_ASPECT_COLOR_BIT);
- SetLayout(pObject, imgpair, layout, VK_IMAGE_ASPECT_DEPTH_BIT);
- SetLayout(pObject, imgpair, layout, VK_IMAGE_ASPECT_STENCIL_BIT);
- SetLayout(pObject, imgpair, layout, VK_IMAGE_ASPECT_METADATA_BIT);
-}
-
-template <class OBJECT, class LAYOUT>
-void SetLayout(OBJECT *pObject, VkImage image, const LAYOUT &layout) {
- ImageSubresourcePair imgpair = {image, false, VkImageSubresource()};
- SetLayout(pObject, image, imgpair, layout);
-}
-
void SetLayout(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, VkImageView imageView, const VkImageLayout &layout) {
auto view_state = getImageViewState(dev_data, imageView);
assert(view_state);
@@ -3632,7 +3609,7 @@
}
// For given CB object, fetch associated CB Node from map
-static GLOBAL_CB_NODE *getCBNode(layer_data const *my_data, const VkCommandBuffer cb) {
+GLOBAL_CB_NODE *getCBNode(layer_data const *my_data, const VkCommandBuffer cb) {
auto it = my_data->commandBufferMap.find(cb);
if (it == my_data->commandBufferMap.end()) {
log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
@@ -3701,9 +3678,9 @@
return false;
}
-// Validate the given command being added to the specified cmd buffer, flagging errors if CB is not
-// in the recording state or if there's an issue with the Cmd ordering
-static bool ValidateCmd(layer_data *my_data, GLOBAL_CB_NODE *pCB, const CMD_TYPE cmd, const char *caller_name) {
+// Validate the given command being added to the specified cmd buffer, flagging errors if CB is not in the recording state or if
+// there's an issue with the Cmd ordering
+bool ValidateCmd(layer_data *my_data, GLOBAL_CB_NODE *pCB, const CMD_TYPE cmd, const char *caller_name) {
bool skip_call = false;
auto pPool = getCommandPoolNode(my_data, pCB->createInfo.commandPool);
if (pPool) {
@@ -3774,7 +3751,7 @@
return skip_call;
}
-static void UpdateCmdBufferLastCmd(layer_data *my_data, GLOBAL_CB_NODE *cb_state, const CMD_TYPE cmd) {
+void UpdateCmdBufferLastCmd(layer_data *my_data, GLOBAL_CB_NODE *cb_state, const CMD_TYPE cmd) {
if (cb_state->state == CB_RECORDING) {
cb_state->last_cmd = cmd;
}
@@ -3970,10 +3947,9 @@
}
}
-// Flags validation error if the associated call is made inside a render pass. The apiName
-// routine should ONLY be called outside a render pass.
-static bool insideRenderPass(const layer_data *my_data, GLOBAL_CB_NODE *pCB, const char *apiName,
- UNIQUE_VALIDATION_ERROR_CODE msgCode) {
+// Flags validation error if the associated call is made inside a render pass. The apiName routine should ONLY be called outside a
+// render pass.
+bool insideRenderPass(const layer_data *my_data, GLOBAL_CB_NODE *pCB, const char *apiName, UNIQUE_VALIDATION_ERROR_CODE msgCode) {
bool inside = false;
if (pCB->activeRenderPass) {
inside = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
@@ -6405,42 +6381,6 @@
return result;
}
-static void ResolveRemainingLevelsLayers(layer_data *dev_data, VkImageSubresourceRange *range, VkImage image) {
- // Expects global_lock to be held by caller
-
- auto image_state = getImageState(dev_data, image);
- if (image_state) {
- // If the caller used the special values VK_REMAINING_MIP_LEVELS and VK_REMAINING_ARRAY_LAYERS, resolve them now in our
- // internal state to the actual values.
- if (range->levelCount == VK_REMAINING_MIP_LEVELS) {
- range->levelCount = image_state->createInfo.mipLevels - range->baseMipLevel;
- }
-
- if (range->layerCount == VK_REMAINING_ARRAY_LAYERS) {
- range->layerCount = image_state->createInfo.arrayLayers - range->baseArrayLayer;
- }
- }
-}
-
-// Return the correct layer/level counts if the caller used the special
-// values VK_REMAINING_MIP_LEVELS or VK_REMAINING_ARRAY_LAYERS.
-static void ResolveRemainingLevelsLayers(layer_data *dev_data, uint32_t *levels, uint32_t *layers, VkImageSubresourceRange range,
- VkImage image) {
- // Expects global_lock to be held by caller
-
- *levels = range.levelCount;
- *layers = range.layerCount;
- auto image_state = getImageState(dev_data, image);
- if (image_state) {
- if (range.levelCount == VK_REMAINING_MIP_LEVELS) {
- *levels = image_state->createInfo.mipLevels - range.baseMipLevel;
- }
- if (range.layerCount == VK_REMAINING_ARRAY_LAYERS) {
- *layers = image_state->createInfo.arrayLayers - range.baseArrayLayer;
- }
- }
-}
-
// For the given format verify that the aspect masks make sense
static bool ValidateImageAspectMask(layer_data *dev_data, VkImage image, VkFormat format, VkImageAspectFlags aspect_mask,
const char *func_name) {
@@ -8206,83 +8146,6 @@
return skip_call;
}
-static bool VerifyClearImageLayout(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, VkImage image, VkImageSubresourceRange range,
- VkImageLayout dest_image_layout, const char *func_name) {
- bool skip = false;
-
- VkImageSubresourceRange resolved_range = range;
- ResolveRemainingLevelsLayers(dev_data, &resolved_range, image);
-
- if (dest_image_layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
- if (dest_image_layout == VK_IMAGE_LAYOUT_GENERAL) {
- auto image_state = getImageState(dev_data, image);
- if (image_state->createInfo.tiling != VK_IMAGE_TILING_LINEAR) {
- // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning.
- skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0,
- 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
- "%s: Layout for cleared image should be TRANSFER_DST_OPTIMAL instead of GENERAL.", func_name);
- }
- } else {
- UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_01086;
- if (strcmp(func_name, "vkCmdClearDepthStencilImage()") == 0) {
- error_code = VALIDATION_ERROR_01101;
- } else {
- assert(strcmp(func_name, "vkCmdClearColorImage()") == 0);
- }
- skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
- error_code, "DS",
- "%s: Layout for cleared image is %s but can only be "
- "TRANSFER_DST_OPTIMAL or GENERAL. %s",
- func_name, string_VkImageLayout(dest_image_layout), validation_error_map[error_code]);
- }
- }
-
- for (uint32_t level_index = 0; level_index < resolved_range.levelCount; ++level_index) {
- uint32_t level = level_index + resolved_range.baseMipLevel;
- for (uint32_t layer_index = 0; layer_index < resolved_range.layerCount; ++layer_index) {
- uint32_t layer = layer_index + resolved_range.baseArrayLayer;
- VkImageSubresource sub = {resolved_range.aspectMask, level, layer};
- IMAGE_CMD_BUF_LAYOUT_NODE node;
- if (FindLayout(cb_node, image, sub, node)) {
- if (node.layout != dest_image_layout) {
- UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_01085;
- if (strcmp(func_name, "vkCmdClearDepthStencilImage()") == 0) {
- error_code = VALIDATION_ERROR_01100;
- } else {
- assert(strcmp(func_name, "vkCmdClearColorImage()") == 0);
- }
- skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
- VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, error_code, "DS",
- "%s: Cannot clear an image whose layout is %s and "
- "doesn't match the current layout %s. %s",
- func_name, string_VkImageLayout(dest_image_layout), string_VkImageLayout(node.layout),
- validation_error_map[error_code]);
- }
- }
- }
- }
-
- return skip;
-}
-
-static void RecordClearImageLayout(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, VkImage image, VkImageSubresourceRange range,
- VkImageLayout dest_image_layout) {
- VkImageSubresourceRange resolved_range = range;
- ResolveRemainingLevelsLayers(dev_data, &resolved_range, image);
-
- for (uint32_t level_index = 0; level_index < resolved_range.levelCount; ++level_index) {
- uint32_t level = level_index + resolved_range.baseMipLevel;
- for (uint32_t layer_index = 0; layer_index < resolved_range.layerCount; ++layer_index) {
- uint32_t layer = layer_index + resolved_range.baseArrayLayer;
- VkImageSubresource sub = {resolved_range.aspectMask, level, layer};
- IMAGE_CMD_BUF_LAYOUT_NODE node;
- if (!FindLayout(cb_node, image, sub, node)) {
- SetLayout(cb_node, image, sub, IMAGE_CMD_BUF_LAYOUT_NODE(dest_image_layout, dest_image_layout));
- }
- }
- }
-}
-
// Test if two VkExtent3D structs are equivalent
static inline bool IsExtentEqual(const VkExtent3D *extent, const VkExtent3D *other_extent) {
bool result = true;
@@ -8867,45 +8730,6 @@
if (!skip) dev_data->dispatch_table.CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
}
-static bool PreCallValidateCmdClearColorImage(layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image,
- VkImageLayout imageLayout, uint32_t rangeCount,
- const VkImageSubresourceRange *pRanges) {
- bool skip = false;
- // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state
- auto cb_node = getCBNode(dev_data, commandBuffer);
- auto image_state = getImageState(dev_data, image);
- if (cb_node && image_state) {
- skip |= ValidateMemoryIsBoundToImage(dev_data, image_state, "vkCmdClearColorImage()", VALIDATION_ERROR_02527);
- skip |= ValidateCmd(dev_data, cb_node, CMD_CLEARCOLORIMAGE, "vkCmdClearColorImage()");
- skip |= insideRenderPass(dev_data, cb_node, "vkCmdClearColorImage()", VALIDATION_ERROR_01096);
- for (uint32_t i = 0; i < rangeCount; ++i) {
- skip |= ValidateImageAttributes(dev_data, image_state, pRanges[i]);
- skip |= VerifyClearImageLayout(dev_data, cb_node, image, pRanges[i], imageLayout, "vkCmdClearColorImage()");
- }
- }
- return skip;
-}
-
-// This state recording routine is shared between ClearColorImage and ClearDepthStencilImage
-static void PreCallRecordCmdClearImage(layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image,
- VkImageLayout imageLayout, uint32_t rangeCount, const VkImageSubresourceRange *pRanges,
- CMD_TYPE cmd_type) {
- auto cb_node = getCBNode(dev_data, commandBuffer);
- auto image_state = getImageState(dev_data, image);
- if (cb_node && image_state) {
- AddCommandBufferBindingImage(dev_data, cb_node, image_state);
- std::function<bool()> function = [=]() {
- SetImageMemoryValid(dev_data, image_state, true);
- return false;
- };
- cb_node->validate_functions.push_back(function);
- UpdateCmdBufferLastCmd(dev_data, cb_node, cmd_type);
- for (uint32_t i = 0; i < rangeCount; ++i) {
- RecordClearImageLayout(dev_data, cb_node, image, pRanges[i], imageLayout);
- }
- }
-}
-
VKAPI_ATTR void VKAPI_CALL CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
const VkClearColorValue *pColor, uint32_t rangeCount,
const VkImageSubresourceRange *pRanges) {
@@ -8920,24 +8744,6 @@
}
}
-static bool PreCallValidateCmdClearDepthStencilImage(layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image,
- VkImageLayout imageLayout, uint32_t rangeCount,
- const VkImageSubresourceRange *pRanges) {
- bool skip = false;
- // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state
- auto cb_node = getCBNode(dev_data, commandBuffer);
- auto image_state = getImageState(dev_data, image);
- if (cb_node && image_state) {
- skip |= ValidateMemoryIsBoundToImage(dev_data, image_state, "vkCmdClearDepthStencilImage()", VALIDATION_ERROR_02528);
- skip |= ValidateCmd(dev_data, cb_node, CMD_CLEARDEPTHSTENCILIMAGE, "vkCmdClearDepthStencilImage()");
- skip |= insideRenderPass(dev_data, cb_node, "vkCmdClearDepthStencilImage()", VALIDATION_ERROR_01111);
- for (uint32_t i = 0; i < rangeCount; ++i) {
- skip |= VerifyClearImageLayout(dev_data, cb_node, image, pRanges[i], imageLayout, "vkCmdClearDepthStencilImage()");
- }
- }
- return skip;
-}
-
VKAPI_ATTR void VKAPI_CALL CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount,
const VkImageSubresourceRange *pRanges) {
diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h
index b93ad66..e592485 100644
--- a/layers/core_validation_types.h
+++ b/layers/core_validation_types.h
@@ -721,6 +721,7 @@
IMAGE_VIEW_STATE *getImageViewState(const layer_data *, VkImageView);
VkSwapchainKHR getSwapchainFromImage(const layer_data *, VkImage);
SWAPCHAIN_NODE *getSwapchainNode(const layer_data *, VkSwapchainKHR);
+GLOBAL_CB_NODE *getCBNode(layer_data const *my_data, const VkCommandBuffer cb);
void invalidateCommandBuffers(const layer_data *, std::unordered_set<GLOBAL_CB_NODE *> const &, VK_OBJECT);
bool ValidateMemoryIsBoundToBuffer(const layer_data *, const BUFFER_STATE *, const char *, UNIQUE_VALIDATION_ERROR_CODE);
bool ValidateMemoryIsBoundToImage(const layer_data *, const IMAGE_STATE *, const char *, UNIQUE_VALIDATION_ERROR_CODE);
@@ -733,6 +734,14 @@
void invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> const &cb_nodes, VK_OBJECT obj);
void RemoveImageMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info);
bool ClearMemoryObjectBindings(layer_data *dev_data, uint64_t handle, VkDebugReportObjectTypeEXT type);
+bool ValidateCmd(layer_data *my_data, GLOBAL_CB_NODE *pCB, const CMD_TYPE cmd, const char *caller_name);
+bool insideRenderPass(const layer_data *my_data, GLOBAL_CB_NODE *pCB, const char *apiName, UNIQUE_VALIDATION_ERROR_CODE msgCode);
+bool FindLayout(const GLOBAL_CB_NODE *pCB, VkImage image, VkImageSubresource range, IMAGE_CMD_BUF_LAYOUT_NODE &node);
+void SetImageMemoryValid(layer_data *dev_data, IMAGE_STATE *image_state, bool valid);
+void UpdateCmdBufferLastCmd(layer_data *my_data, GLOBAL_CB_NODE *cb_state, const CMD_TYPE cmd);
+void SetLayout(GLOBAL_CB_NODE *pCB, ImageSubresourcePair imgpair, const IMAGE_CMD_BUF_LAYOUT_NODE &node);
+void SetLayout(GLOBAL_CB_NODE *pCB, ImageSubresourcePair imgpair, const VkImageLayout &layout);
+
// Prototypes for layer_data accessor functions. These should be in their own header file at some point
PFN_vkGetPhysicalDeviceFormatProperties GetFormatPropertiesPointer(layer_data *);
@@ -746,4 +755,29 @@
std::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> *GetImageLayoutMap(layer_data *);
}
+
+
+template <class OBJECT, class LAYOUT>
+void SetLayout(OBJECT *pObject, VkImage image, VkImageSubresource range, const LAYOUT &layout) {
+ ImageSubresourcePair imgpair = { image, true, range };
+ SetLayout(pObject, imgpair, layout, VK_IMAGE_ASPECT_COLOR_BIT);
+ SetLayout(pObject, imgpair, layout, VK_IMAGE_ASPECT_DEPTH_BIT);
+ SetLayout(pObject, imgpair, layout, VK_IMAGE_ASPECT_STENCIL_BIT);
+ SetLayout(pObject, imgpair, layout, VK_IMAGE_ASPECT_METADATA_BIT);
+}
+
+template <class OBJECT, class LAYOUT>
+void SetLayout(OBJECT *pObject, ImageSubresourcePair imgpair, const LAYOUT &layout, VkImageAspectFlags aspectMask) {
+ if (imgpair.subresource.aspectMask & aspectMask) {
+ imgpair.subresource.aspectMask = aspectMask;
+ core_validation::SetLayout(pObject, imgpair, layout);
+ }
+}
+
+template <class OBJECT, class LAYOUT>
+void SetLayout(OBJECT *pObject, VkImage image, const LAYOUT &layout) {
+ ImageSubresourcePair imgpair = { image, false, VkImageSubresource() };
+ SetLayout(pObject, image, imgpair, layout);
+}
+
#endif // CORE_VALIDATION_TYPES_H_