blob: 116f49f79c15f19c3073f44044ef689f8d8acb02 [file] [log] [blame]
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -07001/* Copyright (c) 2015-2016 The Khronos Group Inc.
2 * Copyright (c) 2015-2016 Valve Corporation
3 * Copyright (c) 2015-2016 LunarG, Inc.
4 * Copyright (C) 2015-2016 Google Inc.
Jeremy Hayes9cc31582015-06-18 10:12:39 -06005 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -06006 * 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
Jeremy Hayes9cc31582015-06-18 10:12:39 -06009 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060010 * http://www.apache.org/licenses/LICENSE-2.0
Jeremy Hayes9cc31582015-06-18 10:12:39 -060011 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060012 * 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.
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060017 *
18 * Author: Jeremy Hayes <jeremy@lunarg.com>
19 * Author: Mark Lobodzinski <mark@lunarg.com>
20 * Author: Mike Stroyan <mike@LunarG.com>
21 * Author: Tobin Ehlis <tobin@lunarg.com>
Jeremy Hayes9cc31582015-06-18 10:12:39 -060022 */
23
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -060024// Allow use of STL min and max functions in Windows
25#define NOMINMAX
26
Jeremy Hayese0ed6a22016-04-08 09:53:54 -060027#include <algorithm>
28#include <assert.h>
Karl Schultzd7f37542016-05-10 11:36:08 -060029#include <cinttypes>
Jeremy Hayese0ed6a22016-04-08 09:53:54 -060030#include <memory>
31#include <mutex>
Jeremy Hayes9cc31582015-06-18 10:12:39 -060032#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
Jeremy Hayes9cc31582015-06-18 10:12:39 -060035#include <unordered_map>
Jeremy Hayese0ed6a22016-04-08 09:53:54 -060036#include <vector>
Jeremy Hayes9cc31582015-06-18 10:12:39 -060037
Tobin Ehlisb835d1b2015-07-03 10:34:49 -060038#include "vk_loader_platform.h"
Courtney Goeltzenleuchter8f8367e2015-10-07 08:38:30 -060039#include "vk_dispatch_table_helper.h"
40#include "vk_struct_string_helper_cpp.h"
Jeremy Hayes9cc31582015-06-18 10:12:39 -060041#include "vk_enum_validate_helper.h"
Courtney Goeltzenleuchter8f8367e2015-10-07 08:38:30 -060042#include "image.h"
43#include "vk_layer_config.h"
44#include "vk_layer_extension_utils.h"
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -060045#include "vk_layer_table.h"
46#include "vk_layer_data.h"
Courtney Goeltzenleuchter426e1872015-07-07 11:18:30 -060047#include "vk_layer_extension_utils.h"
Mike Stroyana3082432015-09-25 13:39:21 -060048#include "vk_layer_utils.h"
Courtney Goeltzenleuchter8f8367e2015-10-07 08:38:30 -060049#include "vk_layer_logging.h"
Jeremy Hayes9cc31582015-06-18 10:12:39 -060050
Mark Muelleraab36502016-05-03 13:17:29 -060051using namespace std;
52
Chia-I Wuaacb0fc2016-04-28 11:27:46 +080053namespace image {
54
Cody Northrop55443ef2015-09-28 15:09:32 -060055struct layer_data {
Chia-I Wu2cfc77c2016-04-28 16:04:15 +080056 VkInstance instance;
57
Jon Ashburn5484e0c2016-03-08 17:48:44 -070058 debug_report_data *report_data;
59 vector<VkDebugReportCallbackEXT> logging_callback;
60 VkLayerDispatchTable *device_dispatch_table;
Mark Lobodzinskid5a23822015-11-12 15:14:35 -070061 VkLayerInstanceDispatchTable *instance_dispatch_table;
Jon Ashburn5484e0c2016-03-08 17:48:44 -070062 VkPhysicalDevice physicalDevice;
63 VkPhysicalDeviceProperties physicalDeviceProperties;
Mark Lobodzinskid5a23822015-11-12 15:14:35 -070064
Chia-I Wue2fc5522015-10-26 20:04:44 +080065 unordered_map<VkImage, IMAGE_STATE> imageMap;
Cody Northrop55443ef2015-09-28 15:09:32 -060066
Jon Ashburn5484e0c2016-03-08 17:48:44 -070067 layer_data()
68 : report_data(nullptr), device_dispatch_table(nullptr), instance_dispatch_table(nullptr), physicalDevice(0),
69 physicalDeviceProperties(){};
Cody Northrop55443ef2015-09-28 15:09:32 -060070};
Jeremy Hayes9cc31582015-06-18 10:12:39 -060071
Jon Ashburn5484e0c2016-03-08 17:48:44 -070072static unordered_map<void *, layer_data *> layer_data_map;
Jeremy Hayese0ed6a22016-04-08 09:53:54 -060073static std::mutex global_lock;
Jeremy Hayes9cc31582015-06-18 10:12:39 -060074
Mark Lobodzinski1079e1b2016-03-15 14:21:59 -060075static void init_image(layer_data *my_data, const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1079e1b2016-03-15 14:21:59 -060076 layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_image");
Jeremy Hayes9cc31582015-06-18 10:12:39 -060077}
78
Tobin Ehlisf4d352b2016-05-19 09:59:30 -060079static IMAGE_STATE const *getImageState(layer_data const *dev_data, VkImage image) {
80 auto it = dev_data->imageMap.find(image);
81 if (it == dev_data->imageMap.end()) {
82 return nullptr;
83 }
84 return &it->second;
85}
86
Chia-I Wu4935c762016-04-28 14:01:30 +080087VKAPI_ATTR VkResult VKAPI_CALL
88CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
89 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070090 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
91 VkResult res = my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Jeremy Hayes9cc31582015-06-18 10:12:39 -060092 if (res == VK_SUCCESS) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -060093 res = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
Jeremy Hayes9cc31582015-06-18 10:12:39 -060094 }
95 return res;
96}
97
Chia-I Wu4935c762016-04-28 14:01:30 +080098VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance,
99 VkDebugReportCallbackEXT msgCallback,
100 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700101 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
102 my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700103 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600104}
105
Chia-I Wu4935c762016-04-28 14:01:30 +0800106VKAPI_ATTR void VKAPI_CALL
107DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
108 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700109 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700110 my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix,
111 pMsg);
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700112}
113
Chia-I Wu4935c762016-04-28 14:01:30 +0800114VKAPI_ATTR VkResult VKAPI_CALL
115CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700116 VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600117
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700118 assert(chain_info->u.pLayerInfo);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700119 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700120 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700121 if (fpCreateInstance == NULL) {
122 return VK_ERROR_INITIALIZATION_FAILED;
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600123 }
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700124
125 // Advance the link info for the next element on the chain
126 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
127
128 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
129 if (result != VK_SUCCESS)
130 return result;
131
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700132 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
Chia-I Wu2cfc77c2016-04-28 16:04:15 +0800133 my_data->instance = *pInstance;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700134 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700135 layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700136
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700137 my_data->report_data = debug_report_create_instance(my_data->instance_dispatch_table, *pInstance,
138 pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700139
Mark Lobodzinski1079e1b2016-03-15 14:21:59 -0600140 init_image(my_data, pAllocator);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700141
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600142 return result;
143}
144
Chia-I Wu4935c762016-04-28 14:01:30 +0800145VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600146 // Grab the key before the instance is destroyed.
147 dispatch_key key = get_dispatch_key(instance);
Tobin Ehlisb74f6ab2015-10-29 14:19:18 -0600148 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
149 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Chia-I Wuf7458c52015-10-26 21:10:41 +0800150 pTable->DestroyInstance(instance, pAllocator);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600151
152 // Clean up logging callback, if any
Courtney Goeltzenleuchterffcdd8b2015-10-05 15:59:11 -0600153 while (my_data->logging_callback.size() > 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700154 VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700155 layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
Courtney Goeltzenleuchterffcdd8b2015-10-05 15:59:11 -0600156 my_data->logging_callback.pop_back();
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600157 }
158
Tobin Ehlisb74f6ab2015-10-29 14:19:18 -0600159 layer_debug_report_destroy_instance(my_data->report_data);
160 delete my_data->instance_dispatch_table;
161 layer_data_map.erase(key);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600162}
163
Chia-I Wu4935c762016-04-28 14:01:30 +0800164VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice physicalDevice,
165 const VkDeviceCreateInfo *pCreateInfo,
166 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Chia-I Wu2cfc77c2016-04-28 16:04:15 +0800167 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700168 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700169
170 assert(chain_info->u.pLayerInfo);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700171 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
172 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Chia-I Wu2cfc77c2016-04-28 16:04:15 +0800173 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700174 if (fpCreateDevice == NULL) {
175 return VK_ERROR_INITIALIZATION_FAILED;
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600176 }
177
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700178 // Advance the link info for the next element on the chain
179 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
180
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700181 VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700182 if (result != VK_SUCCESS) {
183 return result;
184 }
185
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700186 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700187
188 // Setup device dispatch table
189 my_device_data->device_dispatch_table = new VkLayerDispatchTable;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700190 layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700191
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700192 my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700193 my_device_data->physicalDevice = physicalDevice;
194
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700195 my_instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice,
196 &(my_device_data->physicalDeviceProperties));
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700197
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600198 return result;
199}
200
Chia-I Wu4935c762016-04-28 14:01:30 +0800201VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600202 dispatch_key key = get_dispatch_key(device);
Tobin Ehlisb74f6ab2015-10-29 14:19:18 -0600203 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +0800204 my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
Tobin Ehlisb74f6ab2015-10-29 14:19:18 -0600205 delete my_data->device_dispatch_table;
206 layer_data_map.erase(key);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600207}
208
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700209static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600210
Chia-I Wu740891e2016-04-28 14:12:27 +0800211static const VkLayerProperties global_layer = {
Jon Ashburndc9111c2016-03-22 12:57:13 -0600212 "VK_LAYER_LUNARG_image", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer",
Chia-I Wu740891e2016-04-28 14:12:27 +0800213};
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -0700214
Mark Lobodzinski2fd634c2015-07-29 09:21:22 -0600215// Start of the Image layer proper
216
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700217static inline uint32_t validate_VkImageLayoutKHR(VkImageLayout input_value) {
218 return ((validate_VkImageLayout(input_value) == 1) || (input_value == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR));
Mark Lobodzinski601ed152015-11-10 11:01:32 -0700219}
220
Mark Lobodzinski9d1d6b12016-05-17 08:42:03 -0600221VKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
222 const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
223 bool skip_call = false;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700224 VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
Michael Lentine0a369f62016-02-03 16:51:46 -0600225 VkImageFormatProperties ImageFormatProperties;
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700226
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700227 layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
228 VkPhysicalDevice physicalDevice = device_data->physicalDevice;
229 layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700230
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700231 if (pCreateInfo->format != VK_FORMAT_UNDEFINED) {
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600232 VkFormatProperties properties;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700233 phy_dev_data->instance_dispatch_table->GetPhysicalDeviceFormatProperties(device_data->physicalDevice, pCreateInfo->format,
234 &properties);
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700235 if ((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0)) {
Mark Lobodzinski9d1d6b12016-05-17 08:42:03 -0600236 std::stringstream ss;
237 ss << "vkCreateImage format parameter (" << string_VkFormat(pCreateInfo->format) << ") is an unsupported format";
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700238 // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
Mark Lobodzinski9d1d6b12016-05-17 08:42:03 -0600239 skip_call |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
240 0, __LINE__, IMAGE_FORMAT_UNSUPPORTED, "IMAGE", "%s", ss.str().c_str());
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600241 }
Mark Lobodzinski9d1d6b12016-05-17 08:42:03 -0600242
243 // Validate that format supports usage as color attachment
244 if (pCreateInfo->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
245 if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) &&
246 ((properties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)) {
247 std::stringstream ss;
248 ss << "vkCreateImage: VkFormat for TILING_OPTIMAL image (" << string_VkFormat(pCreateInfo->format)
249 << ") does not support requested Image usage type VK_IMAGE_USAGE_COLOR_ATTACHMENT";
250 skip_call |=
251 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
252 __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
253 }
254 if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) &&
255 ((properties.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)) {
256 std::stringstream ss;
257 ss << "vkCreateImage: VkFormat for TILING_LINEAR image (" << string_VkFormat(pCreateInfo->format)
258 << ") does not support requested Image usage type VK_IMAGE_USAGE_COLOR_ATTACHMENT";
259 skip_call |=
260 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
261 __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
262 }
263 }
264 // Validate that format supports usage as depth/stencil attachment
265 if (pCreateInfo->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
266 if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) &&
267 ((properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)) {
268 std::stringstream ss;
269 ss << "vkCreateImage: VkFormat for TILING_OPTIMAL image (" << string_VkFormat(pCreateInfo->format)
270 << ") does not support requested Image usage type VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT";
271 skip_call |=
272 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
273 __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
274 }
275 if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) &&
276 ((properties.linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)) {
277 std::stringstream ss;
278 ss << "vkCreateImage: VkFormat for TILING_LINEAR image (" << string_VkFormat(pCreateInfo->format)
279 << ") does not support requested Image usage type VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT";
280 skip_call |=
281 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
282 __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
283 }
284 }
285 } else {
286 skip_call |=
287 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
288 IMAGE_INVALID_FORMAT, "IMAGE", "vkCreateImage: VkFormat for image must not be VK_FORMAT_UNDEFINED");
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600289 }
290
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700291 // Internal call to get format info. Still goes through layers, could potentially go directly to ICD.
292 phy_dev_data->instance_dispatch_table->GetPhysicalDeviceImageFormatProperties(
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700293 physicalDevice, pCreateInfo->format, pCreateInfo->imageType, pCreateInfo->tiling, pCreateInfo->usage, pCreateInfo->flags,
294 &ImageFormatProperties);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600295
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700296 VkDeviceSize imageGranularity = device_data->physicalDeviceProperties.limits.bufferImageGranularity;
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700297 imageGranularity = imageGranularity == 1 ? 0 : imageGranularity;
298
Mark Youngc48c4c12016-04-11 14:26:49 -0600299 // Make sure all required dimension are non-zero at least.
300 bool failedMinSize = false;
301 switch (pCreateInfo->imageType) {
302 case VK_IMAGE_TYPE_3D:
303 if (pCreateInfo->extent.depth == 0) {
304 failedMinSize = true;
305 }
306 // Intentional fall-through
307 case VK_IMAGE_TYPE_2D:
308 if (pCreateInfo->extent.height == 0) {
309 failedMinSize = true;
310 }
311 // Intentional fall-through
312 case VK_IMAGE_TYPE_1D:
313 if (pCreateInfo->extent.width == 0) {
314 failedMinSize = true;
315 }
316 break;
317 default:
318 break;
319 }
320 if (failedMinSize) {
Mark Lobodzinski9d1d6b12016-05-17 08:42:03 -0600321 skip_call |=
Mark Youngc48c4c12016-04-11 14:26:49 -0600322 log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
Mark Lobodzinski9d1d6b12016-05-17 08:42:03 -0600323 0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
Mark Youngc48c4c12016-04-11 14:26:49 -0600324 "CreateImage extents is 0 for at least one required dimension for image of type %d: "
325 "Width = %d Height = %d Depth = %d.",
326 pCreateInfo->imageType, pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth);
327 }
328
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700329 if ((pCreateInfo->extent.depth > ImageFormatProperties.maxExtent.depth) ||
330 (pCreateInfo->extent.width > ImageFormatProperties.maxExtent.width) ||
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700331 (pCreateInfo->extent.height > ImageFormatProperties.maxExtent.height)) {
Mark Lobodzinski9d1d6b12016-05-17 08:42:03 -0600332 skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
333 0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700334 "CreateImage extents exceed allowable limits for format: "
335 "Width = %d Height = %d Depth = %d: Limits for Width = %d Height = %d Depth = %d for format %s.",
336 pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth,
337 ImageFormatProperties.maxExtent.width, ImageFormatProperties.maxExtent.height,
338 ImageFormatProperties.maxExtent.depth, string_VkFormat(pCreateInfo->format));
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700339 }
340
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700341 uint64_t totalSize = ((uint64_t)pCreateInfo->extent.width * (uint64_t)pCreateInfo->extent.height *
342 (uint64_t)pCreateInfo->extent.depth * (uint64_t)pCreateInfo->arrayLayers *
343 (uint64_t)pCreateInfo->samples * (uint64_t)vk_format_get_size(pCreateInfo->format) +
344 (uint64_t)imageGranularity) &
345 ~(uint64_t)imageGranularity;
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700346
347 if (totalSize > ImageFormatProperties.maxResourceSize) {
Mark Lobodzinski9d1d6b12016-05-17 08:42:03 -0600348 skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
349 0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700350 "CreateImage resource size exceeds allowable maximum "
Mark Muelleraab36502016-05-03 13:17:29 -0600351 "Image resource size = 0x%" PRIxLEAST64 ", maximum resource size = 0x%" PRIxLEAST64 " ",
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700352 totalSize, ImageFormatProperties.maxResourceSize);
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700353 }
354
355 if (pCreateInfo->mipLevels > ImageFormatProperties.maxMipLevels) {
Mark Lobodzinski9d1d6b12016-05-17 08:42:03 -0600356 skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
357 0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700358 "CreateImage mipLevels=%d exceeds allowable maximum supported by format of %d", pCreateInfo->mipLevels,
359 ImageFormatProperties.maxMipLevels);
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700360 }
361
362 if (pCreateInfo->arrayLayers > ImageFormatProperties.maxArrayLayers) {
Mark Lobodzinski9d1d6b12016-05-17 08:42:03 -0600363 skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
364 0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700365 "CreateImage arrayLayers=%d exceeds allowable maximum supported by format of %d",
366 pCreateInfo->arrayLayers, ImageFormatProperties.maxArrayLayers);
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700367 }
368
369 if ((pCreateInfo->samples & ImageFormatProperties.sampleCounts) == 0) {
Mark Lobodzinski9d1d6b12016-05-17 08:42:03 -0600370 skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
371 0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700372 "CreateImage samples %s is not supported by format 0x%.8X",
373 string_VkSampleCountFlagBits(pCreateInfo->samples), ImageFormatProperties.sampleCounts);
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700374 }
375
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700376 if (pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_UNDEFINED && pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_PREINITIALIZED) {
Mark Lobodzinski9d1d6b12016-05-17 08:42:03 -0600377 skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
378 0, __LINE__, IMAGE_INVALID_LAYOUT, "Image",
Jeremy Hayesffc8a702016-03-01 14:01:45 -0700379 "vkCreateImage parameter, pCreateInfo->initialLayout, must be VK_IMAGE_LAYOUT_UNDEFINED or "
380 "VK_IMAGE_LAYOUT_PREINITIALIZED");
381 }
382
Mark Lobodzinski9d1d6b12016-05-17 08:42:03 -0600383 if (!skip_call) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700384 result = device_data->device_dispatch_table->CreateImage(device, pCreateInfo, pAllocator, pImage);
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700385 }
386 if (result == VK_SUCCESS) {
Jeremy Hayese0ed6a22016-04-08 09:53:54 -0600387 std::lock_guard<std::mutex> lock(global_lock);
Chia-I Wue2fc5522015-10-26 20:04:44 +0800388 device_data->imageMap[*pImage] = IMAGE_STATE(pCreateInfo);
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600389 }
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600390 return result;
391}
392
Chia-I Wu4935c762016-04-28 14:01:30 +0800393VKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700394 layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayese0ed6a22016-04-08 09:53:54 -0600395 std::unique_lock<std::mutex> lock(global_lock);
Chia-I Wue2fc5522015-10-26 20:04:44 +0800396 device_data->imageMap.erase(image);
Jeremy Hayese0ed6a22016-04-08 09:53:54 -0600397 lock.unlock();
Chia-I Wuf7458c52015-10-26 21:10:41 +0800398 device_data->device_dispatch_table->DestroyImage(device, image, pAllocator);
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600399}
400
Chia-I Wu4935c762016-04-28 14:01:30 +0800401VKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
402 const VkAllocationCallbacks *pAllocator,
403 VkRenderPass *pRenderPass) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700404 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Dustin Graves080069b2016-04-05 13:48:15 -0600405 bool skipCall = false;
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600406
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700407 for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
408 if (!validate_VkImageLayoutKHR(pCreateInfo->pAttachments[i].initialLayout) ||
409 !validate_VkImageLayoutKHR(pCreateInfo->pAttachments[i].finalLayout)) {
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600410 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700411 ss << "vkCreateRenderPass parameter, VkImageLayout in pCreateInfo->pAttachments[" << i << "], is unrecognized";
412 // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700413 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
414 IMAGE_RENDERPASS_INVALID_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600415 }
416 }
417
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700418 for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
419 if (!validate_VkAttachmentLoadOp(pCreateInfo->pAttachments[i].loadOp)) {
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600420 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700421 ss << "vkCreateRenderPass parameter, VkAttachmentLoadOp in pCreateInfo->pAttachments[" << i << "], is unrecognized";
422 // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700423 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
424 IMAGE_RENDERPASS_INVALID_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600425 }
426 }
427
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700428 for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
429 if (!validate_VkAttachmentStoreOp(pCreateInfo->pAttachments[i].storeOp)) {
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600430 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700431 ss << "vkCreateRenderPass parameter, VkAttachmentStoreOp in pCreateInfo->pAttachments[" << i << "], is unrecognized";
432 // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700433 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
434 IMAGE_RENDERPASS_INVALID_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600435 }
436 }
437
Mark Lobodzinski2fd634c2015-07-29 09:21:22 -0600438 // Any depth buffers specified as attachments?
Dustin Graves080069b2016-04-05 13:48:15 -0600439 bool depthFormatPresent = false;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700440 for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
Tobin Ehlis6a4605b2016-05-19 10:10:09 -0600441 depthFormatPresent |= vk_format_is_depth_or_stencil(pCreateInfo->pAttachments[i].format);
Mark Lobodzinski2fd634c2015-07-29 09:21:22 -0600442 }
443
Dustin Graves080069b2016-04-05 13:48:15 -0600444 if (!depthFormatPresent) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700445 // No depth attachment is present, validate that subpasses set depthStencilAttachment to VK_ATTACHMENT_UNUSED;
Mark Lobodzinski2fd634c2015-07-29 09:21:22 -0600446 for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
Chia-I Wu1efb7e52015-10-26 17:32:47 +0800447 if (pCreateInfo->pSubpasses[i].pDepthStencilAttachment &&
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700448 pCreateInfo->pSubpasses[i].pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
Mark Lobodzinski2fd634c2015-07-29 09:21:22 -0600449 std::stringstream ss;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700450 ss << "vkCreateRenderPass has no depth/stencil attachment, yet subpass[" << i
451 << "] has VkSubpassDescription::depthStencilAttachment value that is not VK_ATTACHMENT_UNUSED";
452 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
453 IMAGE_RENDERPASS_INVALID_DS_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinski2fd634c2015-07-29 09:21:22 -0600454 }
455 }
456 }
Tobin Ehlisdea00952015-09-22 08:40:52 -0600457 if (skipCall)
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700458 return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski2fd634c2015-07-29 09:21:22 -0600459
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700460 VkResult result = my_data->device_dispatch_table->CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600461
462 return result;
463}
464
Chia-I Wu4935c762016-04-28 14:01:30 +0800465VKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo,
466 const VkAllocationCallbacks *pAllocator, VkImageView *pView) {
Dustin Graves080069b2016-04-05 13:48:15 -0600467 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700468 layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600469 auto imageEntry = getImageState(device_data, pCreateInfo->image);
470 if (imageEntry) {
471 if (pCreateInfo->subresourceRange.baseMipLevel >= imageEntry->mipLevels) {
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600472 std::stringstream ss;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700473 ss << "vkCreateImageView called with baseMipLevel " << pCreateInfo->subresourceRange.baseMipLevel << " for image "
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600474 << pCreateInfo->image << " that only has " << imageEntry->mipLevels << " mip levels.";
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700475 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
476 IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600477 }
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600478 if (pCreateInfo->subresourceRange.baseArrayLayer >= imageEntry->arraySize) {
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600479 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700480 ss << "vkCreateImageView called with baseArrayLayer " << pCreateInfo->subresourceRange.baseArrayLayer << " for image "
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600481 << pCreateInfo->image << " that only has " << imageEntry->arraySize << " array layers.";
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700482 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
483 IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600484 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800485 if (!pCreateInfo->subresourceRange.levelCount) {
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600486 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700487 ss << "vkCreateImageView called with 0 in pCreateInfo->subresourceRange.levelCount.";
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700488 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
489 IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600490 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800491 if (!pCreateInfo->subresourceRange.layerCount) {
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600492 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700493 ss << "vkCreateImageView called with 0 in pCreateInfo->subresourceRange.layerCount.";
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700494 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
495 IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600496 }
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600497
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600498 VkImageCreateFlags imageFlags = imageEntry->flags;
499 VkFormat imageFormat = imageEntry->format;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700500 VkFormat ivciFormat = pCreateInfo->format;
501 VkImageAspectFlags aspectMask = pCreateInfo->subresourceRange.aspectMask;
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600502
Mark Lobodzinskiadaac9d2016-01-08 11:07:56 -0700503 // Validate VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT state
Mark Lobodzinski1e638c62016-01-11 16:50:30 -0700504 if (imageFlags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700505 // Format MUST be compatible (in the same format compatibility class) as the format the image was created with
506 if (vk_format_get_compatibility_class(imageFormat) != vk_format_get_compatibility_class(ivciFormat)) {
Mark Lobodzinskiadaac9d2016-01-08 11:07:56 -0700507 std::stringstream ss;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700508 ss << "vkCreateImageView(): ImageView format " << string_VkFormat(ivciFormat)
509 << " is not in the same format compatibility class as image (" << (uint64_t)pCreateInfo->image << ") format "
510 << string_VkFormat(imageFormat) << ". Images created with the VK_IMAGE_CREATE_MUTABLE_FORMAT BIT "
511 << "can support ImageViews with differing formats but they must be in the same compatibility class.";
512 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
513 __LINE__, IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskiadaac9d2016-01-08 11:07:56 -0700514 }
515 } else {
516 // Format MUST be IDENTICAL to the format the image was created with
517 if (imageFormat != ivciFormat) {
518 std::stringstream ss;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700519 ss << "vkCreateImageView() format " << string_VkFormat(ivciFormat) << " differs from image "
520 << (uint64_t)pCreateInfo->image << " format " << string_VkFormat(imageFormat)
521 << ". Formats MUST be IDENTICAL unless VK_IMAGE_CREATE_MUTABLE_FORMAT BIT was set on image creation.";
522 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
523 __LINE__, IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskiadaac9d2016-01-08 11:07:56 -0700524 }
525 }
526
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700527 // Validate correct image aspect bits for desired formats and format consistency
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600528 if (vk_format_is_color(imageFormat)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700529 if ((aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600530 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700531 ss << "vkCreateImageView: Color image formats must have the VK_IMAGE_ASPECT_COLOR_BIT set";
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700532 skipCall |=
533 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
534 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600535 }
536 if ((aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != aspectMask) {
537 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700538 ss << "vkCreateImageView: Color image formats must have ONLY the VK_IMAGE_ASPECT_COLOR_BIT set";
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700539 skipCall |=
540 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
541 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600542 }
Dustin Graves080069b2016-04-05 13:48:15 -0600543 if (!vk_format_is_color(ivciFormat)) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600544 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700545 ss << "vkCreateImageView: The image view's format can differ from the parent image's format, but both must be "
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700546 << "color formats. ImageFormat is " << string_VkFormat(imageFormat) << " ImageViewFormat is "
547 << string_VkFormat(ivciFormat);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700548 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700549 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600550 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700551 // TODO: Uncompressed formats are compatible if they occupy they same number of bits per pixel.
552 // Compressed formats are compatible if the only difference between them is the numerical type of
553 // the uncompressed pixels (e.g. signed vs. unsigned, or sRGB vs. UNORM encoding).
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700554 } else if (vk_format_is_depth_and_stencil(imageFormat)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700555 if ((aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) == 0) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600556 std::stringstream ss;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700557 ss << "vkCreateImageView: Depth/stencil image formats must have at least one of VK_IMAGE_ASPECT_DEPTH_BIT and "
558 "VK_IMAGE_ASPECT_STENCIL_BIT set";
559 skipCall |=
560 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
561 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600562 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700563 if ((aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != aspectMask) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600564 std::stringstream ss;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700565 ss << "vkCreateImageView: Combination depth/stencil image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT and "
566 "VK_IMAGE_ASPECT_STENCIL_BIT set";
567 skipCall |=
568 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
569 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600570 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700571 } else if (vk_format_is_depth_only(imageFormat)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700572 if ((aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600573 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700574 ss << "vkCreateImageView: Depth-only image formats must have the VK_IMAGE_ASPECT_DEPTH_BIT set";
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700575 skipCall |=
576 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
577 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600578 }
579 if ((aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != aspectMask) {
580 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700581 ss << "vkCreateImageView: Depth-only image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT set";
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700582 skipCall |=
583 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
584 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600585 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700586 } else if (vk_format_is_stencil_only(imageFormat)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700587 if ((aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600588 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700589 ss << "vkCreateImageView: Stencil-only image formats must have the VK_IMAGE_ASPECT_STENCIL_BIT set";
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700590 skipCall |=
591 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
592 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600593 }
594 if ((aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != aspectMask) {
595 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700596 ss << "vkCreateImageView: Stencil-only image formats can have only the VK_IMAGE_ASPECT_STENCIL_BIT set";
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700597 skipCall |=
598 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
599 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600600 }
601 }
602 }
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600603
Mark Lobodzinskiadaac9d2016-01-08 11:07:56 -0700604 if (skipCall) {
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700605 return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinskiadaac9d2016-01-08 11:07:56 -0700606 }
Tobin Ehlisdea00952015-09-22 08:40:52 -0600607
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700608 VkResult result = device_data->device_dispatch_table->CreateImageView(device, pCreateInfo, pAllocator, pView);
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600609 return result;
610}
611
Chia-I Wu4935c762016-04-28 14:01:30 +0800612VKAPI_ATTR void VKAPI_CALL CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image,
613 VkImageLayout imageLayout, const VkClearColorValue *pColor,
614 uint32_t rangeCount, const VkImageSubresourceRange *pRanges) {
Dustin Graves080069b2016-04-05 13:48:15 -0600615 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700616 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Jeremy Hayesa4dc0ac2016-03-01 16:51:02 -0700617
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700618 if (imageLayout != VK_IMAGE_LAYOUT_GENERAL && imageLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
Jeremy Hayesa4dc0ac2016-03-01 16:51:02 -0700619 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
620 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_LAYOUT, "IMAGE",
621 "vkCmdClearColorImage parameter, imageLayout, must be VK_IMAGE_LAYOUT_GENERAL or "
622 "VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL");
623 }
624
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600625 // For each range, image aspect must be color only
626 for (uint32_t i = 0; i < rangeCount; i++) {
627 if (pRanges[i].aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700628 char const str[] =
629 "vkCmdClearColorImage aspectMasks for all subresource ranges must be set to VK_IMAGE_ASPECT_COLOR_BIT";
630 skipCall |=
631 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
632 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600633 }
634 }
635
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600636 auto image_state = getImageState(device_data, image);
637 if (image_state) {
638 if (vk_format_is_depth_or_stencil(image_state->format)) {
639 char const str[] = "vkCmdClearColorImage called with depth/stencil image.";
640 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
641 reinterpret_cast<uint64_t &>(image), __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", str);
642 } else if (vk_format_is_compressed(image_state->format)) {
643 char const str[] = "vkCmdClearColorImage called with compressed image.";
644 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
645 reinterpret_cast<uint64_t &>(image), __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", str);
646 }
Tony Barbour26434b92016-06-02 09:43:50 -0600647
648 if (!(image_state->usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
649 char const str[] = "vkCmdClearColorImage called with image created without VK_IMAGE_USAGE_TRANSFER_DST_BIT.";
650 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
651 reinterpret_cast<uint64_t &>(image), __LINE__, IMAGE_INVALID_USAGE, "IMAGE", str);
652 }
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600653 }
654
Dustin Graves080069b2016-04-05 13:48:15 -0600655 if (!skipCall) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700656 device_data->device_dispatch_table->CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600657 }
658}
659
Chia-I Wu4935c762016-04-28 14:01:30 +0800660VKAPI_ATTR void VKAPI_CALL
661CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
662 const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount,
663 const VkImageSubresourceRange *pRanges) {
Dustin Graves080069b2016-04-05 13:48:15 -0600664 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700665 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600666 // For each range, Image aspect must be depth or stencil or both
667 for (uint32_t i = 0; i < rangeCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700668 if (((pRanges[i].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
669 ((pRanges[i].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700670 char const str[] = "vkCmdClearDepthStencilImage aspectMasks for all subresource ranges must be "
671 "set to VK_IMAGE_ASPECT_DEPTH_BIT and/or VK_IMAGE_ASPECT_STENCIL_BIT";
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700672 skipCall |=
673 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
674 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600675 }
676 }
677
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600678 auto image_state = getImageState(device_data, image);
679 if (image_state && !vk_format_is_depth_or_stencil(image_state->format)) {
680 char const str[] = "vkCmdClearDepthStencilImage called without a depth/stencil image.";
681 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
682 reinterpret_cast<uint64_t &>(image), __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", str);
683 }
684
Dustin Graves080069b2016-04-05 13:48:15 -0600685 if (!skipCall) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700686 device_data->device_dispatch_table->CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount,
687 pRanges);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600688 }
689}
690
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600691// Returns true if [x, xoffset] and [y, yoffset] overlap
692static bool ranges_intersect(int32_t start, uint32_t start_offset, int32_t end, uint32_t end_offset) {
693 bool result = false;
694 uint32_t intersection_min = std::max(static_cast<uint32_t>(start), static_cast<uint32_t>(end));
695 uint32_t intersection_max = std::min(static_cast<uint32_t>(start) + start_offset, static_cast<uint32_t>(end) + end_offset);
696
697 if (intersection_max > intersection_min) {
698 result = true;
699 }
700 return result;
701}
702
703// Returns true if two VkImageCopy structures overlap
704static bool region_intersects(const VkImageCopy *src, const VkImageCopy *dst, VkImageType type) {
705 bool result = true;
706 if ((src->srcSubresource.mipLevel == dst->dstSubresource.mipLevel) &&
707 (ranges_intersect(src->srcSubresource.baseArrayLayer, src->srcSubresource.layerCount, dst->dstSubresource.baseArrayLayer,
708 dst->dstSubresource.layerCount))) {
709
710 switch (type) {
711 case VK_IMAGE_TYPE_3D:
712 result &= ranges_intersect(src->srcOffset.z, src->extent.depth, dst->dstOffset.z, dst->extent.depth);
713 // Intentionally fall through to 2D case
714 case VK_IMAGE_TYPE_2D:
715 result &= ranges_intersect(src->srcOffset.y, src->extent.height, dst->dstOffset.y, dst->extent.height);
716 // Intentionally fall through to 1D case
717 case VK_IMAGE_TYPE_1D:
718 result &= ranges_intersect(src->srcOffset.x, src->extent.width, dst->dstOffset.x, dst->extent.width);
719 break;
720 default:
721 // Unrecognized or new IMAGE_TYPE enums will be caught in parameter_validation
722 assert(false);
723 }
724 }
725 return result;
726}
727
728// Returns true if offset and extent exceed image extents
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600729static bool exceeds_bounds(const VkOffset3D *offset, const VkExtent3D *extent, const IMAGE_STATE *image) {
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600730 bool result = false;
731 // Extents/depths cannot be negative but checks left in for clarity
732
733 return result;
734}
735
Dustin Graves080069b2016-04-05 13:48:15 -0600736bool cmd_copy_image_valid_usage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImage dstImage, uint32_t regionCount,
737 const VkImageCopy *pRegions) {
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600738
Dustin Graves080069b2016-04-05 13:48:15 -0600739 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700740 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600741 auto srcImageEntry = getImageState(device_data, srcImage);
742 auto dstImageEntry = getImageState(device_data, dstImage);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600743
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600744 // TODO: This does not cover swapchain-created images. This should fall out when this layer is moved
745 // into the core_validation layer
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600746 if (srcImageEntry && dstImageEntry) {
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600747
748 for (uint32_t i = 0; i < regionCount; i++) {
749
750 if (pRegions[i].srcSubresource.layerCount == 0) {
751 std::stringstream ss;
752 ss << "vkCmdCopyImage: number of layers in pRegions[" << i << "] srcSubresource is zero";
753 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
754 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer),
755 __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
756 }
757
758 if (pRegions[i].dstSubresource.layerCount == 0) {
759 std::stringstream ss;
760 ss << "vkCmdCopyImage: number of layers in pRegions[" << i << "] dstSubresource is zero";
761 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
762 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer),
763 __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
764 }
765
766 // For each region the layerCount member of srcSubresource and dstSubresource must match
767 if (pRegions[i].srcSubresource.layerCount != pRegions[i].dstSubresource.layerCount) {
768 std::stringstream ss;
769 ss << "vkCmdCopyImage: number of layers in source and destination subresources for pRegions[" << i
770 << "] do not match";
771 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
772 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer),
773 __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
774 }
775
776 // For each region, the aspectMask member of srcSubresource and dstSubresource must match
777 if (pRegions[i].srcSubresource.aspectMask != pRegions[i].dstSubresource.aspectMask) {
778 char const str[] = "vkCmdCopyImage: Src and dest aspectMasks for each region must match";
779 skipCall |=
780 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
781 reinterpret_cast<uint64_t &>(commandBuffer), __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
782 }
783
784 // AspectMask must not contain VK_IMAGE_ASPECT_METADATA_BIT
785 if ((pRegions[i].srcSubresource.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT) ||
786 (pRegions[i].dstSubresource.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT)) {
787 std::stringstream ss;
788 ss << "vkCmdCopyImage: pRegions[" << i << "] may not specify aspectMask containing VK_IMAGE_ASPECT_METADATA_BIT";
789 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
790 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer),
791 __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
792 }
793
794 // For each region, if aspectMask contains VK_IMAGE_ASPECT_COLOR_BIT, it must not contain either of
795 // VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT
796 if ((pRegions[i].srcSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) &&
797 (pRegions[i].srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) {
798 char const str[] = "vkCmdCopyImage aspectMask cannot specify both COLOR and DEPTH/STENCIL aspects";
799 skipCall |=
800 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
801 reinterpret_cast<uint64_t &>(commandBuffer), __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
802 }
803
804 // If either of the calling command's srcImage or dstImage parameters are of VkImageType VK_IMAGE_TYPE_3D,
805 // the baseArrayLayer and layerCount members of both srcSubresource and dstSubresource must be 0 and 1, respectively
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600806 if (((srcImageEntry->imageType == VK_IMAGE_TYPE_3D) || (dstImageEntry->imageType == VK_IMAGE_TYPE_3D)) &&
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600807 ((pRegions[i].srcSubresource.baseArrayLayer != 0) || (pRegions[i].srcSubresource.layerCount != 1) ||
808 (pRegions[i].dstSubresource.baseArrayLayer != 0) || (pRegions[i].dstSubresource.layerCount != 1))) {
809 std::stringstream ss;
810 ss << "vkCmdCopyImage: src or dstImage type was IMAGE_TYPE_3D, but in subRegion[" << i
811 << "] baseArrayLayer was not zero or layerCount was not 1.";
812 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
813 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer),
814 __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
815 }
816
817 // MipLevel must be less than the mipLevels specified in VkImageCreateInfo when the image was created
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600818 if (pRegions[i].srcSubresource.mipLevel >= srcImageEntry->mipLevels) {
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600819 std::stringstream ss;
820 ss << "vkCmdCopyImage: pRegions[" << i
821 << "] specifies a src mipLevel greater than the number specified when the srcImage was created.";
822 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
823 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer),
824 __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
825 }
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600826 if (pRegions[i].dstSubresource.mipLevel >= dstImageEntry->mipLevels) {
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600827 std::stringstream ss;
828 ss << "vkCmdCopyImage: pRegions[" << i
829 << "] specifies a dst mipLevel greater than the number specified when the dstImage was created.";
830 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
831 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer),
832 __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
833 }
834
835 // (baseArrayLayer + layerCount) must be less than or equal to the arrayLayers specified in VkImageCreateInfo when the
836 // image was created
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600837 if ((pRegions[i].srcSubresource.baseArrayLayer + pRegions[i].srcSubresource.layerCount) > srcImageEntry->arraySize) {
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600838 std::stringstream ss;
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600839 ss << "vkCmdCopyImage: srcImage arrayLayers was " << srcImageEntry->arraySize << " but subRegion[" << i
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600840 << "] baseArrayLayer + layerCount is "
841 << (pRegions[i].srcSubresource.baseArrayLayer + pRegions[i].srcSubresource.layerCount);
842 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
843 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer),
844 __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
845 }
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600846 if ((pRegions[i].dstSubresource.baseArrayLayer + pRegions[i].dstSubresource.layerCount) > dstImageEntry->arraySize) {
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600847 std::stringstream ss;
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600848 ss << "vkCmdCopyImage: dstImage arrayLayers was " << dstImageEntry->arraySize << " but subRegion[" << i
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600849 << "] baseArrayLayer + layerCount is "
850 << (pRegions[i].dstSubresource.baseArrayLayer + pRegions[i].dstSubresource.layerCount);
851 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
852 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer),
853 __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
854 }
855
856 // The source region specified by a given element of pRegions must be a region that is contained within srcImage
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600857 if (exceeds_bounds(&pRegions[i].srcOffset, &pRegions[i].extent, srcImageEntry)) {
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600858 std::stringstream ss;
859 ss << "vkCmdCopyImage: srcSubResource in pRegions[" << i << "] exceeds extents srcImage was created with";
860 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
861 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer),
862 __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
863 }
864
865 // The destination region specified by a given element of pRegions must be a region that is contained within dstImage
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600866 if (exceeds_bounds(&pRegions[i].dstOffset, &pRegions[i].extent, dstImageEntry)) {
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600867 std::stringstream ss;
868 ss << "vkCmdCopyImage: dstSubResource in pRegions[" << i << "] exceeds extents dstImage was created with";
869 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
870 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer),
871 __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
872 }
873
874 // The union of all source regions, and the union of all destination regions, specified by the elements of pRegions,
875 // must not overlap in memory
876 if (srcImage == dstImage) {
877 for (uint32_t j = 0; j < regionCount; j++) {
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600878 if (region_intersects(&pRegions[i], &pRegions[j], srcImageEntry->imageType)) {
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600879 std::stringstream ss;
880 ss << "vkCmdCopyImage: pRegions[" << i << "] src overlaps with pRegions[" << j << "].";
881 skipCall |=
882 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
883 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer),
884 __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
885 }
886 }
887 }
Mike Stroyana3082432015-09-25 13:39:21 -0600888 }
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600889
890 // The formats of srcImage and dstImage must be compatible. Formats are considered compatible if their texel size in bytes
891 // is the same between both formats. For example, VK_FORMAT_R8G8B8A8_UNORM is compatible with VK_FORMAT_R32_UINT because
892 // because both texels are 4 bytes in size. Depth/stencil formats must match exactly.
Tobin Ehlis6a4605b2016-05-19 10:10:09 -0600893 if (vk_format_is_depth_or_stencil(srcImageEntry->format) || vk_format_is_depth_or_stencil(dstImageEntry->format)) {
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600894 if (srcImageEntry->format != dstImageEntry->format) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700895 char const str[] = "vkCmdCopyImage called with unmatched source and dest image depth/stencil formats.";
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700896 skipCall |=
897 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600898 reinterpret_cast<uint64_t &>(commandBuffer), __LINE__, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
Mike Stroyana3082432015-09-25 13:39:21 -0600899 }
900 } else {
Tobin Ehlisf4d352b2016-05-19 09:59:30 -0600901 size_t srcSize = vk_format_get_size(srcImageEntry->format);
902 size_t destSize = vk_format_get_size(dstImageEntry->format);
Mike Stroyana3082432015-09-25 13:39:21 -0600903 if (srcSize != destSize) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700904 char const str[] = "vkCmdCopyImage called with unmatched source and dest image format sizes.";
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700905 skipCall |=
906 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600907 reinterpret_cast<uint64_t &>(commandBuffer), __LINE__, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
Mike Stroyana3082432015-09-25 13:39:21 -0600908 }
909 }
910 }
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600911 return skipCall;
912}
913
Chia-I Wu4935c762016-04-28 14:01:30 +0800914VKAPI_ATTR void VKAPI_CALL CmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage,
915 VkImageLayout srcImageLayout, VkImage dstImage,
916 VkImageLayout dstImageLayout, uint32_t regionCount,
917 const VkImageCopy *pRegions) {
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600918
Dustin Graves080069b2016-04-05 13:48:15 -0600919 bool skipCall = false;
Mark Lobodzinskib2ad7022016-03-29 17:10:14 -0600920 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
921
922 skipCall = cmd_copy_image_valid_usage(commandBuffer, srcImage, dstImage, regionCount, pRegions);
Mike Stroyana3082432015-09-25 13:39:21 -0600923
Dustin Graves080069b2016-04-05 13:48:15 -0600924 if (!skipCall) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700925 device_data->device_dispatch_table->CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout,
926 regionCount, pRegions);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600927 }
928}
929
Chia-I Wu4935c762016-04-28 14:01:30 +0800930VKAPI_ATTR void VKAPI_CALL CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
931 const VkClearAttachment *pAttachments, uint32_t rectCount,
932 const VkClearRect *pRects) {
Dustin Graves080069b2016-04-05 13:48:15 -0600933 bool skipCall = false;
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -0600934 VkImageAspectFlags aspectMask;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700935 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -0600936 for (uint32_t i = 0; i < attachmentCount; i++) {
937 aspectMask = pAttachments[i].aspectMask;
938 if (aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
939 if (aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700940 // VK_IMAGE_ASPECT_COLOR_BIT is not the only bit set for this attachment
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700941 char const str[] =
942 "vkCmdClearAttachments aspectMask [%d] must set only VK_IMAGE_ASPECT_COLOR_BIT of a color attachment.";
943 skipCall |=
944 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
945 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str, i);
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -0600946 }
947 } else {
948 // Image aspect must be depth or stencil or both
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700949 if (((aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
950 ((aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT)) {
951 char const str[] = "vkCmdClearAttachments aspectMask [%d] must be set to VK_IMAGE_ASPECT_DEPTH_BIT and/or "
952 "VK_IMAGE_ASPECT_STENCIL_BIT";
953 skipCall |=
954 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
955 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str, i);
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -0600956 }
957 }
958 }
959
Dustin Graves080069b2016-04-05 13:48:15 -0600960 if (!skipCall) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700961 device_data->device_dispatch_table->CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -0600962 }
963}
964
Chia-I Wu4935c762016-04-28 14:01:30 +0800965VKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage,
966 VkImageLayout srcImageLayout, VkBuffer dstBuffer,
967 uint32_t regionCount, const VkBufferImageCopy *pRegions) {
Dustin Graves080069b2016-04-05 13:48:15 -0600968 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700969 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
970 // For each region, the number of layers in the image subresource should not be zero
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600971 // Image aspect must be ONE OF color, depth, stencil
972 for (uint32_t i = 0; i < regionCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700973 if (pRegions[i].imageSubresource.layerCount == 0) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700974 char const str[] = "vkCmdCopyImageToBuffer: number of layers in image subresource is zero";
975 // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700976 skipCall |=
977 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
978 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -0600979 }
980
Chia-I Wuab83a0e2015-10-27 19:00:15 +0800981 VkImageAspectFlags aspectMask = pRegions[i].imageSubresource.aspectMask;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700982 if ((aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) && (aspectMask != VK_IMAGE_ASPECT_DEPTH_BIT) &&
Chia-I Wuab83a0e2015-10-27 19:00:15 +0800983 (aspectMask != VK_IMAGE_ASPECT_STENCIL_BIT)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700984 char const str[] = "vkCmdCopyImageToBuffer: aspectMasks for each region must specify only COLOR or DEPTH or STENCIL";
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700985 skipCall |=
986 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
987 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600988 }
989 }
990
Dustin Graves080069b2016-04-05 13:48:15 -0600991 if (!skipCall) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700992 device_data->device_dispatch_table->CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount,
993 pRegions);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600994 }
995}
996
Chia-I Wu4935c762016-04-28 14:01:30 +0800997VKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer,
998 VkImage dstImage, VkImageLayout dstImageLayout,
999 uint32_t regionCount, const VkBufferImageCopy *pRegions) {
Dustin Graves080069b2016-04-05 13:48:15 -06001000 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001001 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
1002 // For each region, the number of layers in the image subresource should not be zero
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001003 // Image aspect must be ONE OF color, depth, stencil
1004 for (uint32_t i = 0; i < regionCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001005 if (pRegions[i].imageSubresource.layerCount == 0) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001006 char const str[] = "vkCmdCopyBufferToImage: number of layers in image subresource is zero";
1007 // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001008 skipCall |=
1009 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1010 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -06001011 }
1012
Chia-I Wuab83a0e2015-10-27 19:00:15 +08001013 VkImageAspectFlags aspectMask = pRegions[i].imageSubresource.aspectMask;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001014 if ((aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) && (aspectMask != VK_IMAGE_ASPECT_DEPTH_BIT) &&
Chia-I Wuab83a0e2015-10-27 19:00:15 +08001015 (aspectMask != VK_IMAGE_ASPECT_STENCIL_BIT)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001016 char const str[] = "vkCmdCopyBufferToImage: aspectMasks for each region must specify only COLOR or DEPTH or STENCIL";
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001017 skipCall |=
1018 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1019 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001020 }
1021 }
1022
Dustin Graves080069b2016-04-05 13:48:15 -06001023 if (!skipCall) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001024 device_data->device_dispatch_table->CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount,
1025 pRegions);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001026 }
1027}
1028
Chia-I Wu4935c762016-04-28 14:01:30 +08001029VKAPI_ATTR void VKAPI_CALL
1030CmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
1031 VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit *pRegions, VkFilter filter) {
Dustin Graves080069b2016-04-05 13:48:15 -06001032 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001033 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001034
Tobin Ehlisf4d352b2016-05-19 09:59:30 -06001035 auto srcImageEntry = getImageState(device_data, srcImage);
1036 auto dstImageEntry = getImageState(device_data, dstImage);
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001037
Tobin Ehlisf4d352b2016-05-19 09:59:30 -06001038 if (srcImageEntry && dstImageEntry) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001039
Tobin Ehlisf4d352b2016-05-19 09:59:30 -06001040 VkFormat srcFormat = srcImageEntry->format;
1041 VkFormat dstFormat = dstImageEntry->format;
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001042
1043 // Validate consistency for signed and unsigned formats
1044 if ((vk_format_is_sint(srcFormat) && !vk_format_is_sint(dstFormat)) ||
1045 (vk_format_is_uint(srcFormat) && !vk_format_is_uint(dstFormat))) {
1046 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001047 ss << "vkCmdBlitImage: If one of srcImage and dstImage images has signed/unsigned integer format, "
1048 << "the other one must also have signed/unsigned integer format. "
1049 << "Source format is " << string_VkFormat(srcFormat) << " Destination format is " << string_VkFormat(dstFormat);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001050 skipCall |=
1051 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1052 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001053 }
1054
1055 // Validate aspect bits and formats for depth/stencil images
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001056 if (vk_format_is_depth_or_stencil(srcFormat) || vk_format_is_depth_or_stencil(dstFormat)) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001057 if (srcFormat != dstFormat) {
1058 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001059 ss << "vkCmdBlitImage: If one of srcImage and dstImage images has a format of depth, stencil or depth "
1060 << "stencil, the other one must have exactly the same format. "
1061 << "Source format is " << string_VkFormat(srcFormat) << " Destination format is " << string_VkFormat(dstFormat);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001062 skipCall |=
1063 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1064 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001065 }
1066
1067 for (uint32_t i = 0; i < regionCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001068 if (pRegions[i].srcSubresource.layerCount == 0) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001069 char const str[] = "vkCmdBlitImage: number of layers in source subresource is zero";
1070 // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001071 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1072 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
1073 IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -06001074 }
1075
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001076 if (pRegions[i].dstSubresource.layerCount == 0) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001077 char const str[] = "vkCmdBlitImage: number of layers in destination subresource is zero";
1078 // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001079 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1080 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
1081 IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -06001082 }
1083
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001084 if (pRegions[i].srcSubresource.layerCount != pRegions[i].dstSubresource.layerCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001085 char const str[] = "vkCmdBlitImage: number of layers in source and destination subresources must match";
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001086 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1087 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
1088 IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -06001089 }
1090
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001091 VkImageAspectFlags srcAspect = pRegions[i].srcSubresource.aspectMask;
1092 VkImageAspectFlags dstAspect = pRegions[i].dstSubresource.aspectMask;
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001093
1094 if (srcAspect != dstAspect) {
1095 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001096 ss << "vkCmdBlitImage: Image aspects of depth/stencil images should match";
1097 // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001098 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1099 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
1100 IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001101 }
1102 if (vk_format_is_depth_and_stencil(srcFormat)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001103 if ((srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) && (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT)) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001104 std::stringstream ss;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001105 ss << "vkCmdBlitImage: Combination depth/stencil image formats must have only one of "
1106 "VK_IMAGE_ASPECT_DEPTH_BIT "
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001107 << "and VK_IMAGE_ASPECT_STENCIL_BIT set in srcImage and dstImage";
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001108 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1109 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
1110 IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001111 }
1112 } else if (vk_format_is_stencil_only(srcFormat)) {
1113 if (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT) {
1114 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001115 ss << "vkCmdBlitImage: Stencil-only image formats must have only the VK_IMAGE_ASPECT_STENCIL_BIT "
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001116 << "set in both the srcImage and dstImage";
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001117 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1118 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
1119 IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001120 }
1121 } else if (vk_format_is_depth_only(srcFormat)) {
1122 if (srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) {
1123 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001124 ss << "vkCmdBlitImage: Depth-only image formats must have only the VK_IMAGE_ASPECT_DEPTH "
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001125 << "set in both the srcImage and dstImage";
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001126 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1127 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
1128 IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001129 }
1130 }
1131 }
1132 }
1133
1134 // Validate filter
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001135 if (vk_format_is_depth_or_stencil(srcFormat) || vk_format_is_int(srcFormat)) {
Chia-I Wub99df442015-10-26 16:49:32 +08001136 if (filter != VK_FILTER_NEAREST) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001137 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001138 ss << "vkCmdBlitImage: If the format of srcImage is a depth, stencil, depth stencil or integer-based format "
Chia-I Wub99df442015-10-26 16:49:32 +08001139 << "then filter must be VK_FILTER_NEAREST.";
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001140 skipCall |=
1141 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1142 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_FILTER, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001143 }
1144 }
1145 }
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001146
Tony Barbourf8309102016-05-05 10:50:21 -06001147 if (!skipCall) {
1148 device_data->device_dispatch_table->CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount,
1149 pRegions, filter);
1150 }
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001151}
1152
Chia-I Wu4935c762016-04-28 14:01:30 +08001153VKAPI_ATTR void VKAPI_CALL
1154CmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
1155 VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
1156 uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
1157 uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
Dustin Graves080069b2016-04-05 13:48:15 -06001158 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001159 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Jeremy Hayes01b38892015-11-17 18:19:55 -07001160
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001161 for (uint32_t i = 0; i < imageMemoryBarrierCount; ++i) {
1162 VkImageMemoryBarrier const *const barrier = (VkImageMemoryBarrier const *const) & pImageMemoryBarriers[i];
1163 if (barrier->sType == VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER) {
1164 if (barrier->subresourceRange.layerCount == 0) {
Jeremy Hayes01b38892015-11-17 18:19:55 -07001165 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001166 ss << "vkCmdPipelineBarrier called with 0 in ppMemoryBarriers[" << i << "]->subresourceRange.layerCount.";
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001167 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
1168 __LINE__, IMAGE_INVALID_IMAGE_RESOURCE, "IMAGE", "%s", ss.str().c_str());
Jeremy Hayes01b38892015-11-17 18:19:55 -07001169 }
1170 }
1171 }
1172
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001173 if (skipCall) {
Jeremy Hayes01b38892015-11-17 18:19:55 -07001174 return;
1175 }
1176
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001177 device_data->device_dispatch_table->CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001178 memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
1179 pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
Jeremy Hayes01b38892015-11-17 18:19:55 -07001180}
1181
Chia-I Wu4935c762016-04-28 14:01:30 +08001182VKAPI_ATTR void VKAPI_CALL
1183CmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
1184 VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve *pRegions) {
Dustin Graves080069b2016-04-05 13:48:15 -06001185 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001186 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Tobin Ehlisf4d352b2016-05-19 09:59:30 -06001187 auto srcImageEntry = getImageState(device_data, srcImage);
1188 auto dstImageEntry = getImageState(device_data, dstImage);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001189
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001190 // For each region, the number of layers in the image subresource should not be zero
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001191 // For each region, src and dest image aspect must be color only
1192 for (uint32_t i = 0; i < regionCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001193 if (pRegions[i].srcSubresource.layerCount == 0) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001194 char const str[] = "vkCmdResolveImage: number of layers in source subresource is zero";
1195 // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid/error
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001196 skipCall |=
1197 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1198 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -06001199 }
1200
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001201 if (pRegions[i].dstSubresource.layerCount == 0) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001202 char const str[] = "vkCmdResolveImage: number of layers in destination subresource is zero";
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001203
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001204 // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid/error
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001205 skipCall |=
1206 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1207 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -06001208 }
1209
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001210 if ((pRegions[i].srcSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) ||
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001211 (pRegions[i].dstSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT)) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001212 char const str[] =
1213 "vkCmdResolveImage: src and dest aspectMasks for each region must specify only VK_IMAGE_ASPECT_COLOR_BIT";
1214 skipCall |=
1215 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1216 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001217 }
1218 }
1219
Tobin Ehlisf4d352b2016-05-19 09:59:30 -06001220 if (srcImageEntry && dstImageEntry) {
1221 if (srcImageEntry->format != dstImageEntry->format) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001222 char const str[] = "vkCmdResolveImage called with unmatched source and dest formats.";
1223 skipCall |=
1224 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1225 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
Mike Stroyana3082432015-09-25 13:39:21 -06001226 }
Tobin Ehlisf4d352b2016-05-19 09:59:30 -06001227 if (srcImageEntry->imageType != dstImageEntry->imageType) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001228 char const str[] = "vkCmdResolveImage called with unmatched source and dest image types.";
1229 skipCall |=
1230 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1231 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_TYPE, "IMAGE", str);
Mike Stroyana3082432015-09-25 13:39:21 -06001232 }
Tobin Ehlisf4d352b2016-05-19 09:59:30 -06001233 if (srcImageEntry->samples == VK_SAMPLE_COUNT_1_BIT) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001234 char const str[] = "vkCmdResolveImage called with source sample count less than 2.";
1235 skipCall |=
1236 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1237 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_RESOLVE_SAMPLES, "IMAGE", str);
Mike Stroyana3082432015-09-25 13:39:21 -06001238 }
Tobin Ehlisf4d352b2016-05-19 09:59:30 -06001239 if (dstImageEntry->samples != VK_SAMPLE_COUNT_1_BIT) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001240 char const str[] = "vkCmdResolveImage called with dest sample count greater than 1.";
1241 skipCall |=
1242 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1243 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_RESOLVE_SAMPLES, "IMAGE", str);
Mike Stroyana3082432015-09-25 13:39:21 -06001244 }
1245 }
1246
Dustin Graves080069b2016-04-05 13:48:15 -06001247 if (!skipCall) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001248 device_data->device_dispatch_table->CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout,
1249 regionCount, pRegions);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001250 }
1251}
1252
Chia-I Wu4935c762016-04-28 14:01:30 +08001253VKAPI_ATTR void VKAPI_CALL
1254GetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource *pSubresource, VkSubresourceLayout *pLayout) {
Dustin Graves080069b2016-04-05 13:48:15 -06001255 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001256 layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001257 VkFormat format;
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001258
Tobin Ehlisf4d352b2016-05-19 09:59:30 -06001259 auto imageEntry = getImageState(device_data, image);
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001260
1261 // Validate that image aspects match formats
Tobin Ehlisf4d352b2016-05-19 09:59:30 -06001262 if (imageEntry) {
1263 format = imageEntry->format;
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001264 if (vk_format_is_color(format)) {
Chia-I Wu52b07e72015-10-27 19:55:05 +08001265 if (pSubresource->aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001266 std::stringstream ss;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001267 ss << "vkGetImageSubresourceLayout: For color formats, the aspectMask field of VkImageSubresource must be "
1268 "VK_IMAGE_ASPECT_COLOR.";
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001269 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001270 (uint64_t)image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001271 }
1272 } else if (vk_format_is_depth_or_stencil(format)) {
Chia-I Wu52b07e72015-10-27 19:55:05 +08001273 if ((pSubresource->aspectMask != VK_IMAGE_ASPECT_DEPTH_BIT) &&
1274 (pSubresource->aspectMask != VK_IMAGE_ASPECT_STENCIL_BIT)) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001275 std::stringstream ss;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001276 ss << "vkGetImageSubresourceLayout: For depth/stencil formats, the aspectMask selects either the depth or stencil "
1277 "image aspectMask.";
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001278 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001279 (uint64_t)image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001280 }
1281 }
1282 }
1283
Dustin Graves080069b2016-04-05 13:48:15 -06001284 if (!skipCall) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001285 device_data->device_dispatch_table->GetImageSubresourceLayout(device, image, pSubresource, pLayout);
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001286 }
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001287}
1288
Chia-I Wu4935c762016-04-28 14:01:30 +08001289VKAPI_ATTR void VKAPI_CALL
1290GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001291 layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1292 phy_dev_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice, pProperties);
Mark Lobodzinskid5a23822015-11-12 15:14:35 -07001293}
1294
Chia-I Wub02600c2016-05-20 07:11:22 +08001295VKAPI_ATTR VkResult VKAPI_CALL
1296EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
1297 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
1298}
1299
1300VKAPI_ATTR VkResult VKAPI_CALL
1301EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
1302 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
1303}
1304
1305VKAPI_ATTR VkResult VKAPI_CALL
1306EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
1307 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
1308 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
1309
1310 return VK_ERROR_LAYER_NOT_PRESENT;
1311}
1312
Chia-I Wu4935c762016-04-28 14:01:30 +08001313VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1314 const char *pLayerName, uint32_t *pCount,
1315 VkExtensionProperties *pProperties) {
Chia-I Wueec9a312016-04-28 11:21:49 +08001316 // Image does not have any physical device extensions
Chia-I Wu3f326222016-04-28 14:21:13 +08001317 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
Chia-I Wueec9a312016-04-28 11:21:49 +08001318 return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Chia-I Wu3f326222016-04-28 14:21:13 +08001319
1320 assert(physicalDevice);
1321
1322 dispatch_key key = get_dispatch_key(physicalDevice);
1323 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
1324 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
1325 return pTable->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Chia-I Wueec9a312016-04-28 11:21:49 +08001326}
1327
Chia-I Wu64df8ed2016-04-28 14:38:57 +08001328static PFN_vkVoidFunction
Chia-I Wu428eba02016-04-28 14:38:57 +08001329intercept_core_instance_command(const char *name);
1330static PFN_vkVoidFunction
Chia-I Wu64df8ed2016-04-28 14:38:57 +08001331intercept_core_device_command(const char *name);
Tobin Ehlisb74f6ab2015-10-29 14:19:18 -06001332
Chia-I Wu64df8ed2016-04-28 14:38:57 +08001333VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
1334 PFN_vkVoidFunction proc = intercept_core_device_command(funcName);
1335 if (proc)
1336 return proc;
1337
1338 assert(device);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001339
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001340 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001341
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001342 VkLayerDispatchTable *pTable = my_data->device_dispatch_table;
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001343 {
Tobin Ehlisb74f6ab2015-10-29 14:19:18 -06001344 if (pTable->GetDeviceProcAddr == NULL)
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001345 return NULL;
Tobin Ehlisb74f6ab2015-10-29 14:19:18 -06001346 return pTable->GetDeviceProcAddr(device, funcName);
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001347 }
1348}
1349
Chia-I Wu4935c762016-04-28 14:01:30 +08001350VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wu428eba02016-04-28 14:38:57 +08001351 PFN_vkVoidFunction proc = intercept_core_instance_command(funcName);
Chia-I Wuf89922c2016-04-28 15:16:59 +08001352 if (!proc)
1353 proc = intercept_core_device_command(funcName);
Chia-I Wu428eba02016-04-28 14:38:57 +08001354 if (proc)
1355 return proc;
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001356
Chia-I Wuf89922c2016-04-28 15:16:59 +08001357 assert(instance);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001358 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001359
Chia-I Wuf89922c2016-04-28 15:16:59 +08001360 proc = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
1361 if (proc)
1362 return proc;
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001363
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001364 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001365 if (pTable->GetInstanceProcAddr == NULL)
1366 return NULL;
1367 return pTable->GetInstanceProcAddr(instance, funcName);
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001368}
Chia-I Wueec9a312016-04-28 11:21:49 +08001369
Chia-I Wu64df8ed2016-04-28 14:38:57 +08001370static PFN_vkVoidFunction
Chia-I Wu428eba02016-04-28 14:38:57 +08001371intercept_core_instance_command(const char *name) {
1372 static const struct {
1373 const char *name;
1374 PFN_vkVoidFunction proc;
1375 } core_instance_commands[] = {
1376 { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
1377 { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
1378 { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
1379 { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
Chia-I Wub02600c2016-05-20 07:11:22 +08001380 { "vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties) },
1381 { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
1382 { "vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties) },
Chia-I Wu428eba02016-04-28 14:38:57 +08001383 { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
1384 { "vkGetPhysicalDeviceProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceProperties) },
1385 };
1386
1387 for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
1388 if (!strcmp(core_instance_commands[i].name, name))
1389 return core_instance_commands[i].proc;
1390 }
1391
1392 return nullptr;
1393}
1394
1395static PFN_vkVoidFunction
Chia-I Wu64df8ed2016-04-28 14:38:57 +08001396intercept_core_device_command(const char *name) {
1397 static const struct {
1398 const char *name;
1399 PFN_vkVoidFunction proc;
1400 } core_device_commands[] = {
1401 { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
1402 { "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice) },
1403 { "vkCreateImage", reinterpret_cast<PFN_vkVoidFunction>(CreateImage) },
1404 { "vkDestroyImage", reinterpret_cast<PFN_vkVoidFunction>(DestroyImage) },
1405 { "vkCreateImageView", reinterpret_cast<PFN_vkVoidFunction>(CreateImageView) },
1406 { "vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CreateRenderPass) },
1407 { "vkCmdClearColorImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearColorImage) },
1408 { "vkCmdClearDepthStencilImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearDepthStencilImage) },
1409 { "vkCmdClearAttachments", reinterpret_cast<PFN_vkVoidFunction>(CmdClearAttachments) },
1410 { "vkCmdCopyImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImage) },
1411 { "vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImageToBuffer) },
1412 { "vkCmdCopyBufferToImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBufferToImage) },
1413 { "vkCmdBlitImage", reinterpret_cast<PFN_vkVoidFunction>(CmdBlitImage) },
1414 { "vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(CmdPipelineBarrier) },
1415 { "vkCmdResolveImage", reinterpret_cast<PFN_vkVoidFunction>(CmdResolveImage) },
1416 { "vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(GetImageSubresourceLayout) },
1417 };
1418
1419 for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) {
1420 if (!strcmp(core_device_commands[i].name, name))
1421 return core_device_commands[i].proc;
1422 }
1423
1424 return nullptr;
1425}
1426
Chia-I Wuaacb0fc2016-04-28 11:27:46 +08001427} // namespace image
1428
1429// vk_layer_logging.h expects these to be defined
1430
1431VKAPI_ATTR VkResult VKAPI_CALL
1432vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
1433 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Chia-I Wu4935c762016-04-28 14:01:30 +08001434 return image::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Chia-I Wuaacb0fc2016-04-28 11:27:46 +08001435}
1436
1437VKAPI_ATTR void VKAPI_CALL
1438vkDestroyDebugReportCallbackEXT(VkInstance instance,
1439 VkDebugReportCallbackEXT msgCallback,
1440 const VkAllocationCallbacks *pAllocator) {
Chia-I Wu4935c762016-04-28 14:01:30 +08001441 image::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Chia-I Wuaacb0fc2016-04-28 11:27:46 +08001442}
1443
1444VKAPI_ATTR void VKAPI_CALL
1445vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
1446 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Chia-I Wu4935c762016-04-28 14:01:30 +08001447 image::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
Chia-I Wuaacb0fc2016-04-28 11:27:46 +08001448}
1449
Chia-I Wub02600c2016-05-20 07:11:22 +08001450// loader-layer interface v0, just wrappers since there is only a layer
Chia-I Wuaacb0fc2016-04-28 11:27:46 +08001451
Chia-I Wueec9a312016-04-28 11:21:49 +08001452VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1453vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08001454 return image::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
Chia-I Wueec9a312016-04-28 11:21:49 +08001455}
1456
1457VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1458vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08001459 return image::EnumerateInstanceLayerProperties(pCount, pProperties);
Chia-I Wueec9a312016-04-28 11:21:49 +08001460}
1461
1462VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1463vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08001464 // the layer command handles VK_NULL_HANDLE just fine internally
1465 assert(physicalDevice == VK_NULL_HANDLE);
1466 return image::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
Chia-I Wuaacb0fc2016-04-28 11:27:46 +08001467}
1468
1469VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1470 const char *pLayerName, uint32_t *pCount,
1471 VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08001472 // the layer command handles VK_NULL_HANDLE just fine internally
1473 assert(physicalDevice == VK_NULL_HANDLE);
Chia-I Wu3f326222016-04-28 14:21:13 +08001474 return image::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
Chia-I Wuaacb0fc2016-04-28 11:27:46 +08001475}
1476
1477VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
Chia-I Wu4935c762016-04-28 14:01:30 +08001478 return image::GetDeviceProcAddr(dev, funcName);
Chia-I Wuaacb0fc2016-04-28 11:27:46 +08001479}
1480
1481VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wu4935c762016-04-28 14:01:30 +08001482 return image::GetInstanceProcAddr(instance, funcName);
Chia-I Wueec9a312016-04-28 11:21:49 +08001483}