blob: a6d62e5ef73b01d442b8b28524d55b2a5163e233 [file] [log] [blame]
Mark Lobodzinskid42e4d22017-01-17 14:14:22 -07001/* Copyright (c) 2015-2017 The Khronos Group Inc.
2 * Copyright (c) 2015-2017 Valve Corporation
3 * Copyright (c) 2015-2017 LunarG, Inc.
4 * Copyright (C) 2015-2017 Google Inc.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: Mark Lobodzinski <mark@lunarg.com>
19 */
20
21// Allow use of STL min and max functions in Windows
22#define NOMINMAX
23
Mark Lobodzinski90224de2017-01-26 15:23:11 -070024#include <sstream>
25
26#include "vk_enum_string_helper.h"
27#include "vk_layer_data.h"
28#include "vk_layer_utils.h"
29#include "vk_layer_logging.h"
30
31
Mark Lobodzinskid42e4d22017-01-17 14:14:22 -070032#include "buffer_validation.h"
Mark Lobodzinski42fe5f72017-01-11 11:36:16 -070033
Mark Lobodzinski90224de2017-01-26 15:23:11 -070034bool PreCallValidateCreateImage(core_validation::layer_data *device_data, const VkImageCreateInfo *pCreateInfo,
35 const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
36 bool skip_call = false;
37 VkImageFormatProperties ImageFormatProperties;
38 const VkPhysicalDevice physical_device = core_validation::GetPhysicalDevice(device_data);
39 const debug_report_data *report_data = core_validation::GetReportData(device_data);
40
41 if (pCreateInfo->format != VK_FORMAT_UNDEFINED) {
42 VkFormatProperties properties;
43 core_validation::GetFormatPropertiesPointer(device_data)(physical_device, pCreateInfo->format, &properties);
44
45 if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) && (properties.linearTilingFeatures == 0)) {
46 std::stringstream ss;
47 ss << "vkCreateImage format parameter (" << string_VkFormat(pCreateInfo->format) << ") is an unsupported format";
48 skip_call |=
49 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
50 VALIDATION_ERROR_02150, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02150]);
51 }
52
53 if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) && (properties.optimalTilingFeatures == 0)) {
54 std::stringstream ss;
55 ss << "vkCreateImage format parameter (" << string_VkFormat(pCreateInfo->format) << ") is an unsupported format";
56 skip_call |=
57 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
58 VALIDATION_ERROR_02155, "IMAGE", "%s. %s", ss.str().c_str(), validation_error_map[VALIDATION_ERROR_02155]);
59 }
60
61 // Validate that format supports usage as color attachment
62 if (pCreateInfo->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
63 if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) &&
64 ((properties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)) {
65 std::stringstream ss;
66 ss << "vkCreateImage: VkFormat for TILING_OPTIMAL image (" << string_VkFormat(pCreateInfo->format)
67 << ") does not support requested Image usage type VK_IMAGE_USAGE_COLOR_ATTACHMENT";
68 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
69 __LINE__, VALIDATION_ERROR_02158, "IMAGE", "%s. %s", ss.str().c_str(),
70 validation_error_map[VALIDATION_ERROR_02158]);
71 }
72 if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) &&
73 ((properties.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)) {
74 std::stringstream ss;
75 ss << "vkCreateImage: VkFormat for TILING_LINEAR image (" << string_VkFormat(pCreateInfo->format)
76 << ") does not support requested Image usage type VK_IMAGE_USAGE_COLOR_ATTACHMENT";
77 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
78 __LINE__, VALIDATION_ERROR_02153, "IMAGE", "%s. %s", ss.str().c_str(),
79 validation_error_map[VALIDATION_ERROR_02153]);
80 }
81 }
82 // Validate that format supports usage as depth/stencil attachment
83 if (pCreateInfo->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
84 if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) &&
85 ((properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)) {
86 std::stringstream ss;
87 ss << "vkCreateImage: VkFormat for TILING_OPTIMAL image (" << string_VkFormat(pCreateInfo->format)
88 << ") does not support requested Image usage type VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT";
89 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
90 __LINE__, VALIDATION_ERROR_02159, "IMAGE", "%s. %s", ss.str().c_str(),
91 validation_error_map[VALIDATION_ERROR_02159]);
92 }
93 if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) &&
94 ((properties.linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)) {
95 std::stringstream ss;
96 ss << "vkCreateImage: VkFormat for TILING_LINEAR image (" << string_VkFormat(pCreateInfo->format)
97 << ") does not support requested Image usage type VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT";
98 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
99 __LINE__, VALIDATION_ERROR_02154, "IMAGE", "%s. %s", ss.str().c_str(),
100 validation_error_map[VALIDATION_ERROR_02154]);
101 }
102 }
103 } else {
104 skip_call |=
105 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
106 VALIDATION_ERROR_00715, "IMAGE", "vkCreateImage: VkFormat for image must not be VK_FORMAT_UNDEFINED. %s",
107 validation_error_map[VALIDATION_ERROR_00715]);
108 }
109
110 // Internal call to get format info. Still goes through layers, could potentially go directly to ICD.
111 core_validation::GetImageFormatPropertiesPointer(device_data)(physical_device, pCreateInfo->format, pCreateInfo->imageType,
112 pCreateInfo->tiling, pCreateInfo->usage, pCreateInfo->flags,
113 &ImageFormatProperties);
114
115 VkDeviceSize imageGranularity = core_validation::GetPhysicalDeviceProperties(device_data)->limits.bufferImageGranularity;
116 imageGranularity = imageGranularity == 1 ? 0 : imageGranularity;
117
Mark Lobodzinski688ed322017-01-27 11:13:21 -0700118 if ((pCreateInfo->extent.width <= 0) || (pCreateInfo->extent.height <= 0) || (pCreateInfo->extent.depth <= 0)) {
119 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
120 VALIDATION_ERROR_00716, "Image",
121 "CreateImage extent is 0 for at least one required dimension for image: "
122 "Width = %d Height = %d Depth = %d. %s",
123 pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth,
124 validation_error_map[VALIDATION_ERROR_00716]);
Mark Lobodzinski90224de2017-01-26 15:23:11 -0700125 }
126
127 // TODO: VALIDATION_ERROR_02125 VALIDATION_ERROR_02126 VALIDATION_ERROR_02128 VALIDATION_ERROR_00720
128 // All these extent-related VUs should be checked here
129 if ((pCreateInfo->extent.depth > ImageFormatProperties.maxExtent.depth) ||
130 (pCreateInfo->extent.width > ImageFormatProperties.maxExtent.width) ||
131 (pCreateInfo->extent.height > ImageFormatProperties.maxExtent.height)) {
132 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
133 IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
134 "CreateImage extents exceed allowable limits for format: "
135 "Width = %d Height = %d Depth = %d: Limits for Width = %d Height = %d Depth = %d for format %s.",
136 pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth,
137 ImageFormatProperties.maxExtent.width, ImageFormatProperties.maxExtent.height,
138 ImageFormatProperties.maxExtent.depth, string_VkFormat(pCreateInfo->format));
139 }
140
141 uint64_t totalSize = ((uint64_t)pCreateInfo->extent.width * (uint64_t)pCreateInfo->extent.height *
142 (uint64_t)pCreateInfo->extent.depth * (uint64_t)pCreateInfo->arrayLayers *
143 (uint64_t)pCreateInfo->samples * (uint64_t)vk_format_get_size(pCreateInfo->format) +
144 (uint64_t)imageGranularity) &
145 ~(uint64_t)imageGranularity;
146
147 if (totalSize > ImageFormatProperties.maxResourceSize) {
148 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
149 IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
150 "CreateImage resource size exceeds allowable maximum "
151 "Image resource size = 0x%" PRIxLEAST64 ", maximum resource size = 0x%" PRIxLEAST64 " ",
152 totalSize, ImageFormatProperties.maxResourceSize);
153 }
154
155 // TODO: VALIDATION_ERROR_02132
156 if (pCreateInfo->mipLevels > ImageFormatProperties.maxMipLevels) {
157 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
158 IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
159 "CreateImage mipLevels=%d exceeds allowable maximum supported by format of %d", pCreateInfo->mipLevels,
160 ImageFormatProperties.maxMipLevels);
161 }
162
163 if (pCreateInfo->arrayLayers > ImageFormatProperties.maxArrayLayers) {
164 skip_call |= log_msg(
165 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__, VALIDATION_ERROR_02133,
166 "Image", "CreateImage arrayLayers=%d exceeds allowable maximum supported by format of %d. %s", pCreateInfo->arrayLayers,
167 ImageFormatProperties.maxArrayLayers, validation_error_map[VALIDATION_ERROR_02133]);
168 }
169
170 if ((pCreateInfo->samples & ImageFormatProperties.sampleCounts) == 0) {
171 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
172 VALIDATION_ERROR_02138, "Image", "CreateImage samples %s is not supported by format 0x%.8X. %s",
173 string_VkSampleCountFlagBits(pCreateInfo->samples), ImageFormatProperties.sampleCounts,
174 validation_error_map[VALIDATION_ERROR_02138]);
175 }
176
177 if (pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_UNDEFINED && pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_PREINITIALIZED) {
178 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
179 VALIDATION_ERROR_00731, "Image",
180 "vkCreateImage parameter, pCreateInfo->initialLayout, must be VK_IMAGE_LAYOUT_UNDEFINED or "
181 "VK_IMAGE_LAYOUT_PREINITIALIZED. %s",
182 validation_error_map[VALIDATION_ERROR_00731]);
183 }
184
185 return skip_call;
186}
187
Mark Lobodzinski214144a2017-01-27 14:25:32 -0700188void PostCallRecordCreateImage(core_validation::layer_data *device_data, const VkImageCreateInfo *pCreateInfo, VkImage *pImage) {
Mark Lobodzinski42fe5f72017-01-11 11:36:16 -0700189 IMAGE_LAYOUT_NODE image_state;
190 image_state.layout = pCreateInfo->initialLayout;
191 image_state.format = pCreateInfo->format;
Mark Lobodzinski214144a2017-01-27 14:25:32 -0700192 GetImageMap(device_data)->insert(std::make_pair(*pImage, std::unique_ptr<IMAGE_STATE>(new IMAGE_STATE(*pImage, pCreateInfo))));
Mark Lobodzinski42fe5f72017-01-11 11:36:16 -0700193 ImageSubresourcePair subpair{*pImage, false, VkImageSubresource()};
Mark Lobodzinski214144a2017-01-27 14:25:32 -0700194 (*core_validation::GetImageSubresourceMap(device_data))[*pImage].push_back(subpair);
195 (*core_validation::GetImageLayoutMap(device_data))[subpair] = image_state;
Mark Lobodzinski42fe5f72017-01-11 11:36:16 -0700196}
Mark Lobodzinski9ef5d562017-01-27 12:28:30 -0700197
198bool PreCallValidateDestroyImage(core_validation::layer_data *device_data, VkImage image, IMAGE_STATE **image_state,
199 VK_OBJECT *obj_struct) {
200 const CHECK_DISABLED *disabled = core_validation::GetDisables(device_data);
201 *image_state = core_validation::getImageState(device_data, image);
202 *obj_struct = {reinterpret_cast<uint64_t &>(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT};
203 if (disabled->destroy_image) return false;
204 bool skip = false;
205 if (*image_state) {
206 skip |= core_validation::ValidateObjectNotInUse(device_data, *image_state, *obj_struct, VALIDATION_ERROR_00743);
207 }
208 return skip;
209}
210
211void PostCallRecordDestroyImage(core_validation::layer_data *device_data, VkImage image, IMAGE_STATE *image_state,
212 VK_OBJECT obj_struct) {
213 core_validation::invalidateCommandBuffers(device_data, image_state->cb_bindings, obj_struct);
214 // Clean up memory mapping, bindings and range references for image
215 for (auto mem_binding : image_state->GetBoundMemory()) {
216 auto mem_info = core_validation::getMemObjInfo(device_data, mem_binding);
217 if (mem_info) {
218 core_validation::RemoveImageMemoryRange(obj_struct.handle, mem_info);
219 }
220 }
221 core_validation::ClearMemoryObjectBindings(device_data, obj_struct.handle, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT);
222 // Remove image from imageMap
223 core_validation::GetImageMap(device_data)->erase(image);
224 std::unordered_map<VkImage, std::vector<ImageSubresourcePair>> *imageSubresourceMap =
225 core_validation::GetImageSubresourceMap(device_data);
226
227 const auto &sub_entry = imageSubresourceMap->find(image);
228 if (sub_entry != imageSubresourceMap->end()) {
229 for (const auto &pair : sub_entry->second) {
230 core_validation::GetImageLayoutMap(device_data)->erase(pair);
231 }
232 imageSubresourceMap->erase(sub_entry);
233 }
234}
Mark Lobodzinskic409a582017-01-27 15:16:01 -0700235
236bool ValidateImageAttributes(core_validation::layer_data *device_data, IMAGE_STATE *image_state, VkImageSubresourceRange range) {
237 bool skip = false;
238 const debug_report_data *report_data = core_validation::GetReportData(device_data);
239
240 if (range.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
241 char const str[] = "vkCmdClearColorImage aspectMasks for all subresource ranges must be set to VK_IMAGE_ASPECT_COLOR_BIT";
242 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
243 reinterpret_cast<uint64_t &>(image_state->image), __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", str);
244 }
245
246 if (vk_format_is_depth_or_stencil(image_state->createInfo.format)) {
247 char const str[] = "vkCmdClearColorImage called with depth/stencil image.";
248 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
249 reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01088, "IMAGE", "%s. %s", str,
250 validation_error_map[VALIDATION_ERROR_01088]);
251 } else if (vk_format_is_compressed(image_state->createInfo.format)) {
252 char const str[] = "vkCmdClearColorImage called with compressed image.";
253 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
254 reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01088, "IMAGE", "%s. %s", str,
255 validation_error_map[VALIDATION_ERROR_01088]);
256 }
257
258 if (!(image_state->createInfo.usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
259 char const str[] = "vkCmdClearColorImage called with image created without VK_IMAGE_USAGE_TRANSFER_DST_BIT.";
260 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
261 reinterpret_cast<uint64_t &>(image_state->image), __LINE__, VALIDATION_ERROR_01084, "IMAGE", "%s. %s", str,
262 validation_error_map[VALIDATION_ERROR_01084]);
263 }
264 return skip;
265}
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700266
Mark Lobodzinski9c93dbd2017-02-02 08:31:18 -0700267void ResolveRemainingLevelsLayers(core_validation::layer_data *dev_data, VkImageSubresourceRange *range, IMAGE_STATE *image_state) {
268 // If the caller used the special values VK_REMAINING_MIP_LEVELS and VK_REMAINING_ARRAY_LAYERS, resolve them now in our
269 // internal state to the actual values.
270 if (range->levelCount == VK_REMAINING_MIP_LEVELS) {
271 range->levelCount = image_state->createInfo.mipLevels - range->baseMipLevel;
272 }
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700273
Mark Lobodzinski9c93dbd2017-02-02 08:31:18 -0700274 if (range->layerCount == VK_REMAINING_ARRAY_LAYERS) {
275 range->layerCount = image_state->createInfo.arrayLayers - range->baseArrayLayer;
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700276 }
277}
278
279// Return the correct layer/level counts if the caller used the special values VK_REMAINING_MIP_LEVELS or VK_REMAINING_ARRAY_LAYERS.
280void ResolveRemainingLevelsLayers(core_validation::layer_data *dev_data, uint32_t *levels, uint32_t *layers,
Mark Lobodzinski9c93dbd2017-02-02 08:31:18 -0700281 VkImageSubresourceRange range, IMAGE_STATE *image_state) {
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700282 *levels = range.levelCount;
283 *layers = range.layerCount;
Mark Lobodzinski9c93dbd2017-02-02 08:31:18 -0700284 if (range.levelCount == VK_REMAINING_MIP_LEVELS) {
285 *levels = image_state->createInfo.mipLevels - range.baseMipLevel;
286 }
287 if (range.layerCount == VK_REMAINING_ARRAY_LAYERS) {
288 *layers = image_state->createInfo.arrayLayers - range.baseArrayLayer;
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700289 }
290}
291
Mark Lobodzinski9c93dbd2017-02-02 08:31:18 -0700292bool VerifyClearImageLayout(core_validation::layer_data *device_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *image_state,
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700293 VkImageSubresourceRange range, VkImageLayout dest_image_layout, const char *func_name) {
294 bool skip = false;
295 const debug_report_data *report_data = core_validation::GetReportData(device_data);
296
297 VkImageSubresourceRange resolved_range = range;
Mark Lobodzinski9c93dbd2017-02-02 08:31:18 -0700298 ResolveRemainingLevelsLayers(device_data, &resolved_range, image_state);
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700299
300 if (dest_image_layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
301 if (dest_image_layout == VK_IMAGE_LAYOUT_GENERAL) {
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700302 if (image_state->createInfo.tiling != VK_IMAGE_TILING_LINEAR) {
303 // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning.
304 skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
305 __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
306 "%s: Layout for cleared image should be TRANSFER_DST_OPTIMAL instead of GENERAL.", func_name);
307 }
308 } else {
309 UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_01086;
310 if (strcmp(func_name, "vkCmdClearDepthStencilImage()") == 0) {
311 error_code = VALIDATION_ERROR_01101;
312 } else {
313 assert(strcmp(func_name, "vkCmdClearColorImage()") == 0);
314 }
315 skip |=
316 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, error_code, "DS",
317 "%s: Layout for cleared image is %s but can only be "
318 "TRANSFER_DST_OPTIMAL or GENERAL. %s",
319 func_name, string_VkImageLayout(dest_image_layout), validation_error_map[error_code]);
320 }
321 }
322
323 for (uint32_t level_index = 0; level_index < resolved_range.levelCount; ++level_index) {
324 uint32_t level = level_index + resolved_range.baseMipLevel;
325 for (uint32_t layer_index = 0; layer_index < resolved_range.layerCount; ++layer_index) {
326 uint32_t layer = layer_index + resolved_range.baseArrayLayer;
327 VkImageSubresource sub = {resolved_range.aspectMask, level, layer};
328 IMAGE_CMD_BUF_LAYOUT_NODE node;
Mark Lobodzinski9c93dbd2017-02-02 08:31:18 -0700329 if (core_validation::FindLayout(cb_node, image_state->image, sub, node)) {
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700330 if (node.layout != dest_image_layout) {
331 UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_01085;
332 if (strcmp(func_name, "vkCmdClearDepthStencilImage()") == 0) {
333 error_code = VALIDATION_ERROR_01100;
334 } else {
335 assert(strcmp(func_name, "vkCmdClearColorImage()") == 0);
336 }
337 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
338 __LINE__, error_code, "DS",
339 "%s: Cannot clear an image whose layout is %s and "
340 "doesn't match the current layout %s. %s",
341 func_name, string_VkImageLayout(dest_image_layout), string_VkImageLayout(node.layout),
342 validation_error_map[error_code]);
343 }
344 }
345 }
346 }
347
348 return skip;
349}
350
Mark Lobodzinski9c93dbd2017-02-02 08:31:18 -0700351void RecordClearImageLayout(core_validation::layer_data *device_data, GLOBAL_CB_NODE *cb_node, VkImage image,
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700352 VkImageSubresourceRange range, VkImageLayout dest_image_layout) {
353 VkImageSubresourceRange resolved_range = range;
Mark Lobodzinski9c93dbd2017-02-02 08:31:18 -0700354 ResolveRemainingLevelsLayers(device_data, &resolved_range, getImageState(device_data, image));
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700355
356 for (uint32_t level_index = 0; level_index < resolved_range.levelCount; ++level_index) {
357 uint32_t level = level_index + resolved_range.baseMipLevel;
358 for (uint32_t layer_index = 0; layer_index < resolved_range.layerCount; ++layer_index) {
359 uint32_t layer = layer_index + resolved_range.baseArrayLayer;
360 VkImageSubresource sub = {resolved_range.aspectMask, level, layer};
361 IMAGE_CMD_BUF_LAYOUT_NODE node;
362 if (!core_validation::FindLayout(cb_node, image, sub, node)) {
363 SetLayout(cb_node, image, sub, IMAGE_CMD_BUF_LAYOUT_NODE(dest_image_layout, dest_image_layout));
364 }
365 }
366 }
367}
368
369bool PreCallValidateCmdClearColorImage(core_validation::layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image,
370 VkImageLayout imageLayout, uint32_t rangeCount, const VkImageSubresourceRange *pRanges) {
371 bool skip = false;
372 // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state
373 auto cb_node = core_validation::getCBNode(dev_data, commandBuffer);
374 auto image_state = getImageState(dev_data, image);
375 if (cb_node && image_state) {
376 skip |= ValidateMemoryIsBoundToImage(dev_data, image_state, "vkCmdClearColorImage()", VALIDATION_ERROR_02527);
377 skip |= ValidateCmd(dev_data, cb_node, CMD_CLEARCOLORIMAGE, "vkCmdClearColorImage()");
378 skip |= insideRenderPass(dev_data, cb_node, "vkCmdClearColorImage()", VALIDATION_ERROR_01096);
379 for (uint32_t i = 0; i < rangeCount; ++i) {
380 skip |= ValidateImageAttributes(dev_data, image_state, pRanges[i]);
Mark Lobodzinski9c93dbd2017-02-02 08:31:18 -0700381 skip |= VerifyClearImageLayout(dev_data, cb_node, image_state, pRanges[i], imageLayout, "vkCmdClearColorImage()");
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700382 }
383 }
384 return skip;
385}
386
387// This state recording routine is shared between ClearColorImage and ClearDepthStencilImage
388void PreCallRecordCmdClearImage(core_validation::layer_data *dev_data, VkCommandBuffer commandBuffer, VkImage image,
389 VkImageLayout imageLayout, uint32_t rangeCount, const VkImageSubresourceRange *pRanges,
390 CMD_TYPE cmd_type) {
391 auto cb_node = getCBNode(dev_data, commandBuffer);
392 auto image_state = getImageState(dev_data, image);
393 if (cb_node && image_state) {
394 AddCommandBufferBindingImage(dev_data, cb_node, image_state);
395 std::function<bool()> function = [=]() {
396 SetImageMemoryValid(dev_data, image_state, true);
397 return false;
398 };
399 cb_node->validate_functions.push_back(function);
400 UpdateCmdBufferLastCmd(dev_data, cb_node, cmd_type);
401 for (uint32_t i = 0; i < rangeCount; ++i) {
402 RecordClearImageLayout(dev_data, cb_node, image, pRanges[i], imageLayout);
403 }
404 }
405}
406
Mark Lobodzinski1241a312017-02-01 10:57:21 -0700407bool PreCallValidateCmdClearDepthStencilImage(core_validation::layer_data *device_data, VkCommandBuffer commandBuffer,
408 VkImage image, VkImageLayout imageLayout, uint32_t rangeCount,
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700409 const VkImageSubresourceRange *pRanges) {
410 bool skip = false;
Mark Lobodzinski1241a312017-02-01 10:57:21 -0700411 const debug_report_data *report_data = core_validation::GetReportData(device_data);
412
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700413 // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state
Mark Lobodzinski1241a312017-02-01 10:57:21 -0700414 auto cb_node = getCBNode(device_data, commandBuffer);
415 auto image_state = getImageState(device_data, image);
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700416 if (cb_node && image_state) {
Mark Lobodzinski1241a312017-02-01 10:57:21 -0700417 skip |= ValidateMemoryIsBoundToImage(device_data, image_state, "vkCmdClearDepthStencilImage()", VALIDATION_ERROR_02528);
418 skip |= ValidateCmd(device_data, cb_node, CMD_CLEARDEPTHSTENCILIMAGE, "vkCmdClearDepthStencilImage()");
419 skip |= insideRenderPass(device_data, cb_node, "vkCmdClearDepthStencilImage()", VALIDATION_ERROR_01111);
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700420 for (uint32_t i = 0; i < rangeCount; ++i) {
Mark Lobodzinski9c93dbd2017-02-02 08:31:18 -0700421 skip |=
422 VerifyClearImageLayout(device_data, cb_node, image_state, pRanges[i], imageLayout, "vkCmdClearDepthStencilImage()");
Mark Lobodzinski1241a312017-02-01 10:57:21 -0700423 // Image aspect must be depth or stencil or both
424 if (((pRanges[i].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
425 ((pRanges[i].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT)) {
426 char const str[] =
427 "vkCmdClearDepthStencilImage aspectMasks for all subresource ranges must be "
428 "set to VK_IMAGE_ASPECT_DEPTH_BIT and/or VK_IMAGE_ASPECT_STENCIL_BIT";
429 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
430 (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_IMAGE_ASPECT, "IMAGE", str);
431 }
432 }
433 if (image_state && !vk_format_is_depth_or_stencil(image_state->createInfo.format)) {
434 char const str[] = "vkCmdClearDepthStencilImage called without a depth/stencil image.";
435 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
436 reinterpret_cast<uint64_t &>(image), __LINE__, VALIDATION_ERROR_01103, "IMAGE", "%s. %s", str,
437 validation_error_map[VALIDATION_ERROR_01103]);
Mark Lobodzinskid81d1012017-02-01 09:03:06 -0700438 }
439 }
440 return skip;
441}