blob: 1b650aaa5a7a4a681ac9d578a9beb2415c6849a0 [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
118 // Make sure all required dimension are non-zero at least.
119 bool failedMinSize = false;
120 switch (pCreateInfo->imageType) {
121 case VK_IMAGE_TYPE_3D:
122 if (pCreateInfo->extent.depth == 0) {
123 failedMinSize = true;
124 }
125 // Intentional fall-through
126 case VK_IMAGE_TYPE_2D:
127 if (pCreateInfo->extent.height == 0) {
128 failedMinSize = true;
129 }
130 // Intentional fall-through
131 case VK_IMAGE_TYPE_1D:
132 if (pCreateInfo->extent.width == 0) {
133 failedMinSize = true;
134 }
135 break;
136 default:
137 break;
138 }
139 // TODO: VALIDATION_ERROR_00716
140 // this is *almost* VU 00716, except should not be condidtional on image type - all extents must be non-zero for all types
141 if (failedMinSize) {
142 skip_call |=
143 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
144 IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
145 "CreateImage extents is 0 for at least one required dimension for image of type %d: "
146 "Width = %d Height = %d Depth = %d.",
147 pCreateInfo->imageType, pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth);
148 }
149
150 // TODO: VALIDATION_ERROR_02125 VALIDATION_ERROR_02126 VALIDATION_ERROR_02128 VALIDATION_ERROR_00720
151 // All these extent-related VUs should be checked here
152 if ((pCreateInfo->extent.depth > ImageFormatProperties.maxExtent.depth) ||
153 (pCreateInfo->extent.width > ImageFormatProperties.maxExtent.width) ||
154 (pCreateInfo->extent.height > ImageFormatProperties.maxExtent.height)) {
155 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
156 IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
157 "CreateImage extents exceed allowable limits for format: "
158 "Width = %d Height = %d Depth = %d: Limits for Width = %d Height = %d Depth = %d for format %s.",
159 pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth,
160 ImageFormatProperties.maxExtent.width, ImageFormatProperties.maxExtent.height,
161 ImageFormatProperties.maxExtent.depth, string_VkFormat(pCreateInfo->format));
162 }
163
164 uint64_t totalSize = ((uint64_t)pCreateInfo->extent.width * (uint64_t)pCreateInfo->extent.height *
165 (uint64_t)pCreateInfo->extent.depth * (uint64_t)pCreateInfo->arrayLayers *
166 (uint64_t)pCreateInfo->samples * (uint64_t)vk_format_get_size(pCreateInfo->format) +
167 (uint64_t)imageGranularity) &
168 ~(uint64_t)imageGranularity;
169
170 if (totalSize > ImageFormatProperties.maxResourceSize) {
171 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
172 IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
173 "CreateImage resource size exceeds allowable maximum "
174 "Image resource size = 0x%" PRIxLEAST64 ", maximum resource size = 0x%" PRIxLEAST64 " ",
175 totalSize, ImageFormatProperties.maxResourceSize);
176 }
177
178 // TODO: VALIDATION_ERROR_02132
179 if (pCreateInfo->mipLevels > ImageFormatProperties.maxMipLevels) {
180 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
181 IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
182 "CreateImage mipLevels=%d exceeds allowable maximum supported by format of %d", pCreateInfo->mipLevels,
183 ImageFormatProperties.maxMipLevels);
184 }
185
186 if (pCreateInfo->arrayLayers > ImageFormatProperties.maxArrayLayers) {
187 skip_call |= log_msg(
188 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__, VALIDATION_ERROR_02133,
189 "Image", "CreateImage arrayLayers=%d exceeds allowable maximum supported by format of %d. %s", pCreateInfo->arrayLayers,
190 ImageFormatProperties.maxArrayLayers, validation_error_map[VALIDATION_ERROR_02133]);
191 }
192
193 if ((pCreateInfo->samples & ImageFormatProperties.sampleCounts) == 0) {
194 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
195 VALIDATION_ERROR_02138, "Image", "CreateImage samples %s is not supported by format 0x%.8X. %s",
196 string_VkSampleCountFlagBits(pCreateInfo->samples), ImageFormatProperties.sampleCounts,
197 validation_error_map[VALIDATION_ERROR_02138]);
198 }
199
200 if (pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_UNDEFINED && pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_PREINITIALIZED) {
201 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 0, __LINE__,
202 VALIDATION_ERROR_00731, "Image",
203 "vkCreateImage parameter, pCreateInfo->initialLayout, must be VK_IMAGE_LAYOUT_UNDEFINED or "
204 "VK_IMAGE_LAYOUT_PREINITIALIZED. %s",
205 validation_error_map[VALIDATION_ERROR_00731]);
206 }
207
208 return skip_call;
209}
210
Mark Lobodzinskibf93db72017-01-17 16:24:29 -0700211void PostCallRecordCreateImage(std::unordered_map<VkImage, std::unique_ptr<IMAGE_STATE>> *imageMap,
212 std::unordered_map<VkImage, std::vector<ImageSubresourcePair>> *imageSubresourceMap,
213 std::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> *imageLayoutMap,
214 const VkImageCreateInfo *pCreateInfo, VkImage *pImage) {
Mark Lobodzinski42fe5f72017-01-11 11:36:16 -0700215 IMAGE_LAYOUT_NODE image_state;
216 image_state.layout = pCreateInfo->initialLayout;
217 image_state.format = pCreateInfo->format;
Mark Lobodzinskibf93db72017-01-17 16:24:29 -0700218 (*imageMap).insert(std::make_pair(*pImage, std::unique_ptr<IMAGE_STATE>(new IMAGE_STATE(*pImage, pCreateInfo))));
Mark Lobodzinski42fe5f72017-01-11 11:36:16 -0700219 ImageSubresourcePair subpair{*pImage, false, VkImageSubresource()};
Mark Lobodzinskibf93db72017-01-17 16:24:29 -0700220 (*imageSubresourceMap)[*pImage].push_back(subpair);
221 (*imageLayoutMap)[subpair] = image_state;
Mark Lobodzinski42fe5f72017-01-11 11:36:16 -0700222}